Compare commits

...

84 Commits

Author SHA1 Message Date
James Seibel 42ab9eebe5 Fully move getShade into ClientLevelWrapper 2026-05-31 07:43:28 -05:00
Acuadragon100 49e3e11250 Move getShade into ClientLevelWrapper. 2026-05-31 11:16:05 +02:00
Acuadragon100 10925d7c57 Include both the dimension type name and the dimension id number in the dimension name on 1.12.2. 2026-05-16 14:23:16 +02:00
Acuadragon100 7d918fe8dc Also use the original camera position when Immersive Portals is loaded. 2026-05-16 13:25:19 +02:00
Acuadragon100 938631a379 Merge remote-tracking branch 'root/main' into fix-portals
# Conflicts:
#	coreSubProjects
2026-05-15 16:42:34 +02:00
Acuadragon100 48966bf32a Use the dimension id number as the level key on 1.12.2. 2026-05-15 16:01:58 +02:00
Acuadragon100 2dc38622e2 Fix compile errors with 1.12.2. 2026-05-15 15:16:18 +02:00
James Seibel 36f1c49f49 Add MC Version locking to the config 2026-05-15 07:44:22 -05:00
James Seibel 271f4e8b21 Fix compiling MC 1.16.5+ 2026-05-14 20:52:36 -05:00
James Seibel b164e4646d add 1.12.2 to the build script 2026-05-14 20:13:22 -05:00
James Seibel 14fd5729e2 use ModInfo packet path 2026-05-14 20:11:41 -05:00
James Seibel 7c3e279237 preprocessor cleanup 2026-05-14 20:11:32 -05:00
Acuadragon100 536389af0b Merge remote-tracking branch 'refs/remotes/root/main' into fix-portals
# Conflicts:
#	common/src/main/java/com/seibel/distanthorizons/common/commonMixins/MixinVanillaFogCommon.java
#	common/src/main/java/com/seibel/distanthorizons/common/wrappers/level/KeyedClientLevelManager.java
#	common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftClientWrapper.java
#	common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftRenderWrapper.java
#	common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ClientLevelWrapper.java
#	common/src/main/java/com/seibel/distanthorizons/common/wrappers/world/ServerLevelWrapper.java
#	coreSubProjects
#	forge/src/main/java/com/seibel/distanthorizons/forge/mixins/client/MixinFogRenderer.java
2026-05-14 22:46:23 +02:00
James Seibel 2884094dee refactoring and cleanup 2026-05-14 07:49:32 -05:00
James Seibel 817c268491 Tint color cleanup 2026-05-14 07:11:44 -05:00
Vojtěch Šokala 071a306f14 Preprocessor cleanup 2026-05-14 13:03:32 +02:00
Acuadragon100 7ad0599beb Only tick levels the player is in on the client. 2026-05-14 12:09:02 +02:00
Vojtěch Šokala c97fea6d0a Fix compile of modern 2026-05-14 07:53:00 +02:00
Vojtěch Šokala d94faf828d Preprocessor cleanup + colored beacons for 1.12.2 2026-05-13 23:59:09 +02:00
Vojtěch Šokala 0d6d4b133e Fix compile of modern 2026-05-13 23:58:25 +02:00
Acuadragon100 8234ac60b8 Always return the player's level and position even when a portal is being rendered. 2026-05-13 21:06:43 +02:00
James Seibel 5ab6bfb663 preprocessor cleanup 2026-05-13 07:49:18 -05:00
James Seibel e087dbc878 temp unit test disable 2026-05-12 21:56:30 -05:00
James Seibel 391e96ad3d abstract mod init cleanup 2026-05-12 21:54:03 -05:00
James Seibel fbf812091d MC 1.12.2 refactoring and cleanup 2026-05-12 21:38:07 -05:00
Acuadragon100 31ab738392 Fix Immersive Portals not properly detected on Forge 1.16.5 2026-05-12 21:23:50 +02:00
James Seibel 7448483f84 revert option screen name for consistency 2026-05-12 08:02:26 -05:00
James Seibel e3d6e1bcc6 use vanilla fog common 2026-05-12 07:32:57 -05:00
James Seibel fbbcd1b95b fix forgix running on only a single modloader 2026-05-12 07:28:59 -05:00
James Seibel d8e7325044 minor gradle cleanup 2026-05-12 07:28:45 -05:00
James Seibel f17aeca79c add cleanroom run config 2026-05-12 07:28:37 -05:00
James Seibel ac3a223114 add missing licensing headers 2026-05-12 07:28:25 -05:00
James Seibel e4312c2f8b reformat 1.12.2 version prop 2026-05-12 07:28:11 -05:00
James Seibel 17bde631ac Put back jvmdowngrader 2026-05-12 07:02:04 -05:00
Vojtěch Šokala 578efbf15f Fix compile of 1.21.6+ 2026-05-08 02:19:45 +02:00
Vojtěch Šokala 8b6bb228e3 Put 26.1.2 back in mcVer 2026-05-08 01:17:19 +02:00
Vojtěch Šokala 611c4606d7 Fix 1.12.2 bugs, fill mcmod.info 2026-05-08 01:15:13 +02:00
Vojtěch Šokala 05bdaf0390 Prevent air transforming into water if waterSubSurfaceBlockReplacementCsv contains invalid resource location 2026-05-07 15:39:14 +02:00
Vojtěch Šokala eb8fcaee36 Fix compilation of modern 2026-05-07 15:34:26 +02:00
Vojtěch Šokala 32a71933d6 Bump forge version on 1.20.1, 1.20.4 for Java 26 support 2026-05-07 15:34:01 +02:00
Vojtěch Šokala a4baf9ca0a make cleanroom work in dev 2026-05-07 12:23:01 +02:00
Vojtěch Šokala 72bfd0a2bb fix color resolve for liquid blocks 2026-05-07 03:39:49 +02:00
Vojtěch Šokala 7ae4a9f460 1.12.2 compiles again 2026-05-06 20:51:08 +02:00
Vojtěch Šokala 9bd6fb0105 merge upstream 2026-05-05 10:00:18 +02:00
Acuadragon100 42344e9c31 Fix some compile errors and backport stuff to Forge. 2026-05-03 23:03:25 +02:00
Acuadragon100 904cc4760f Prevent multiple DhClientLevels of the same level from existing at once. 2026-05-03 21:09:43 +02:00
Acuadragon100 297a8dc980 Fix current level unloading on the client. 2026-05-03 21:08:43 +02:00
James Seibel 30eb02f3b7 lightmap move common level code to common 2026-05-02 10:02:08 -05:00
James Seibel 86cda56381 optimize and fix block wrapper duplicate init 2026-05-02 10:01:08 -05:00
James Seibel 35c1bae156 move fog common mixin code to common 2026-05-02 10:00:24 -05:00
James Seibel e1ce3ae200 neo/fabric move lightmap level to core 2026-05-02 09:57:27 -05:00
James Seibel ed16c83271 minor format updating 2026-05-02 09:54:25 -05:00
Acuadragon100 9d9fdd8ddd Added some missing license headers. 2026-04-26 15:10:01 +02:00
Acuadragon100 2711d8dccc More cleanup 2026-04-26 14:53:27 +02:00
Acuadragon100 c8535f13a6 Check if same level before trying to decode the data. 2026-04-26 14:53:23 +02:00
Acuadragon100 b5ba7862a9 Actually, we can re-enable this if we just make sure it applies to the correct level. 2026-04-26 14:53:21 +02:00
Acuadragon100 33e61b7ef0 Fix not unloading client levels on servers. 2026-04-26 14:53:11 +02:00
Acuadragon100 1617ebda9e Disable fading detection on 1.21.6+ for now.
Might be worth revisiting once a proper fork of Immersive Portals appear for newer versions.
2026-04-26 13:51:52 +02:00
Acuadragon100 29042e2ced Cleanup 2026-04-26 13:51:37 +02:00
Acuadragon100 390dda94c6 Fix server loading. 2026-04-26 13:49:36 +02:00
Acuadragon100 6600703d52 Redo loading 2026-04-26 13:45:06 +02:00
Acuadragon100 3a065d1784 Bug fixes and refactoring. 2026-04-26 13:44:25 +02:00
Acuadragon100 0e340e4558 Tweaked portal loading and fix portals not being detected to disable fading until entered at least once. 2026-04-26 13:43:26 +02:00
Acuadragon100 ca550a0a57 Disable fade rendering when immersive portals and sodium are active at once. 2026-04-26 13:41:03 +02:00
Acuadragon100 30143cbbcb 26.1 support 2026-04-26 13:40:31 +02:00
Acuadragon100 81abcbdb86 Move timer out of mixin to fix crash. 2026-04-26 13:40:13 +02:00
Michael Harvey 3080102f06 Address maintainer feedback: single level loading system, TimerUtil cleanup, consistent formatting 2026-04-26 00:49:31 +02:00
Michael Harvey 6316587ebe remove duplicate copy 2026-04-26 00:49:31 +02:00
Michael Harvey 2e1a2367bd add server support for immersive portals 2026-04-26 00:49:31 +02:00
Michael Harvey e65b1e2dfc add immersive portals support 2026-04-26 00:49:31 +02:00
Vojtěch Šokala 9fea29cbb6 Put canvas back 2026-03-17 15:46:00 +01:00
Vojtěch Šokala 7e1e5a56e2 Set back 1.21.11 as default mcVer 2026-03-15 23:41:13 +01:00
Vojtěch Šokala 059293ebe0 Add missing shaders into cleanroom project 2026-03-15 23:31:35 +01:00
Vojtěch Šokala 4f9d4e2a14 Fix compile error 2026-03-15 23:31:13 +01:00
Vojtěch Šokala 6bd3c825c3 Merge branch 'main' of https://gitlab.com/distant-horizons-team/distant-horizons
# Conflicts:
#	common/src/main/java/com/seibel/distanthorizons/common/wrappers/worldGeneration/InternalServerGenerator.java
2026-03-15 23:27:20 +01:00
Vojtěch Šokala c75595a5e2 [1.12.2] implement pregen command 2026-03-15 23:17:12 +01:00
Vojtěch Šokala 266d463873 fix compile errors 2026-03-15 23:14:54 +01:00
Vojtěch Šokala 73c718c676 [1.12.2] improve config gui to match other versions 2026-03-15 22:13:07 +01:00
Vojtěch Šokala 3df5c04759 Fix issue when MC framebuffer is using renderbuffer for depth 2026-03-15 22:10:03 +01:00
Vojtěch Šokala d72c34a926 Merge branch 'main' of https://gitlab.com/distant-horizons-team/distant-horizons
# Conflicts:
#	common/src/main/java/com/seibel/distanthorizons/common/AbstractModInitializer.java
#	common/src/main/java/com/seibel/distanthorizons/common/commands/PregenCommand.java
#	common/src/main/java/com/seibel/distanthorizons/common/render/openGl/GlDhTerrainShaderProgram.java
2026-03-15 15:49:41 +01:00
Vojtěch Šokala 8991338be1 [1.12.2] add support for 3.0.0b 2026-03-15 15:42:08 +01:00
Vojtěch Šokala 6b32ab02d3 Merge branch 'main' of https://gitlab.com/distant-horizons-team/distant-horizons
# Conflicts:
#	common/src/main/java/com/seibel/distanthorizons/common/AbstractModInitializer.java
#	common/src/main/java/com/seibel/distanthorizons/common/wrappers/WrapperFactory.java
#	common/src/main/java/com/seibel/distanthorizons/common/wrappers/block/BlockStateWrapper.java
#	common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftGLWrapper.java
#	common/src/main/java/com/seibel/distanthorizons/common/wrappers/misc/LightMapWrapper.java
2026-03-11 09:42:18 +01:00
Vojtěch Šokala c5adc3f72a 1.12.2 working in dev 2026-03-11 09:20:32 +01:00
Vojtěch Šokala 1d0d67d215 1.12.2 buildscript 2026-02-20 15:00:13 +01:00
141 changed files with 6188 additions and 1033 deletions
+2 -1
View File
@@ -41,7 +41,8 @@ build:
"1.19.4", "1.19.2", "1.19.4", "1.19.2",
"1.18.2", "1.18.2",
"1.17.1", "1.17.1",
"1.16.5" "1.16.5",
"1.12.2"
] ]
script: script:
# this both runs the unit tests and assembles the code # this both runs the unit tests and assembles the code
@@ -0,0 +1,27 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="distant-horizons [cleanroom:runClient]" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="cleanroom:runClient" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<ExternalSystemDebugDisabled>false</ExternalSystemDebugDisabled>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<GradleProfilingDisabled>false</GradleProfilingDisabled>
<GradleCoverageDisabled>false</GradleCoverageDisabled>
<method v="2" />
</configuration>
</component>
+7 -1
View File
@@ -4,10 +4,10 @@ plugins {
} }
forgix { forgix {
autoRun = true
// add the mod loaders to the end of the jar // add the mod loaders to the end of the jar
// put together in the format: "a", "a-b", "a-b-c" // put together in the format: "a", "a-b", "a-b-c"
int loaderCount = 0;
String modLoaders = ""; String modLoaders = "";
((String) gradle.builds_for) ((String) gradle.builds_for)
.split(",") .split(",")
@@ -20,7 +20,13 @@ forgix {
} }
modLoaders += loaderName; modLoaders += loaderName;
loaderCount++;
} }
// run if there are multiple launchers that need merging
autoRun = (loaderCount > 1);
// merged jars are named in the format: // merged jars are named in the format:
// "DistantHorizons-3.0.1-b-dev-26.1-fabric-neoforge.jar" // "DistantHorizons-3.0.1-b-dev-26.1-fabric-neoforge.jar"
archiveClassifier = modLoaders archiveClassifier = modLoaders
+98 -26
View File
@@ -6,6 +6,7 @@ import org.apache.tools.zip.ZipOutputStream
import javax.annotation.Nonnull import javax.annotation.Nonnull
import java.util.function.Function import java.util.function.Function
import java.util.function.Predicate import java.util.function.Predicate
import groovy.json.JsonSlurper
// Convention plugin for all MC-facing subprojects (common + loaders). // Convention plugin for all MC-facing subprojects (common + loaders).
// Common uses this directly; loaders use it via unimined-fabric/forge/neoforge. // Common uses this directly; loaders use it via unimined-fabric/forge/neoforge.
@@ -23,6 +24,9 @@ plugins {
def isNotCommonProject = project.name != "common" def isNotCommonProject = project.name != "common"
if (isNotCommonProject) {
evaluationDependsOn(":common")
}
// ==================== Version Properties ==================== // ==================== Version Properties ====================
@@ -121,6 +125,15 @@ if (isNotCommonProject) {
'Multi-Release': true, 'Multi-Release': true,
'Main-Class': 'com.seibel.distanthorizons.core.jar.JarMain', 'Main-Class': 'com.seibel.distanthorizons.core.jar.JarMain',
) )
if (project.name == "cleanroom") {
attributes(
'ModType': 'CRL',
'MixinConfigs': "${mod_id}.default.mixin.json,${mod_id}.mod.mixin.json",
'FMLCorePlugin': 'com.seibel.distanthorizons.cleanroom.DistantHorizonsLoadingPlugin',
'FMLCorePluginContainsFMLMod': true,
'FMLAT': "src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons_at.cfg"
)
}
} }
} }
} }
@@ -133,8 +146,14 @@ unimined.minecraft(sourceSets.main, true) {
if (gradle.ext.minecraft_version.startsWith("1.")) { // 26.1+ doesn't use obfuscation if (gradle.ext.minecraft_version.startsWith("1.")) { // 26.1+ doesn't use obfuscation
mappings { mappings {
mojmap() if(gradle.ext.minecraft_version.startsWith("1.12.2")){
devNamespace "mojmap" mcp("stable", "39-1.12")
}
else{
mojmap()
devNamespace "mojmap"
}
} }
} }
} }
@@ -165,18 +184,22 @@ if (isNotCommonProject) {
source(project(":common").sourceSets.main.allSource) source(project(":common").sourceSets.main.allSource)
} }
} else { } else {
// Common: fabric for compilation + access widener, no jar remapping or runs
unimined.minecraft { unimined.minecraft {
fabric { if (gradle.ext.minecraft_version.equals("1.12.2")) {
loader gradle.ext.fabric_loader_version cleanroom {
accessWidener project.file("src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons.accesswidener") loader gradle.ext.cleanroom_loader_version
}
} else {
fabric {
loader gradle.ext.fabric_loader_version
accessWidener project.file("src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons.accesswidener")
}
} }
defaultRemapJar = false defaultRemapJar = false
runs.off = true runs.off = true
} }
} }
// ==================== Configurations ==================== // ==================== Configurations ====================
evaluationDependsOn(":core") evaluationDependsOn(":core")
@@ -346,12 +369,25 @@ if (isNotCommonProject) {
def loaderPaths = configurations.minecraftLibraries.resolve().collect { it.path }.toSet() def loaderPaths = configurations.minecraftLibraries.resolve().collect { it.path }.toSet()
tasks.withType(JavaExec).configureEach { runTask -> tasks.withType(JavaExec).configureEach { runTask ->
dependsOn(shadowJar) dependsOn(shadowJar)
classpath = files(shadowJar.archiveFile) + classpath.filter { file -> if (project.name != "cleanroom") {
!file.path.contains(project.buildDir.path) && classpath = files(shadowJar.archiveFile) + classpath.filter { file ->
!file.path.contains("core${File.separator}build") && file != shadowJar.archiveFile.get().asFile &&
!file.path.contains("api${File.separator}build") && !file.path.contains(project.buildDir.path) &&
!file.path.contains("common${File.separator}build") && !file.path.contains("core${File.separator}build") &&
!(shadowedPaths.contains(file.path) && !loaderPaths.contains(file.path)) !file.path.contains("api${File.separator}build") &&
!file.path.contains("common${File.separator}build") &&
!(shadowedPaths.contains(file.path) && !loaderPaths.contains(file.path))
}
} else {
// For cleanroom, don't put shadow jar on app classpath.
// crl.dev.extrapath loads it via LaunchClassLoader instead.
classpath = classpath.filter { file ->
!file.path.contains(project.buildDir.path) &&
!file.path.contains("core${File.separator}build") &&
!file.path.contains("api${File.separator}build") &&
!file.path.contains("common${File.separator}build") &&
!(shadowedPaths.contains(file.path) && !loaderPaths.contains(file.path))
}
} }
// Shared run directory so all loaders use the same worlds // Shared run directory so all loaders use the same worlds
@@ -367,20 +403,28 @@ if (isNotCommonProject) {
} }
runTask.jvmArgs = filteredArgs runTask.jvmArgs = filteredArgs
// fix (Neo)forge debug running if(project.name == "forge"
doFirst { || project.name == "neoforge"
def modsDir = rootProject.file("run/${isClient ? 'client' : 'server'}/mods") || project.name == "cleanroom")
modsDir.mkdirs() {
// fix (Neo)forge, Cleanroom debug running
doFirst {
def modsDir = rootProject.file("run/${isClient ? 'client' : 'server'}/mods")
modsDir.mkdirs()
// Remove any stale DH jars before copying the fresh one // Remove any stale DH jars before copying the fresh one
modsDir.listFiles()?.each { file -> modsDir.listFiles()?.each({ file ->
if (file.name.startsWith(rootProject.mod_name)) file.delete() if (file.name.startsWith(rootProject.mod_name))
} {
file.delete()
}
});
// Copy shadow jar into mods folder so (Neo)Forge discovers it properly // Copy shadow jar into mods folder so (Neo)Forge discovers it properly
copy { copy {
from shadowJar.archiveFile from shadowJar.archiveFile
into modsDir into modsDir
}
} }
} }
@@ -418,6 +462,10 @@ if (isNotCommonProject) {
} }
} }
tasks.downgradeJar.inputFile.set(tasks.named("remapJar").flatMap { it.archiveFile })
tasks.jar.finalizedBy(tasks.named("remapJar"))
tasks.named("remapJar").configure { finalizedBy(tasks.shadeDowngradedApi) }
} }
} }
@@ -429,6 +477,7 @@ if (isNotCommonProject) {
def resourceTargets = [ def resourceTargets = [
"build_info.json", "build_info.json",
"fabric.mod.json", "fabric.mod.json",
"mcmod.info",
"quilt.mod.json", "quilt.mod.json",
"META-INF/mods.toml", "META-INF/mods.toml",
"META-INF/neoforge.mods.toml", "META-INF/neoforge.mods.toml",
@@ -439,6 +488,7 @@ if (isNotCommonProject) {
// Quilt contributors // Quilt contributors
def quilt_contributors = [] def quilt_contributors = []
def mod_author_list = rootProject.mod_authors.replaceAll("\"", "").replace("[", "").replace("]", "").split(",") def mod_author_list = rootProject.mod_authors.replaceAll("\"", "").replace("[", "").replace("]", "").split(",")
def cleanroom_author_list = rootProject.mod_authors.replace('[', '').replace(']', '').split(',').collect({ it.trim().replace('"', '') }).join('", "')
for (dev in mod_author_list) { for (dev in mod_author_list) {
quilt_contributors.push("\"${dev.strip()}\": \"Developer\"") quilt_contributors.push("\"${dev.strip()}\": \"Developer\"")
} }
@@ -456,9 +506,11 @@ if (isNotCommonProject) {
def replaceProperties = [ def replaceProperties = [
version : rootProject.mod_version, version : rootProject.mod_version,
mod_id : rootProject.mod_id,
mod_name : rootProject.mod_readable_name, mod_name : rootProject.mod_readable_name,
group : rootProject.maven_group, group : rootProject.maven_group,
authors : rootProject.mod_authors, authors : rootProject.mod_authors,
cleanroom_authors : cleanroom_author_list,
description : rootProject.mod_description, description : rootProject.mod_description,
homepage : rootProject.mod_homepage, homepage : rootProject.mod_homepage,
source : rootProject.mod_source, source : rootProject.mod_source,
@@ -476,6 +528,7 @@ if (isNotCommonProject) {
fabric_incompatibility_list : rootProject.fabric_incompatibility_list, fabric_incompatibility_list : rootProject.fabric_incompatibility_list,
fabric_recommend_list : rootProject.fabric_recommend_list, fabric_recommend_list : rootProject.fabric_recommend_list,
neoforge_version_range : rootProject.neoforge_version_range, neoforge_version_range : rootProject.neoforge_version_range,
logo_path : "assets/distanthorizons/icon.png"
] ]
inputs.properties replaceProperties inputs.properties replaceProperties
@@ -486,7 +539,7 @@ if (isNotCommonProject) {
// Remove unused access wideners // Remove unused access wideners
exclude { file -> exclude { file ->
if (file.name.contains(".distanthorizons.accesswidener") && file.name != "${rootProject.accessWidenerVersion}.distanthorizons.accesswidener") { if ((file.name.contains(".distanthorizons.accesswidener") && file.name != "${rootProject.accessWidenerVersion}.distanthorizons.accesswidener")) {
return true return true
} }
return false return false
@@ -506,6 +559,25 @@ if (isNotCommonProject) {
from fileTree(project(":core").file("src/main/resources")) from fileTree(project(":core").file("src/main/resources"))
into project.file("build/resources/main") into project.file("build/resources/main")
} }
tasks.register("convertJsonToLang") {
dependsOn(copyCoreResources)
File input = project.file("build/resources/main/assets/distanthorizons/lang/en_us.json")
File output = project.file("build/resources/main/assets/distanthorizons/lang/en_us.lang")
inputs.file(input)
outputs.file(output)
doLast {
output.withWriter("UTF-8") { writer ->
writer.writeLine("#PARSE_ESCAPES")
new JsonSlurper()
.parse(input)
.each { key, value ->
writer.writeLine("${key}=${value.toString().replace("%", "%%").replace("\n", "\\n")}")
}
}
}
}
// ==================== JVMDowngrader ==================== // ==================== JVMDowngrader ====================
@@ -0,0 +1,15 @@
plugins {
id 'dh-loader'
}
unimined.minecraft {
cleanroom {
loader gradle.ext.cleanroom_loader_version
useToolchains = false
accessTransformer project(":common").file("src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons_at.cfg")
runs.all {
systemProperty("crl.dev.mixin", "${mod_id}.default.mixin.json,${mod_id}.mod.mixin.json")
systemProperty("fml.coreMods.load", "com.seibel.distanthorizons.cleanroom.DistantHorizonsLoadingPlugin")
}
}
}
+48
View File
@@ -0,0 +1,48 @@
plugins {
id 'unimined-cleanroom'
}
// ==================== Mod Dependency Helper ====================
def addMod(path, enabled) {
if (enabled == "2")
dependencies { modImplementation(path) }
else if (enabled == "1")
dependencies { compileOnly(path) }
}
// ==================== Dependencies ====================
dependencies {
}
// ==================== Tasks ====================
task deleteResources(type: Delete) {
delete file("build/resources/main")
}
processResources {
rename '(.+_at.cfg)', 'META-INF/$1'
dependsOn(copyCoreResources)
dependsOn(convertJsonToLang)
// dependsOn(copyCommonLoaderResources)
}
tasks.named('runClient') {
dependsOn(copyCoreResources)
// dependsOn(copyCommonLoaderResources)
finalizedBy(deleteResources)
}
sourcesJar {
def commonSources = project(":common").sourcesJar
dependsOn commonSources
from commonSources.archiveFile.map { zipTree(it) }
}
@@ -0,0 +1,214 @@
/*
* 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.cleanroom;
import com.seibel.distanthorizons.common.AbstractModInitializer;
import com.seibel.distanthorizons.common.util.ProxyUtil;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
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.ServerApi;
import com.seibel.distanthorizons.core.api.internal.SharedApi;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
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;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.InputEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL32;
import java.util.concurrent.AbstractExecutorService;
public class CleanroomClientProxy implements AbstractModInitializer.IEventProxy
{
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private static final CleanroomPluginPacketSender PACKET_SENDER = (CleanroomPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
private static World GetEventLevel(WorldEvent e) { return e.getWorld(); }
@Override
public void registerEvents()
{
MinecraftForge.EVENT_BUS.register(this);
MinecraftForge.EVENT_BUS.register(FMLCommonHandler.instance());
CleanroomPluginPacketSender.setPacketHandler(ClientApi.INSTANCE::pluginMessageReceived);
}
//==============//
// chunk events //
//==============//
//region
@SubscribeEvent
public void rightClickBlockEvent(PlayerInteractEvent.RightClickBlock event)
{
if (MC.clientConnectedToDedicatedServer())
{
World level = event.getWorld();
ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(level);
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(wrappedLevel, event.getPos().getX(), event.getPos().getZ()))
{
return;
}
AbstractExecutorService executor = ThreadPoolUtil.getFileHandlerExecutor();
if (executor != null)
{
executor.execute(() ->
{
Chunk chunk = level.getChunk(event.getPos());
SharedApi.INSTANCE.applyChunkUpdate(new ChunkWrapper(chunk, wrappedLevel), wrappedLevel);
});
}
}
}
@SubscribeEvent
public void leftClickBlockEvent(PlayerInteractEvent.LeftClickBlock event)
{
if (MC.clientConnectedToDedicatedServer())
{
World level = event.getWorld();
ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(level);
if (SharedApi.isChunkAtBlockPosAlreadyUpdating(wrappedLevel, event.getPos().getX(), event.getPos().getZ()))
{
return;
}
AbstractExecutorService executor = ThreadPoolUtil.getFileHandlerExecutor();
if (executor != null)
{
executor.execute(() ->
{
Chunk chunk = level.getChunk(event.getPos());
SharedApi.INSTANCE.applyChunkUpdate(new ChunkWrapper(chunk, wrappedLevel), wrappedLevel);
});
}
}
}
@SubscribeEvent
public void clientChunkLoadEvent(ChunkEvent.Load event)
{
if (MC.clientConnectedToDedicatedServer())
{
ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(GetEventLevel(event));
IChunkWrapper chunkWrapper = new ChunkWrapper(event.getChunk(), wrappedLevel);
SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, wrappedLevel);
}
}
//endregion
//==============//
// key bindings //
//==============//
//region
@SubscribeEvent
public void registerKeyBindings(InputEvent.KeyInputEvent event)
{
/* if (Minecraft.getMinecraft().player == null)
{
return;
}
if (event.getAction() != GLFW.GLFW_PRESS)
{
return;
}
ClientApi.INSTANCE.keyPressedEvent(event.getKey());*/
}
//endregion
//===========//
// rendering //
//===========//
//region
@SubscribeEvent
public void afterLevelRenderEvent(TickEvent.RenderTickEvent event)
{
if (event.type.equals(TickEvent.RenderTickEvent.Type.RENDER))
{
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);
}
}
}
@SubscribeEvent
public void onRenderOverlay(RenderGameOverlayEvent.Text event)
{
Minecraft mc = Minecraft.getMinecraft();
if (event.isCanceled()
|| !mc.gameSettings.showDebugInfo)
{
return;
}
F3Screen.addStringToDisplay(event.getRight());
}
//endregion
}
@@ -0,0 +1,147 @@
/*
* 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.cleanroom;
import com.seibel.distanthorizons.cleanroom.modAccessor.ModChecker;
import com.seibel.distanthorizons.common.AbstractModInitializer;
import com.seibel.distanthorizons.common.commands.CommandInitializer;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.InternalServerGenerator;
import com.seibel.distanthorizons.core.api.internal.ServerApi;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
import com.seibel.distanthorizons.coreapi.ModInfo;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.*;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator;
import java.util.List;
import java.util.function.Consumer;
/**
* Initialize and setup the Mod. <br>
* If you are looking for the real start of the mod
* check out the ClientProxy.
*/
@Mod(modid = ModInfo.ID, name = ModInfo.NAME, version = ModInfo.VERSION)
public class CleanroomMain extends AbstractModInitializer
{
@Mod.Instance
public static CleanroomMain instance;
@Mod.EventHandler
public void preinit(FMLPreInitializationEvent event)
{
Configurator.setLevel("org.sqlite", Level.INFO);
ForgeChunkManager.setForcedChunkLoadingCallback(CleanroomMain.instance, (tickets, world) -> { });
}
@Mod.EventHandler
public void init(FMLInitializationEvent event)
{
if (FMLCommonHandler.instance().getEffectiveSide().isClient())
{
this.onInitializeClient();
}
else
{
this.onInitializeServer();
}
}
@Override
protected void createInitialSharedBindings()
{
SingletonInjector.INSTANCE.bind(IModChecker.class, ModChecker.INSTANCE);
SingletonInjector.INSTANCE.bind(IPluginPacketSender.class, new CleanroomPluginPacketSender());
}
@Override
protected void createInitialClientBindings() { /* no additional setup needed currently */ }
@Override
protected IEventProxy createClientProxy() { return new CleanroomClientProxy(); }
@Override
protected IEventProxy createServerProxy(boolean isDedicated) { return new CleanroomServerProxy(isDedicated); }
@Override
protected void initializeModCompat()
{
}
/* @Override
protected void subscribeRegisterCommandsEvent(Consumer<CommandDispatcher<CommandSourceStack>> eventHandler)
{ MinecraftForge.EVENT_BUS.addListener((RegisterCommandsEvent e) -> { eventHandler.accept(e.getDispatcher()); }); }*/
@Override
protected void subscribeClientStartedEvent(Runnable eventHandler)
{
// Just run the event handler, since there are no proper ClientLifecycleEvent for the client
// to signify readiness other than FmlClientSetupEvent
eventHandler.run();
}
@Mod.EventHandler
public void onServerStarting(FMLServerStartingEvent event)
{
event.registerServerCommand(CommandInitializer.initCommands());
}
@Mod.EventHandler
public void onServerAboutToStart(FMLServerAboutToStartEvent event)
{
if (eventHandlerStartServer != null)
{
eventHandlerStartServer.accept(event.getServer());
}
}
Consumer<MinecraftServer> eventHandlerStartServer;
@Override
protected void subscribeServerStartingEvent(Consumer<MinecraftServer> eventHandler)
{
eventHandlerStartServer = eventHandler;
}
@Override
protected void runDelayedSetup() { SingletonInjector.INSTANCE.runDelayedSetup(); }
// ServerWorldLoadEvent
@Mod.EventHandler
public void dedicatedWorldLoadEvent(FMLServerAboutToStartEvent event)
{
ServerApi.INSTANCE.serverLoadEvent(event.getServer().isDedicatedServer());
}
// ServerWorldUnloadEvent
@Mod.EventHandler
public void serverWorldUnloadEvent(FMLServerStoppingEvent event)
{
ServerApi.INSTANCE.serverUnloadEvent();
}
}
@@ -0,0 +1,136 @@
/*
* 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.cleanroom;
import com.seibel.distanthorizons.common.AbstractPluginPacketSender;
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
import com.seibel.distanthorizons.core.network.messages.MessageRegistry;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
import net.minecraftforge.fml.relauncher.Side;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class CleanroomPluginPacketSender extends AbstractPluginPacketSender
{
public static final SimpleNetworkWrapper PLUGIN_CHANNEL =
NetworkRegistry.INSTANCE.newSimpleChannel(
AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE
);
public static void setPacketHandler(Consumer<AbstractNetworkMessage> consumer)
{ setPacketHandler((player, message) -> consumer.accept(message)); }
static BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> consumerPacket;
public static void setPacketHandler(BiConsumer<IServerPlayerWrapper, AbstractNetworkMessage> consumer)
{
PLUGIN_CHANNEL.registerMessage(MessageWrapper.Handler.class, MessageWrapper.class, 0, Side.CLIENT);
PLUGIN_CHANNEL.registerMessage(MessageWrapper.Handler.class, MessageWrapper.class, 0, Side.SERVER);
consumerPacket = consumer;
}
@Override
public void sendToServer(AbstractNetworkMessage message)
{ PLUGIN_CHANNEL.sendToServer(new MessageWrapper(message)); }
@Override
public void sendToClient(EntityPlayerMP serverPlayer, AbstractNetworkMessage message)
{ PLUGIN_CHANNEL.sendTo(new MessageWrapper(message), serverPlayer); }
//================//
// helper classes //
//================//
//region
// Forge doesn't support using abstract classes
@SuppressWarnings({"ClassCanBeRecord", "RedundantSuppression"})
public static class MessageWrapper implements IMessage
{
public AbstractNetworkMessage message;
//=============//
// constructor //
//=============//
//region
public MessageWrapper(AbstractNetworkMessage message) { this.message = message; }
public MessageWrapper()
{
// For reflection
}
//endregion
@Override
public void fromBytes(ByteBuf buf)
{
int messageId = buf.readByte();
message = MessageRegistry.INSTANCE.createMessage(messageId);
message.decode(buf);
}
@Override
public void toBytes(ByteBuf buf)
{
buf.writeByte(MessageRegistry.INSTANCE.getMessageId(message));
message.encode(buf);
}
public static class Handler implements IMessageHandler<MessageWrapper, IMessage>
{
@Override
public IMessage onMessage(MessageWrapper wrapper, MessageContext context)
{
if (wrapper.message != null)
{
if (context.side == Side.SERVER)
{
consumerPacket.accept(ServerPlayerWrapper.getWrapper(context.getServerHandler().player), wrapper.message);
}
else
{
consumerPacket.accept(null, wrapper.message);
}
}
return null; // No response needed
}
}
}
//endregion
}
@@ -0,0 +1,181 @@
/*
* 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.cleanroom;
import com.seibel.distanthorizons.common.AbstractModInitializer;
import com.seibel.distanthorizons.common.commands.CommandInitializer;
import com.seibel.distanthorizons.common.commonMixins.MixinChunkMapCommon;
import com.seibel.distanthorizons.common.util.ProxyUtil;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.InternalServerGenerator;
import com.seibel.distanthorizons.core.api.internal.ServerApi;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
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.entity.player.EntityPlayerMP;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.world.ChunkDataEvent;
import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLServerAboutToStartEvent;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
import java.lang.reflect.Field;
import static com.seibel.distanthorizons.cleanroom.CleanroomMain.instance;
public class CleanroomServerProxy implements AbstractModInitializer.IEventProxy
{
private static final CleanroomPluginPacketSender PACKET_SENDER = (CleanroomPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
private static World GetEventLevel(WorldEvent e) { return e.getWorld(); }
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
private final ServerApi serverApi = ServerApi.INSTANCE;
private final boolean isDedicated;
@Override
public void registerEvents()
{
MinecraftForge.EVENT_BUS.register(this);
FMLCommonHandler.instance().bus().register(this);
if (this.isDedicated)
{
PACKET_SENDER.setPacketHandler(ServerApi.INSTANCE::pluginMessageReceived);
}
}
//=============//
// constructor //
//=============//
//region
public CleanroomServerProxy(boolean isDedicated) { this.isDedicated = isDedicated; }
//endregion
//========//
// events //
//========//
//region
// ServerLevelLoadEvent
@SubscribeEvent
public void serverLevelLoadEvent(WorldEvent.Load event)
{
if (GetEventLevel(event) instanceof WorldServer)
{
this.serverApi.serverLevelLoadEvent(getServerLevelWrapper((WorldServer) GetEventLevel(event)));
}
}
// ServerLevelUnloadEvent
@SubscribeEvent
public void serverLevelUnloadEvent(WorldEvent.Unload event)
{
if (GetEventLevel(event) instanceof WorldServer)
{
this.serverApi.serverLevelUnloadEvent(getServerLevelWrapper((WorldServer) GetEventLevel(event)));
}
}
@SubscribeEvent
public void serverChunkLoadEvent(ChunkEvent.Load event)
{
ILevelWrapper levelWrapper = ProxyUtil.getLevelWrapper(GetEventLevel(event));
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), levelWrapper);
this.serverApi.serverChunkLoadEvent(chunk, levelWrapper);
}
@SubscribeEvent
public void serverChunkSaveEvent(ChunkDataEvent.Save event)
{
if (event.getWorld() instanceof WorldServer worldServer)
{
MixinChunkMapCommon.onChunkSave(worldServer, event.getChunk());
}
}
@SubscribeEvent
public void playerLoggedInEvent(PlayerEvent.PlayerLoggedInEvent event)
{ this.serverApi.serverPlayerJoinEvent(getServerPlayerWrapper(event)); }
@SubscribeEvent
public void playerLoggedOutEvent(PlayerEvent.PlayerLoggedOutEvent event)
{ this.serverApi.serverPlayerDisconnectEvent(getServerPlayerWrapper(event)); }
@SubscribeEvent
public void playerChangedDimensionEvent(PlayerEvent.PlayerChangedDimensionEvent event)
{
this.serverApi.serverPlayerLevelChangeEvent(
getServerPlayerWrapper(event),
getServerLevelWrapper(event.fromDim, event),
getServerLevelWrapper(event.toDim, event)
);
}
//endregion
//================//
// helper methods //
//================//
//region
private static ServerLevelWrapper getServerLevelWrapper(WorldServer level) { return ServerLevelWrapper.getWrapper(level); }
private static ServerLevelWrapper getServerLevelWrapper(int dimensionId, PlayerEvent event)
{
MinecraftServer server = event.player.getServer();
if (server == null)
{
LOGGER.error("getServerLevelWrapper: server is null for player {}", event.player.getName());
return null;
}
return getServerLevelWrapper(server.getWorld(dimensionId));
}
private static ServerPlayerWrapper getServerPlayerWrapper(PlayerEvent event)
{ return ServerPlayerWrapper.getWrapper((EntityPlayerMP) event.player); }
//endregion
}
@@ -0,0 +1,56 @@
/*
* 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.cleanroom;
import net.minecraftforge.fml.common.Loader;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.objectweb.asm.tree.ClassNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import java.util.List;
import java.util.Set;
public class DistantHorizonsConfigPlugin implements IMixinConfigPlugin
{
private static final Logger LOGGER = LogManager.getLogger();
@Override
public void onLoad(String mixinPackage)
{ }
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName)
{
/* return switch (mixinClassName.split("\\.")[5]) {
case "mist" -> Loader.isModLoaded("mist");
default -> true;
};*/
return true;
}
@Override public String getRefMapperConfig() { return null; }
@Override public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) { }
@Override public List<String> getMixins() { return null; }
@Override public void preApply(String targetClassName, ClassNode classNode, String mixinClassName, IMixinInfo mixinInfo) { }
@Override public void postApply(String targetClassName, ClassNode classNode, String mixinClassName, IMixinInfo mixinInfo) { }
}
@@ -0,0 +1,52 @@
/*
* 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.cleanroom;
import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
public class DistantHorizonsLoadingPlugin implements IFMLLoadingPlugin
{
@Override
public @Nullable String[] getASMTransformerClass()
{
return new String[0];
}
@Override
public @Nullable String getModContainerClass()
{
return null;
}
@Override
public @Nullable String getSetupClass()
{
return null;
}
@Override
public void injectData(Map<String, Object> data) { }
@Override
public @Nullable String getAccessTransformerClass()
{
return null;
}
}
@@ -0,0 +1,82 @@
/*
* 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.cleanroom.mixins.client;
import com.seibel.distanthorizons.common.commonMixins.MixinVanillaFogCommon;
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.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.EntityRenderer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.texture.DynamicTexture;
import net.minecraft.init.MobEffects;
import org.apache.logging.log4j.Logger;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(EntityRenderer.class)
public class MixinEntityRenderer
{
@Shadow
@Final
private DynamicTexture lightmapTexture;
@Shadow @Final private Minecraft mc;
@Shadow @Final private static Logger LOGGER;
private static final float A_REALLY_REALLY_BIG_VALUE = 420694206942069.F;
private static final float A_EVEN_LARGER_VALUE = 42069420694206942069.F;
@Inject(at = @At("TAIL"), method = "updateLightmap")
public void onUpdateLightmap(float patrialTicks, CallbackInfo ci)
{
IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
if (mc == null || mc.getWrappedClientLevel() == null)
{
return;
}
MinecraftRenderWrapper renderWrapper = (MinecraftRenderWrapper)SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
renderWrapper.setLightmapId(lightmapTexture.getGlTextureId());
}
@Inject(at = @At("RETURN"), method = "setupFog")
private void disableSetupFog(int startCoords, float partialTicks, CallbackInfo ci)
{
boolean cancelFog = MixinVanillaFogCommon.cancelFog(startCoords, mc);
if (cancelFog)
{
GlStateManager.setFogStart(A_REALLY_REALLY_BIG_VALUE);
GlStateManager.setFogEnd(A_EVEN_LARGER_VALUE);
ClientApi.RENDER_STATE.vanillaFogEnabled = false;
}
else
{
ClientApi.RENDER_STATE.vanillaFogEnabled = true;
}
}
}
@@ -0,0 +1,46 @@
/*
* 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.cleanroom.mixins.client;
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.network.play.server.SPacketJoinGame;
import net.minecraft.util.text.ITextComponent;
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(NetHandlerPlayClient.class)
public class MixinNetHandlerPlayClient
{
@Inject(method = "handleJoinGame", at = @At("RETURN"))
private void onHandleJoinGameEnd(SPacketJoinGame packet, CallbackInfo ci)
{
ClientApi.INSTANCE.onClientOnlyConnected();
}
@Inject(method = "onDisconnect", at = @At("RETURN"))
private void onDisconnect(ITextComponent reason, CallbackInfo ci)
{
ClientApi.INSTANCE.onClientOnlyDisconnected();
}
}
@@ -0,0 +1,83 @@
/*
* 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.cleanroom.mixins.client;
import com.seibel.distanthorizons.common.wrappers.gui.GetConfigScreen;
import com.seibel.distanthorizons.common.wrappers.gui.TexturedButtonWidget;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.coreapi.ModInfo;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiOptions;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.util.ResourceLocation;
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;
/**
* Adds a button to the menu to goto the config
*
* @author coolGi
* @version 12-02-2021
*/
@Mixin(GuiOptions.class)
public class MixinOptionsScreen extends GuiScreen
{
// Get the texture for the button
@Unique private static final ResourceLocation ICON_TEXTURE = new ResourceLocation(ModInfo.ID, "textures/gui/button.png");
@Unique private static final int button_id = 99;
@Inject(at = @At("HEAD"), method = "initGui")
private void lodconfig$init(CallbackInfo ci)
{
if (Config.Client.showDhOptionsButtonInMinecraftUi.get())
this.buttonList.add(
(new TexturedButtonWidget(
button_id,
// Where the button is on the screen
this.width / 2 - 180, this.height / 6 - 12,
// Width and height of the button
20, 20,
// Offset
0, 0,
// Some textuary stuff
20, ICON_TEXTURE, 20, 40,
// Create the button and tell it where to go
// For now it goes to the client option by default
// Add a title to the button
ModInfo.ID + ".title")));
}
@Inject(at = @At("HEAD"), method = "actionPerformed", cancellable = true)
private void lodconfig$actionPerformed(GuiButton button, CallbackInfo ci)
{
if (button.id == button_id)
{
Minecraft.getMinecraft().displayGuiScreen(GetConfigScreen.getScreen(this));
ci.cancel();
}
}
}
@@ -0,0 +1,81 @@
/*
* 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.cleanroom.mixins.client;
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import com.seibel.distanthorizons.core.util.math.Mat4f;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.entity.Entity;
import net.minecraft.util.BlockRenderLayer;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(RenderGlobal.class)
public class MixinRenderGlobal
{
@Shadow private WorldClient world;
@Inject(method = "renderBlockLayer(Lnet/minecraft/util/BlockRenderLayer;DILnet/minecraft/entity/Entity;)I", at = @At("HEAD"))
private void renderChunkLayer(BlockRenderLayer blockLayerIn, double partialTicks, int pass, Entity entityIn, CallbackInfoReturnable<Integer> cir)
{
if (blockLayerIn == BlockRenderLayer.SOLID)
{
float[] mcProjMatrixRaw = new float[16];
GL11.glGetFloatv(GL11.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
ClientApi.RENDER_STATE.mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
ClientApi.RENDER_STATE.mcProjectionMatrix.transpose();
float[] mcModelViewRaw = new float[16];
GL11.glGetFloatv(GL11.GL_MODELVIEW_MATRIX, mcModelViewRaw);
ClientApi.RENDER_STATE.mcModelViewMatrix = new Mat4f(mcModelViewRaw);
ClientApi.RENDER_STATE.mcModelViewMatrix.transpose();
ClientApi.RENDER_STATE.partialTickTime = (float) partialTicks;
ClientApi.RENDER_STATE.clientLevelWrapper = ClientLevelWrapper.getWrapperIfDifferent(ClientApi.RENDER_STATE.clientLevelWrapper, this.world);
int blendSrc = GL11.glGetInteger(GL11.GL_BLEND_SRC);
int blendDst = GL11.glGetInteger(GL11.GL_BLEND_DST);
int boundTexture = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
ClientApi.INSTANCE.renderLods();
GL30.glBindVertexArray(0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
GL20.glUseProgram(0);
//Restore vanilla states
GlStateManager.depthFunc(GL11.GL_LEQUAL);
GlStateManager.bindTexture(boundTexture);
GlStateManager.tryBlendFuncSeparate(blendSrc, blendDst, GL11.GL_ONE, GL11.GL_ZERO);
}
}
}
@@ -0,0 +1,66 @@
/*
* 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.cleanroom.mixins.server;
import com.seibel.distanthorizons.common.wrappers.misc.IMixinServerPlayer;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.util.ITeleporter;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(EntityPlayerMP.class)
public abstract class MixinEntityPlayerMP implements IMixinServerPlayer
{
@Shadow
@Final
public MinecraftServer server;
@Unique
@Nullable
private volatile WorldServer distantHorizons$dimensionChangeDestination;
@Override
@Nullable
public WorldServer distantHorizons$getDimensionChangeDestination()
{ return this.distantHorizons$dimensionChangeDestination; }
@Inject(at = @At("HEAD"), method = "changeDimension(ILnet/minecraftforge/common/util/ITeleporter;)Lnet/minecraft/entity/Entity;")
public void setDimensionChangeDestination(int destinationDimensionID, ITeleporter teleporter, CallbackInfoReturnable<Entity> cir)
{ this.distantHorizons$dimensionChangeDestination = this.server.getWorld(destinationDimensionID); }
@Inject(at = @At("RETURN"), method = "clearInvulnerableDimensionChange")
public void clearDimensionChangeDestination(CallbackInfo ci)
{ this.distantHorizons$dimensionChangeDestination = null; }
}
@@ -0,0 +1,52 @@
/*
* 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.cleanroom.modAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.ModContainer;
import java.io.File;
import java.util.Optional;
import java.util.stream.Stream;
public class ModChecker implements IModChecker
{
public static final ModChecker INSTANCE = new ModChecker();
@Override
public boolean isModLoaded(String modid)
{
return Loader.isModLoaded(modid);
}
@Override
public File modLocation(String modid)
{
Stream<ModContainer> foundStream = Loader.instance().getModList().stream().filter(x -> x.getModId().equals(modid));
Optional<ModContainer> container = foundStream.findFirst();
if (!container.isPresent())
{
throw new RuntimeException("Mod not found: " + modid);
}
return container.get().getSource();
}
}
@@ -0,0 +1,17 @@
{
"required": true,
"package": "com.seibel.distanthorizons.cleanroom.mixins",
"compatibilityLevel": "JAVA_8",
"target": "@env(DEFAULT)",
"mixins": [],
"minVersion": "0.8.7",
"server": [
"server.MixinEntityPlayerMP"
],
"client": [
"client.MixinEntityRenderer",
"client.MixinNetHandlerPlayClient",
"client.MixinOptionsScreen",
"client.MixinRenderGlobal"
]
}
@@ -0,0 +1,11 @@
{
"required": false,
"package": "com.seibel.distanthorizons.cleanroom.mixins.mod",
"compatibilityLevel": "JAVA_8",
"target": "@env(MOD)",
"mixins": [],
"minVersion": "0.8.7",
"plugin": "com.seibel.distanthorizons.cleanroom.DistantHorizonsConfigPlugin",
"client": [
]
}
+12
View File
@@ -0,0 +1,12 @@
[{
"modid": "${mod_id}",
"name": "${mod_name}",
"version": "${version}",
"mcversion": "1.12.2",
"description": "${description}",
"authorList": ["${cleanroom_authors}"],
"credits": "",
"url": "",
"updateJSON": "",
"logoFile": "${logo_path}"
}]
+6
View File
@@ -0,0 +1,6 @@
{
"pack": {
"description": "${mod_name} Resources",
"pack_format": 3
}
}
@@ -1,7 +1,8 @@
package com.seibel.distanthorizons.common; package com.seibel.distanthorizons.common;
import com.mojang.brigadier.CommandDispatcher; import com.seibel.distanthorizons.api.enums.config.EDhApiMcRenderingFadeMode;
import com.seibel.distanthorizons.api.enums.config.EDhApiRenderApi; import com.seibel.distanthorizons.api.enums.config.EDhApiRenderApi;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDhInitEvent; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDhInitEvent;
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeDhInitEvent; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeDhInitEvent;
import com.seibel.distanthorizons.common.commands.CommandInitializer; import com.seibel.distanthorizons.common.commands.CommandInitializer;
@@ -30,7 +31,6 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModAccesso
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector; import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.ModInfo;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.dedicated.DedicatedServer;
import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLogger;
@@ -39,6 +39,11 @@ import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Supplier;
#if MC_VER > MC_1_12_2
import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.commands.CommandSourceStack;
#endif
/** /**
* Base for all mod loader initializers * Base for all mod loader initializers
* and handles most setup. * and handles most setup.
@@ -62,7 +67,9 @@ public abstract class AbstractModInitializer
protected abstract IEventProxy createServerProxy(boolean isDedicated); protected abstract IEventProxy createServerProxy(boolean isDedicated);
protected abstract void initializeModCompat(); protected abstract void initializeModCompat();
#if MC_VER > MC_1_12_2
protected abstract void subscribeRegisterCommandsEvent(Consumer<CommandDispatcher<CommandSourceStack>> eventHandler); protected abstract void subscribeRegisterCommandsEvent(Consumer<CommandDispatcher<CommandSourceStack>> eventHandler);
#endif
protected abstract void subscribeClientStartedEvent(Runnable eventHandler); protected abstract void subscribeClientStartedEvent(Runnable eventHandler);
protected abstract void subscribeServerStartingEvent(Consumer<MinecraftServer> eventHandler); protected abstract void subscribeServerStartingEvent(Consumer<MinecraftServer> eventHandler);
@@ -96,6 +103,7 @@ public abstract class AbstractModInitializer
// Client uses config for auto-updater, so it's initialized here instead of post-init stage // Client uses config for auto-updater, so it's initialized here instead of post-init stage
this.initConfig(); this.initConfig();
logIncompatibilityWarnings(); // needs to be called after config loading logIncompatibilityWarnings(); // needs to be called after config loading
setUnsupportedConfigsBasedOnMcVersion();
Initializer.postConfigInit(); Initializer.postConfigInit();
LOGGER.info(ModInfo.READABLE_NAME + " client Initialized."); LOGGER.info(ModInfo.READABLE_NAME + " client Initialized.");
@@ -130,8 +138,10 @@ public abstract class AbstractModInitializer
this.initializeModCompat(); this.initializeModCompat();
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized, adding event subscribers..."); LOGGER.info(ModInfo.READABLE_NAME + " server Initialized, adding event subscribers...");
#if MC_VER > MC_1_12_2
this.commandInitializer = new CommandInitializer(); this.commandInitializer = new CommandInitializer();
this.subscribeRegisterCommandsEvent(dispatcher -> { this.commandInitializer.initCommands(dispatcher); }); this.subscribeRegisterCommandsEvent(dispatcher -> { this.commandInitializer.initCommands(dispatcher); });
#endif
this.subscribeServerStartingEvent(server -> this.subscribeServerStartingEvent(server ->
{ {
@@ -141,11 +151,20 @@ public abstract class AbstractModInitializer
Initializer.postConfigInit(); Initializer.postConfigInit();
this.postInit(); this.postInit();
this.postServerInit(); this.postServerInit();
#if MC_VER > MC_1_12_2
this.commandInitializer.onServerReady(); this.commandInitializer.onServerReady();
#endif
this.checkForUpdates(); this.checkForUpdates();
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized at " + server.getServerDirectory()); String serverFolderPath;
#if MC_VER <= MC_1_12_2
serverFolderPath = server.getDataDirectory() + "";
#else
serverFolderPath = server.getServerDirectory() + "";
#endif
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized at " + serverFolderPath);
}); });
} }
@@ -393,6 +412,24 @@ public abstract class AbstractModInitializer
} }
/**
* Some Minecraft versions don't support all
* DH options.
* In that case we need to override what options are available.
*/
private static void setUnsupportedConfigsBasedOnMcVersion()
{
#if MC_VER <= MC_1_12_2
Config.Client.Advanced.Graphics.Experimental.renderingApi.setMcVersionOverrideValue(EDhApiRenderApi.OPEN_GL);
Config.Client.Advanced.Graphics.Quality.vanillaFadeMode.setMcVersionOverrideValue(EDhApiMcRenderingFadeMode.NONE);
Config.Common.WorldGenerator.distantGeneratorMode.setMcVersionOverrideValue(EDhApiDistantGeneratorMode.INTERNAL_SERVER);
#elif MC_VER <= MC_1_21_10
Config.Client.Advanced.Graphics.Experimental.renderingApi.setMcVersionOverrideValue(EDhApiRenderApi.OPEN_GL);
#else
#endif
}
//endregion //endregion
@@ -12,10 +12,17 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSende
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.ModInfo;
import io.netty.buffer.ByteBufUtil; import io.netty.buffer.ByteBufUtil;
#if MC_VER <= MC_1_12_2
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.PacketBuffer;
#else
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
#endif
#if MC_VER <= MC_1_21_10 #if MC_VER <= MC_1_12_2
import net.minecraft.util.ResourceLocation;
#elif MC_VER <= MC_1_21_10
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
#else #else
import net.minecraft.resources.Identifier; import net.minecraft.resources.Identifier;
@@ -30,7 +37,9 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender
.fileLevelConfig(Config.Common.Logging.logNetworkEventToFile) .fileLevelConfig(Config.Common.Logging.logNetworkEventToFile)
.build(); .build();
#if MC_VER <= MC_1_20_6 #if MC_VER <= MC_1_12_2
public static final String WRAPPER_PACKET_RESOURCE = ModInfo.RESOURCE_NAMESPACE + ModInfo.WRAPPER_PACKET_PATH;
#elif MC_VER <= MC_1_20_6
public static final ResourceLocation WRAPPER_PACKET_RESOURCE = new ResourceLocation(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH); public static final ResourceLocation WRAPPER_PACKET_RESOURCE = new ResourceLocation(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH);
#elif MC_VER <= MC_1_21_10 #elif MC_VER <= MC_1_21_10
public static final ResourceLocation WRAPPER_PACKET_RESOURCE = ResourceLocation.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH); public static final ResourceLocation WRAPPER_PACKET_RESOURCE = ResourceLocation.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH);
@@ -52,14 +61,28 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender
@Override @Override
public final void sendToClient(IServerPlayerWrapper serverPlayer, AbstractNetworkMessage message) public final void sendToClient(IServerPlayerWrapper serverPlayer, AbstractNetworkMessage message)
{ {
#if MC_VER <= MC_1_12_2
this.sendToClient((EntityPlayerMP) serverPlayer.getWrappedMcObject(), message);
#else
this.sendToClient((ServerPlayer) serverPlayer.getWrappedMcObject(), message); this.sendToClient((ServerPlayer) serverPlayer.getWrappedMcObject(), message);
#endif
} }
#if MC_VER <= MC_1_12_2
public abstract void sendToClient(EntityPlayerMP serverPlayer, AbstractNetworkMessage message);
#else
public abstract void sendToClient(ServerPlayer serverPlayer, AbstractNetworkMessage message); public abstract void sendToClient(ServerPlayer serverPlayer, AbstractNetworkMessage message);
#endif
@Override @Override
public abstract void sendToServer(AbstractNetworkMessage message); public abstract void sendToServer(AbstractNetworkMessage message);
#if MC_VER <= MC_1_12_2
public AbstractNetworkMessage decodeMessage(PacketBuffer in)
#else
public AbstractNetworkMessage decodeMessage(FriendlyByteBuf in) public AbstractNetworkMessage decodeMessage(FriendlyByteBuf in)
#endif
{ {
AbstractNetworkMessage message = null; AbstractNetworkMessage message = null;
@@ -100,7 +123,11 @@ public abstract class AbstractPluginPacketSender implements IPluginPacketSender
} }
} }
#if MC_VER <= MC_1_12_2
public void encodeMessage(PacketBuffer out, AbstractNetworkMessage message)
#else
public void encodeMessage(FriendlyByteBuf out, AbstractNetworkMessage message) public void encodeMessage(FriendlyByteBuf out, AbstractNetworkMessage message)
#endif
{ {
// This is intentionally unhandled, because errors related to this are unlikely to appear in wild // This is intentionally unhandled, because errors related to this are unlikely to appear in wild
Objects.requireNonNull(message); Objects.requireNonNull(message);
@@ -1,5 +1,9 @@
package com.seibel.distanthorizons.common.commands; package com.seibel.distanthorizons.common.commands;
#if MC_VER <= MC_1_12_2
public abstract class AbstractCommand {}
#else
import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper; import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
@@ -100,3 +104,4 @@ public abstract class AbstractCommand
} }
} }
#endif
@@ -1,12 +1,26 @@
package com.seibel.distanthorizons.common.commands; package com.seibel.distanthorizons.common.commands;
#if MC_VER <= MC_1_12_2
import com.seibel.distanthorizons.core.config.ConfigHandler;
import com.seibel.distanthorizons.core.config.types.AbstractConfigBase;
import com.seibel.distanthorizons.core.config.types.ConfigEntry;
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
import net.minecraft.command.CommandBase;
import net.minecraft.command.ICommand;
import net.minecraft.command.ICommandSender;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.text.TextComponentString;
#else
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import static net.minecraft.commands.Commands.literal;
#endif
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import static com.seibel.distanthorizons.core.network.messages.MessageRegistry.DEBUG_CODEC_CRASH_MESSAGE; import static com.seibel.distanthorizons.core.network.messages.MessageRegistry.DEBUG_CODEC_CRASH_MESSAGE;
import static net.minecraft.commands.Commands.literal;
#if MC_VER <= MC_1_21_10 #if MC_VER <= MC_1_21_10
#else #else
@@ -25,6 +39,70 @@ public class CommandInitializer
#endif #endif
#if MC_VER <= MC_1_12_2
public static ICommand initCommands()
{
return new CommandBase()
{
@Override
public String getName() { return "dh"; }
@Override
public String getUsage(ICommandSender sender) { return "/dh <debug|config|pregen>"; }
@Override
public void execute(MinecraftServer server, ICommandSender sender, String[] args)
{
if (args.length == 0)
{
if (DEBUG_CODEC_CRASH_MESSAGE)
{
sender.sendMessage(new TextComponentString("Usage: /dh <debug|config|crash|pregen>"));
}
else
{
sender.sendMessage(new TextComponentString("Usage: /dh <debug|config|pregen"));
}
return;
}
switch (args[0])
{
case "debug":
DebugCommand debugCommand = new DebugCommand();
debugCommand.execute(sender);
break;
case "config":
ConfigCommand configCommand = new ConfigCommand();
configCommand.execute(sender, args);
break;
case "crash":
if (DEBUG_CODEC_CRASH_MESSAGE)
{
CrashCommand crashCommand = new CrashCommand();
crashCommand.execute(sender, args);
}
break;
case "pregen":
if (!server.isDedicatedServer())
{
sender.sendMessage(new TextComponentString("Pregen command is only available on dedicated servers"));
break;
}
PregenCommand pregenCommand = new PregenCommand();
pregenCommand.execute(server, sender, args);
break;
default:
sender.sendMessage(new TextComponentString("Unknown subcommand: " + args[0]));
}
}
};
}
#else
/** /**
* A received command dispatcher, which is held until the server is ready to initialize the commands. * A received command dispatcher, which is held until the server is ready to initialize the commands.
*/ */
@@ -80,5 +158,5 @@ public class CommandInitializer
commandDispatcher.register(builder); commandDispatcher.register(builder);
} }
#endif
} }
@@ -1,13 +1,25 @@
package com.seibel.distanthorizons.common.commands; package com.seibel.distanthorizons.common.commands;
import com.mojang.brigadier.arguments.*;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.seibel.distanthorizons.core.config.ConfigHandler; import com.seibel.distanthorizons.core.config.ConfigHandler;
import com.seibel.distanthorizons.core.config.types.AbstractConfigBase; import com.seibel.distanthorizons.core.config.types.AbstractConfigBase;
import com.seibel.distanthorizons.core.config.types.ConfigEntry; import com.seibel.distanthorizons.core.config.types.ConfigEntry;
#if MC_VER <= MC_1_12_2
import net.minecraft.command.ICommandSender;
import net.minecraft.util.text.TextComponentString;
#else
import com.mojang.brigadier.arguments.*;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import static com.mojang.brigadier.arguments.DoubleArgumentType.doubleArg;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static net.minecraft.commands.Commands.argument;
import static net.minecraft.commands.Commands.literal;
#endif
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@@ -16,16 +28,75 @@ import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.function.ToIntBiFunction; import java.util.function.ToIntBiFunction;
import static com.mojang.brigadier.arguments.DoubleArgumentType.doubleArg;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static net.minecraft.commands.Commands.argument;
import static net.minecraft.commands.Commands.literal;
/** /**
* Command for managing config. * Command for managing config.
*/ */
public class ConfigCommand extends AbstractCommand public class ConfigCommand extends AbstractCommand
{ {
#if MC_VER <= MC_1_12_2
@SuppressWarnings({"unchecked", "rawtypes"})
private static void setConfigValue(ConfigEntry<?> configEntry, String value)
{
Class<?> type = configEntry.getType();
if (type == Boolean.class) ((ConfigEntry) configEntry).set(Boolean.parseBoolean(value));
else if (type == Integer.class) ((ConfigEntry) configEntry).set(Integer.parseInt(value));
else if (type == Double.class) ((ConfigEntry) configEntry).set(Double.parseDouble(value));
else if (type == Float.class) ((ConfigEntry) configEntry).set(Float.parseFloat(value));
else if (type == Long.class) ((ConfigEntry) configEntry).set(Long.parseLong(value));
else if (type == String.class) ((ConfigEntry) configEntry).set(value);
else if (type.isEnum()) ((ConfigEntry) configEntry).set(Enum.valueOf((Class<Enum>) type, value));
else throw new RuntimeException("Unsupported config type: " + type.getSimpleName());
}
public void execute(ICommandSender sender, String[] args)
{
if (args.length < 2)
{
sender.sendMessage(new TextComponentString("Usage: /dh config <name> [value]"));
return;
}
String configName = args[1];
AbstractConfigBase<?> found = null;
for (AbstractConfigBase<?> entry : ConfigHandler.INSTANCE.configBaseList)
{
if (entry instanceof ConfigEntry && configName.equals(((ConfigEntry<?>) entry).getChatCommandName()))
{
found = entry;
break;
}
}
if (found == null)
{
sender.sendMessage(new TextComponentString("Unknown config: " + configName));
return;
}
ConfigEntry<?> configEntry = (ConfigEntry<?>) found;
if (args.length == 2)
{
sender.sendMessage(new TextComponentString("Current value of " + configName + " is " + configEntry.get()));
}
else
{
String value = args[2];
try
{
setConfigValue(configEntry, value);
sender.sendMessage(new TextComponentString("Changed " + configName + " to " + value));
}
catch (Exception e)
{
sender.sendMessage(new TextComponentString("Invalid value: " + value));
}
}
}
#else
private static final List<CommandArgumentData<?>> commandArguments = Arrays.asList( private static final List<CommandArgumentData<?>> commandArguments = Arrays.asList(
new CommandArgumentData<>(Integer.class, configEntry -> integer(configEntry.getMin(), configEntry.getMax()), IntegerArgumentType::getInteger), new CommandArgumentData<>(Integer.class, configEntry -> integer(configEntry.getMin(), configEntry.getMax()), IntegerArgumentType::getInteger),
new CommandArgumentData<>(Double.class, configEntry -> doubleArg(configEntry.getMin(), configEntry.getMax()), DoubleArgumentType::getDouble), new CommandArgumentData<>(Double.class, configEntry -> doubleArg(configEntry.getMin(), configEntry.getMax()), DoubleArgumentType::getDouble),
@@ -150,5 +221,6 @@ public class ConfigCommand extends AbstractCommand
} }
} }
#endif
} }
@@ -1,15 +1,60 @@
package com.seibel.distanthorizons.common.commands; package com.seibel.distanthorizons.common.commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.seibel.distanthorizons.core.api.internal.SharedApi; import com.seibel.distanthorizons.core.api.internal.SharedApi;
import com.seibel.distanthorizons.core.multiplayer.server.ServerPlayerState; import com.seibel.distanthorizons.core.multiplayer.server.ServerPlayerState;
import com.seibel.distanthorizons.core.network.messages.base.CodecCrashMessage; import com.seibel.distanthorizons.core.network.messages.base.CodecCrashMessage;
#if MC_VER <= MC_1_12_2
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
import net.minecraft.command.ICommandSender;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.text.TextComponentString;
#else
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import static net.minecraft.commands.Commands.literal; import static net.minecraft.commands.Commands.literal;
#endif
public class CrashCommand extends AbstractCommand public class CrashCommand extends AbstractCommand
{ {
#if MC_VER <= MC_1_12_2
public void execute(ICommandSender sender, String[] args)
{
if (!(sender instanceof EntityPlayerMP))
{
sender.sendMessage(new TextComponentString("This command can only be run by a player"));
return;
}
if (args.length < 2)
{
sender.sendMessage(new TextComponentString("Usage: /dh crash <encode|decode>"));
return;
}
if (SharedApi.tryGetDhServerWorld() == null) return;
ServerPlayerState serverPlayerState = SharedApi.tryGetDhServerWorld()
.getServerPlayerStateManager()
.getConnectedPlayer(ServerPlayerWrapper.getWrapper((EntityPlayerMP) sender));
if (serverPlayerState == null) return;
switch (args[1])
{
case "encode":
serverPlayerState.networkSession.sendMessage(new CodecCrashMessage(CodecCrashMessage.ECrashPhase.ENCODE));
break;
case "decode":
serverPlayerState.networkSession.sendMessage(new CodecCrashMessage(CodecCrashMessage.ECrashPhase.DECODE));
break;
default:
sender.sendMessage(new TextComponentString("Usage: /dh crash <encode|decode>"));
}
}
#else
@Override @Override
public LiteralArgumentBuilder<CommandSourceStack> buildCommand() public LiteralArgumentBuilder<CommandSourceStack> buildCommand()
{ {
@@ -40,5 +85,6 @@ public class CrashCommand extends AbstractCommand
return 1; return 1;
})); }));
} }
#endif
} }
@@ -1,25 +1,44 @@
package com.seibel.distanthorizons.common.commands; package com.seibel.distanthorizons.common.commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.seibel.distanthorizons.core.logging.f3.F3Screen; import com.seibel.distanthorizons.core.logging.f3.F3Screen;
#if MC_VER <= MC_1_12_2
import net.minecraft.command.ICommandSender;
import net.minecraft.util.text.TextComponentString;
#else
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import static net.minecraft.commands.Commands.literal;
#endif
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static net.minecraft.commands.Commands.literal;
public class DebugCommand extends AbstractCommand public class DebugCommand extends AbstractCommand
{ {
private static String getDebugString()
{
List<String> lines = new ArrayList<>();
F3Screen.addStringToDisplay(lines);
return String.join("\n", lines);
}
#if MC_VER > MC_1_12_2
@Override @Override
public LiteralArgumentBuilder<CommandSourceStack> buildCommand() public LiteralArgumentBuilder<CommandSourceStack> buildCommand()
{ {
return literal("debug") return literal("debug")
.executes(c -> { .executes(c -> {
List<String> lines = new ArrayList<>(); return this.sendSuccessResponse(c, getDebugString(), false);
F3Screen.addStringToDisplay(lines); });
return this.sendSuccessResponse(c, String.join("\n", lines), false);
});
} }
#else
public void execute(ICommandSender sender)
{
sender.sendMessage(new TextComponentString(getDebugString()));
}
#endif
} }
@@ -1,27 +1,36 @@
package com.seibel.distanthorizons.common.commands; package com.seibel.distanthorizons.common.commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.core.api.internal.SharedApi; import com.seibel.distanthorizons.core.api.internal.SharedApi;
import com.seibel.distanthorizons.core.generation.PregenManager; import com.seibel.distanthorizons.core.generation.PregenManager;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D; import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
import com.seibel.distanthorizons.core.world.DhServerWorld; import com.seibel.distanthorizons.core.world.DhServerWorld;
#if MC_VER <= MC_1_12_2
import net.minecraft.command.ICommandSender;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.world.WorldServer;
#else
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.arguments.DimensionArgument; import net.minecraft.commands.arguments.DimensionArgument;
import net.minecraft.commands.arguments.coordinates.ColumnPosArgument; import net.minecraft.commands.arguments.coordinates.ColumnPosArgument;
import net.minecraft.server.level.ColumnPos; import net.minecraft.server.level.ColumnPos;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import java.util.Objects;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger; import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static net.minecraft.commands.Commands.argument; import static net.minecraft.commands.Commands.argument;
import static net.minecraft.commands.Commands.literal; import static net.minecraft.commands.Commands.literal;
#endif
import java.util.Objects;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
public class PregenCommand extends AbstractCommand public class PregenCommand extends AbstractCommand
{ {
@@ -31,6 +40,101 @@ public class PregenCommand extends AbstractCommand
return world.getPregenManager(); return world.getPregenManager();
} }
#if MC_VER <= MC_1_12_2
public void execute(MinecraftServer server, ICommandSender sender, String[] args)
{
if (args.length < 2)
{
sender.sendMessage(new TextComponentString("Usage: /dh pregen <status|start|stop>"));
return;
}
switch (args[1])
{
case "status":
{
String statusString = this.getPregenManager().getStatusString();
sender.sendMessage(new TextComponentString(
statusString != null ? statusString : "Pregen is not running"));
break;
}
case "start":
{
if (args.length < 5)
{
sender.sendMessage(new TextComponentString("Usage: /dh pregen start <dimension> <x> <z> <chunkRadius>"));
return;
}
try
{
String dimensionName = args[2];
int x = Integer.parseInt(args[3]);
int z = Integer.parseInt(args[4]);
int chunkRadius = args.length >= 6 ? Integer.parseInt(args[5]) : 32;
// find the world by dimension name
WorldServer world = null;
for (WorldServer w : server.worlds)
{
if (w.provider.getDimensionType().getName().equals(dimensionName))
{
world = w;
break;
}
}
if (world == null)
{
sender.sendMessage(new TextComponentString("Unknown dimension: " + dimensionName));
return;
}
sender.sendMessage(new TextComponentString("Starting pregen. Progress will be in the server console."));
final ICommandSender finalSender = sender;
CompletableFuture<Void> future = this.getPregenManager().startPregen(
ServerLevelWrapper.getWrapper(world),
new DhBlockPos2D(x, z),
chunkRadius
);
future.whenComplete((result, throwable) -> {
if (throwable instanceof CancellationException)
{
finalSender.sendMessage(new TextComponentString("Pregen is cancelled"));
return;
}
else if (throwable != null)
{
finalSender.sendMessage(new TextComponentString("Pregen failed: " + throwable.getMessage()));
return;
}
finalSender.sendMessage(new TextComponentString("Pregen is complete"));
});
}
catch (NumberFormatException e)
{
sender.sendMessage(new TextComponentString("Invalid number format"));
}
break;
}
case "stop":
{
CompletableFuture<Void> runningPregen = this.getPregenManager().getRunningPregen();
if (runningPregen == null)
{
sender.sendMessage(new TextComponentString("Pregen is not running"));
return;
}
runningPregen.cancel(true);
break;
}
default:
sender.sendMessage(new TextComponentString("Unknown subcommand: " + args[1]));
}
}
#else
@Override @Override
public LiteralArgumentBuilder<CommandSourceStack> buildCommand() public LiteralArgumentBuilder<CommandSourceStack> buildCommand()
{ {
@@ -110,5 +214,5 @@ public class PregenCommand extends AbstractCommand
runningPregen.cancel(true); runningPregen.cancel(true);
return 1; return 1;
} }
#endif
} }
@@ -1,5 +1,6 @@
package com.seibel.distanthorizons.common.commonMixins; package com.seibel.distanthorizons.common.commonMixins;
#if MC_VER > MC_1_12_2
import com.seibel.distanthorizons.api.enums.config.EDhApiUpdateBranch; import com.seibel.distanthorizons.api.enums.config.EDhApiUpdateBranch;
import com.seibel.distanthorizons.common.wrappers.gui.updater.UpdateModScreen; import com.seibel.distanthorizons.common.wrappers.gui.updater.UpdateModScreen;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
@@ -11,16 +12,18 @@ import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants; import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.TitleScreen; #if MC_VER <= MC_1_12_2
#else
import net.minecraft.client.gui.screens.TitleScreen;
#endif
import java.util.ArrayList; import java.util.ArrayList;
public class DhUpdateScreenBase public class DhUpdateScreenBase
{ {
private static final DhLogger LOGGER = new DhLoggerBuilder().build(); private static final DhLogger LOGGER = new DhLoggerBuilder().build();
private static final Minecraft MC = Minecraft.getInstance(); private static final Minecraft MC = Minecraft #if MC_VER <= MC_1_12_2 .getMinecraft() #else .getInstance() #endif;
public static void tryShowUpdateScreenAndRunAutoUpdateStartup(Runnable runnable) public static void tryShowUpdateScreenAndRunAutoUpdateStartup(Runnable runnable)
@@ -86,3 +89,4 @@ public class DhUpdateScreenBase
} }
} }
#endif
@@ -6,15 +6,23 @@ import com.seibel.distanthorizons.core.api.internal.ServerApi;
import com.seibel.distanthorizons.core.api.internal.SharedApi; import com.seibel.distanthorizons.core.api.internal.SharedApi;
import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
#if MC_VER <= MC_1_12_2
import net.minecraft.world.WorldServer;
import net.minecraft.world.chunk.Chunk;
#else
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ProtoChunk; import net.minecraft.world.level.chunk.ProtoChunk;
#endif
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
public class MixinChunkMapCommon public class MixinChunkMapCommon
{ {
#if MC_VER <= MC_1_12_2
public static void onChunkSave(WorldServer level, Chunk chunk)
#else
public static void onChunkSave(ServerLevel level, ChunkAccess chunk, CallbackInfoReturnable<Boolean> ci) public static void onChunkSave(ServerLevel level, ChunkAccess chunk, CallbackInfoReturnable<Boolean> ci)
#endif
{ {
IServerLevelWrapper levelWrapper = ServerLevelWrapper.getWrapper(level); IServerLevelWrapper levelWrapper = ServerLevelWrapper.getWrapper(level);
@@ -37,7 +45,7 @@ public class MixinChunkMapCommon
// is this chunk being saved to disk? // is this chunk being saved to disk?
boolean savingChunkToDisk = ci.getReturnValue(); boolean savingChunkToDisk = #if MC_VER <= MC_1_12_2 true #else ci.getReturnValue() #endif;
// true means a chunk was saved to disk // true means a chunk was saved to disk
if (!savingChunkToDisk) if (!savingChunkToDisk)
{ {
@@ -50,7 +58,12 @@ public class MixinChunkMapCommon
// MC has a tendency to try saving incomplete or corrupted chunks (which show up as empty or black chunks) // MC has a tendency to try saving incomplete or corrupted chunks (which show up as empty or black chunks)
// this logic should prevent that from happening // this logic should prevent that from happening
#if MC_VER <= MC_1_17_1 #if MC_VER <= MC_1_12_2
if (!chunk.isTerrainPopulated() || !chunk.isLightPopulated())
{
return;
}
#elif MC_VER <= MC_1_17_1
if (chunk.isUnsaved() || chunk.getUpgradeData() != null || !chunk.isLightCorrect()) if (chunk.isUnsaved() || chunk.getUpgradeData() != null || !chunk.isLightCorrect())
{ {
return; return;
@@ -67,7 +80,12 @@ public class MixinChunkMapCommon
// biome validation // // biome validation //
// some chunks may be missing their biomes, which cause issues when attempting to save them // some chunks may be missing their biomes, which cause issues when attempting to save them
#if MC_VER <= MC_1_17_1 #if MC_VER <= MC_1_12_2
if (chunk. getBiomeArray() == null)
{
return;
}
#elif MC_VER <= MC_1_17_1
if (chunk.getBiomes() == null) if (chunk.getBiomes() == null)
{ {
return; return;
@@ -0,0 +1,52 @@
package com.seibel.distanthorizons.common.commonMixins;
#if MC_VER > MC_1_12_2
import com.seibel.distanthorizons.common.wrappers.modAccessor.ImmersivePortalsAccessorCommon;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
import com.seibel.distanthorizons.core.util.math.Vec3d;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.phys.Vec3;
public class MixinImmersivePortalsRenderStatesCommon
{
public static void saveVolatileOriginals()
{
Minecraft mc = Minecraft.getInstance();
ImmersivePortalsAccessorCommon.originalLevel = mc.level;
if (mc.player == null) {
ImmersivePortalsAccessorCommon.originalBlockPos = null;
ImmersivePortalsAccessorCommon.originalChunkPos = null;
ImmersivePortalsAccessorCommon.originalCameraPos = null;
return;
}
BlockPos pos = mc.player.blockPosition();
ImmersivePortalsAccessorCommon.originalBlockPos = new DhBlockPos(pos.getX(), pos.getY(), pos.getZ());
#if MC_VER < MC_1_17_1
ChunkPos cPos = new ChunkPos(mc.player.blockPosition());
#else
ChunkPos cPos = mc.player.chunkPosition();
#endif
#if MC_VER <= MC_1_21_11
ImmersivePortalsAccessorCommon.originalChunkPos = new DhChunkPos(cPos.x, cPos.z);
#else
ImmersivePortalsAccessorCommon.originalChunkPos = new DhChunkPos(cPos.x(), cPos.z());
#endif
#if MC_VER <= MC_1_21_10
Vec3 cameraPos = mc.gameRenderer.getMainCamera().getPosition();
#else
Vec3 cameraPos = mc.gameRenderer.getMainCamera().position();
#endif
ImmersivePortalsAccessorCommon.originalCameraPos = new Vec3d(cameraPos.x(), cameraPos.y(), cameraPos.z());
}
}
#endif
@@ -7,21 +7,22 @@ import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IImmersivePortalsAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
#if MC_VER <= MC_1_12_2
#else
import net.minecraft.client.Camera; import net.minecraft.client.Camera;
import net.minecraft.world.effect.MobEffects; import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
#endif
#if MC_VER <= MC_1_12_2
import net.minecraft.client.Camera; import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.world.effect.MobEffects; import net.minecraft.init.MobEffects;
import net.minecraft.world.entity.Entity; #elif MC_VER < MC_1_17_1
import net.minecraft.world.entity.LivingEntity;
#if MC_VER < MC_1_17_1
import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.FluidState;
import net.minecraft.client.renderer.FogRenderer; import net.minecraft.client.renderer.FogRenderer;
import net.minecraft.client.renderer.FogRenderer.FogMode; import net.minecraft.client.renderer.FogRenderer.FogMode;
@@ -51,22 +52,29 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
#else #else
import net.minecraft.world.level.material.FogType; import net.minecraft.world.level.material.FogType;
import net.minecraft.client.renderer.fog.FogRenderer;
import net.minecraft.client.renderer.fog.FogData;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
#endif #endif
public class MixinVanillaFogCommon public class MixinVanillaFogCommon
{ {
#if MC_VER <= MC_1_12_2
#if MC_VER < MC_1_21_6 public static boolean cancelFog(int startCoords, Minecraft mc)
#elif MC_VER < MC_1_21_6
public static boolean cancelFog(Camera camera, FogRenderer.FogMode fogMode) public static boolean cancelFog(Camera camera, FogRenderer.FogMode fogMode)
#else #else
public static boolean cancelFog() public static boolean cancelFog()
#endif #endif
{ {
#if MC_VER <= MC_1_12_2
#if MC_VER < MC_1_21_6 EntityPlayerSP entity = mc.player;
#elif MC_VER < MC_1_21_6
Entity entity = camera.getEntity(); Entity entity = camera.getEntity();
#elif MC_VER <= MC_1_21_10 #elif MC_VER <= MC_1_21_10
Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera(); Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera();
@@ -76,13 +84,23 @@ public class MixinVanillaFogCommon
Entity entity = camera.entity(); Entity entity = camera.entity();
#endif #endif
#if MC_VER <= MC_1_12_2
boolean cameraNotInFluid = cameraNotInFluid(mc);
#else
boolean cameraNotInFluid = cameraNotInFluid(camera); boolean cameraNotInFluid = cameraNotInFluid(camera);
#endif
#if MC_VER <= MC_1_12_2
boolean isSpecialFog = entity.isPotionActive(MobEffects.BLINDNESS);
#else
boolean isSpecialFog = (entity instanceof LivingEntity) && ((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS); boolean isSpecialFog = (entity instanceof LivingEntity) && ((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS);
#endif
boolean cancelFog = !isSpecialFog; boolean cancelFog = !isSpecialFog;
cancelFog = cancelFog && cameraNotInFluid; cancelFog = cancelFog && cameraNotInFluid;
#if MC_VER < MC_1_21_6 #if MC_VER <= MC_1_12_2
cancelFog = cancelFog && startCoords == 0; // 0 = terrain fog
#elif MC_VER < MC_1_21_6
cancelFog = cancelFog && (fogMode == FogRenderer.FogMode.FOG_TERRAIN); cancelFog = cancelFog && (fogMode == FogRenderer.FogMode.FOG_TERRAIN);
#endif #endif
@@ -90,12 +108,25 @@ public class MixinVanillaFogCommon
cancelFog = cancelFog && !Config.Client.Advanced.Graphics.Fog.enableVanillaFog.get(); cancelFog = cancelFog && !Config.Client.Advanced.Graphics.Fog.enableVanillaFog.get();
IImmersivePortalsAccessor immersivePortals = ModAccessorInjector.INSTANCE.get(IImmersivePortalsAccessor.class);
if (immersivePortals != null
&& immersivePortals.isRenderingPortal())
{
cancelFog = false;
}
return cancelFog; return cancelFog;
} }
#if MC_VER <= MC_1_12_2
private static boolean cameraNotInFluid(Minecraft mc)
#else
private static boolean cameraNotInFluid(Camera camera) private static boolean cameraNotInFluid(Camera camera)
#endif
{ {
#if MC_VER < MC_1_17_1 #if MC_VER <= MC_1_12_2
boolean cameraNotInFluid = mc.getRenderViewEntity() != null && !mc.world.getBlockState(mc.getRenderViewEntity().getPosition()).getMaterial().isLiquid();
#elif MC_VER < MC_1_17_1
FluidState fluidState = camera.getFluidInCamera(); FluidState fluidState = camera.getFluidInCamera();
boolean cameraNotInFluid = fluidState.isEmpty(); boolean cameraNotInFluid = fluidState.isEmpty();
#else #else
@@ -97,7 +97,9 @@ public class GLState implements AutoCloseable
{ {
this.frameBufferTexture0 = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME); this.frameBufferTexture0 = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
this.frameBufferTexture1 = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT1, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME); this.frameBufferTexture1 = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT1, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
this.frameBufferDepthTexture = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
int depthType = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
this.frameBufferDepthTexture = (depthType == GL32.GL_TEXTURE) ? GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) : 0;
} }
else else
{ {
@@ -179,9 +181,21 @@ public class GLState implements AutoCloseable
// attempting to set textures on the default frame buffer (ID 0) will throw errors // attempting to set textures on the default frame buffer (ID 0) will throw errors
if (frameBufferSet) if (frameBufferSet)
{ {
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.frameBufferTexture0, 0); if (GL32.glIsTexture(this.frameBufferTexture0))
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT1, GL32.GL_TEXTURE_2D, this.frameBufferTexture1, 0); {
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_TEXTURE_2D, this.frameBufferDepthTexture, 0); GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.frameBufferTexture0, 0);
}
if (this.frameBufferTexture1 != 0 && GL32.glIsTexture(this.frameBufferTexture1))
{
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT1, GL32.GL_TEXTURE_2D, this.frameBufferTexture1, 0);
}
if (GL32.glIsTexture(this.frameBufferDepthTexture))
{
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_TEXTURE_2D, this.frameBufferDepthTexture, 0);
}
} }
GL32.glBindVertexArray(GL32.glIsVertexArray(this.vao) ? this.vao : 0); GL32.glBindVertexArray(GL32.glIsVertexArray(this.vao) ? this.vao : 0);
@@ -22,23 +22,34 @@ package com.seibel.distanthorizons.common.util;
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper; import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
#if MC_VER <= MC_1_12_2
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
#else
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
#endif
public class ProxyUtil public class ProxyUtil
{ {
public static ILevelWrapper getLevelWrapper(LevelAccessor level) public static ILevelWrapper getLevelWrapper(
#if MC_VER <= MC_1_12_2 World #else LevelAccessor #endif level
)
{ {
ILevelWrapper levelWrapper; ILevelWrapper levelWrapper;
if (level instanceof ServerLevel) if (level instanceof #if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif)
{ {
levelWrapper = ServerLevelWrapper.getWrapper((ServerLevel) level); levelWrapper = ServerLevelWrapper.getWrapper(
#if MC_VER <= MC_1_12_2 (WorldServer) #else (ServerLevel) #endif level
);
} }
else else
{ {
levelWrapper = ClientLevelWrapper.getWrapper((ClientLevel) level); levelWrapper = ClientLevelWrapper.getWrapper(
#if MC_VER <= MC_1_12_2 (WorldClient) #else (ClientLevel) #endif level
);
} }
return levelWrapper; return levelWrapper;
@@ -26,9 +26,15 @@ import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.util.math.Mat4f; import com.seibel.distanthorizons.core.util.math.Mat4f;
#if MC_VER <= MC_1_12_2
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
#else
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
#endif
/** /**
* This class converts to and from Minecraft objects (Ex: Matrix4f) * This class converts to and from Minecraft objects (Ex: Matrix4f)
@@ -39,15 +45,17 @@ import net.minecraft.world.level.ChunkPos;
*/ */
public class McObjectConverter public class McObjectConverter
{ {
private static int bufferIndex(int x, int y)
{
return y * 4 + x;
}
//========//
// matrix //
//========//
//region
/** 4x4 float matrix converter */ /** 4x4 float matrix converter */
public static Mat4f Convert( public static Mat4f Convert(
#if MC_VER < MC_1_19_4 com.mojang.math.Matrix4f #if MC_VER <= MC_1_12_2 org.joml.Matrix4f
#elif MC_VER < MC_1_19_4 com.mojang.math.Matrix4f
#elif MC_VER < MC_1_21_6 org.joml.Matrix4f #elif MC_VER < MC_1_21_6 org.joml.Matrix4f
#else org.joml.Matrix4fc #else org.joml.Matrix4fc
#endif #endif
@@ -56,21 +64,24 @@ public class McObjectConverter
FloatBuffer buffer = FloatBuffer.allocate(16); FloatBuffer buffer = FloatBuffer.allocate(16);
storeMatrix(mcMatrix, buffer); storeMatrix(mcMatrix, buffer);
Mat4f matrix = new Mat4f(buffer); Mat4f matrix = new Mat4f(buffer);
#if MC_VER < MC_1_19_4 #if MC_VER > MC_1_12_2 && MC_VER < MC_1_19_4
matrix.transpose(); // In 1.19.3 and later, we no longer need to transpose it matrix.transpose(); // In 1.19.3 and later, we no longer need to transpose it
#endif #endif
return matrix; return matrix;
} }
/** Taken from Minecraft's com.mojang.math.Matrix4f class from 1.18.2 */ /** Taken from Minecraft's com.mojang.math.Matrix4f class from 1.18.2 */
private static void storeMatrix( private static void storeMatrix(
#if MC_VER < MC_1_19_4 com.mojang.math.Matrix4f #if MC_VER <= MC_1_12_2 org.joml.Matrix4f
#elif MC_VER < MC_1_19_4 com.mojang.math.Matrix4f
#elif MC_VER < MC_1_21_6 org.joml.Matrix4f #elif MC_VER < MC_1_21_6 org.joml.Matrix4f
#else org.joml.Matrix4fc #else org.joml.Matrix4fc
#endif #endif
matrix, matrix,
FloatBuffer buffer) FloatBuffer buffer)
{ {
#if MC_VER < MC_1_19_4 #if MC_VER <= MC_1_12_2
matrix.get(buffer);
#elif MC_VER < MC_1_19_4
matrix.store(buffer); matrix.store(buffer);
#else #else
// Mojang starts to use joml's Matrix4f libary in 1.19.3 so we copy their store method and use it here if its newer than 1.19.3 // Mojang starts to use joml's Matrix4f libary in 1.19.3 so we copy their store method and use it here if its newer than 1.19.3
@@ -92,37 +103,85 @@ public class McObjectConverter
buffer.put(bufferIndex(3, 3), matrix.m33()); buffer.put(bufferIndex(3, 3), matrix.m33());
#endif #endif
} }
private static int bufferIndex(int x, int y) { return y * 4 + x; }
//endregion
static final Direction[] directions;
static final EDhDirection[] lodDirections; //===========//
// direction //
//===========//
//region
#if MC_VER <= MC_1_12_2
private static final EnumFacing[] mcDirections;
#else
private static final Direction[] mcDirections;
#endif
private static final EDhDirection[] dhDirections;
static static
{ {
EDhDirection[] lodDirs = EDhDirection.values(); EDhDirection[] lodDirs = EDhDirection.values();
directions = new Direction[lodDirs.length];
lodDirections = new EDhDirection[lodDirs.length]; #if MC_VER <= MC_1_12_2
mcDirections = new EnumFacing[lodDirs.length];
#else
mcDirections = new Direction[lodDirs.length];
#endif
dhDirections = new EDhDirection[lodDirs.length];
for (EDhDirection lodDir : lodDirs) for (EDhDirection lodDir : lodDirs)
{ {
Direction dir; #if MC_VER <= MC_1_12_2
EnumFacing dir;
#else
Direction dir;
#endif
switch (lodDir.name().toUpperCase()) switch (lodDir.name().toUpperCase())
{ {
case "DOWN": case "DOWN":
#if MC_VER <= MC_1_12_2
dir = EnumFacing.DOWN;
#else
dir = Direction.DOWN; dir = Direction.DOWN;
#endif
break; break;
case "UP": case "UP":
#if MC_VER <= MC_1_12_2
dir = EnumFacing.UP;
#else
dir = Direction.UP; dir = Direction.UP;
#endif
break; break;
case "NORTH": case "NORTH":
#if MC_VER <= MC_1_12_2
dir = EnumFacing.NORTH;
#else
dir = Direction.NORTH; dir = Direction.NORTH;
#endif
break; break;
case "SOUTH": case "SOUTH":
#if MC_VER <= MC_1_12_2
dir = EnumFacing.SOUTH;
#else
dir = Direction.SOUTH; dir = Direction.SOUTH;
#endif
break; break;
case "WEST": case "WEST":
#if MC_VER <= MC_1_12_2
dir = EnumFacing.WEST;
#else
dir = Direction.WEST; dir = Direction.WEST;
#endif
break; break;
case "EAST": case "EAST":
#if MC_VER <= MC_1_12_2
dir = EnumFacing.EAST;
#else
dir = Direction.EAST; dir = Direction.EAST;
#endif
break; break;
default: default:
dir = null; dir = null;
@@ -131,13 +190,37 @@ public class McObjectConverter
if (dir == null) if (dir == null)
{ {
throw new IllegalArgumentException("Invalid direction on init mapping: " + lodDir); throw new IllegalArgumentException("Invalid direction on init mapping: [" + lodDir + "].");
} }
directions[lodDir.ordinal()] = dir; mcDirections[lodDir.ordinal()] = dir;
lodDirections[dir.ordinal()] = lodDir; dhDirections[dir.ordinal()] = lodDir;
} }
} }
#if MC_VER <= MC_1_12_2
public static EnumFacing Convert(EDhDirection lodDirection)
#else
public static Direction Convert(EDhDirection lodDirection)
#endif
{ return mcDirections[lodDirection.ordinal()]; }
#if MC_VER <= MC_1_12_2
public static EDhDirection Convert(EnumFacing direction)
#else
public static EDhDirection Convert(Direction direction)
#endif
{ return dhDirections[direction.ordinal()]; }
//endregion
//==================//
// position objects //
//==================//
//region
public static BlockPos Convert(DhBlockPos wrappedPos) { return new BlockPos(wrappedPos.getX(), wrappedPos.getY(), wrappedPos.getZ()); } public static BlockPos Convert(DhBlockPos wrappedPos) { return new BlockPos(wrappedPos.getX(), wrappedPos.getY(), wrappedPos.getZ()); }
public static ChunkPos Convert(DhChunkPos wrappedPos) { return new ChunkPos(wrappedPos.getX(), wrappedPos.getZ()); } public static ChunkPos Convert(DhChunkPos wrappedPos) { return new ChunkPos(wrappedPos.getX(), wrappedPos.getZ()); }
@@ -150,7 +233,8 @@ public class McObjectConverter
#endif #endif
} }
public static Direction Convert(EDhDirection lodDirection) { return directions[lodDirection.ordinal()]; } //endregion
public static EDhDirection Convert(Direction direction) { return lodDirections[direction.ordinal()]; }
} }
@@ -51,7 +51,10 @@ public class VersionConstants implements IVersionConstants
// it can't load client classes when running as a dedicated server, // it can't load client classes when running as a dedicated server,
// which was how we were dynamically accessing the MC version string // which was how we were dynamically accessing the MC version string
#if MC_VER == MC_1_16_5 #if MC_VER == MC_1_12_2
return "1.12.2";
#elif MC_VER == MC_1_16_5
return "1.16.5"; return "1.16.5";
#elif MC_VER == MC_1_17_1 #elif MC_VER == MC_1_17_1
@@ -46,17 +46,30 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.worldGeneration.IBatchGeneratorEnvironmentWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.worldGeneration.IBatchGeneratorEnvironmentWrapper;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import net.minecraft.client.multiplayer.ClientLevel;
#if MC_VER > MC_1_17_1 #if MC_VER > MC_1_17_1
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
#endif #endif
#if MC_VER <= MC_1_12_2
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.chunk.Chunk;
#else
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
#endif
import java.io.IOException; import java.io.IOException;
import java.util.HashSet;
/** /**
* This handles creating abstract wrapper objects. * This handles creating abstract wrapper objects.
@@ -115,7 +128,7 @@ public class WrapperFactory implements IWrapperFactory
throw new ClassCastException("levelWrapper must be returned by DH and of type ["+ILevelWrapper.class.getName()+"]."); throw new ClassCastException("levelWrapper must be returned by DH and of type ["+ILevelWrapper.class.getName()+"].");
} }
return BiomeWrapper.deserialize(resourceLocationString, (ILevelWrapper)levelWrapper); return BiomeWrapper.deserialize(resourceLocationString, (ILevelWrapper)levelWrapper);
} }
@Override @Override
public IDhApiBlockStateWrapper getDefaultBlockStateWrapper(String resourceLocationString, IDhApiLevelWrapper levelWrapper) throws IOException, ClassCastException public IDhApiBlockStateWrapper getDefaultBlockStateWrapper(String resourceLocationString, IDhApiLevelWrapper levelWrapper) throws IOException, ClassCastException
@@ -125,19 +138,19 @@ public class WrapperFactory implements IWrapperFactory
throw new ClassCastException("Invalid ["+IDhApiLevelWrapper.class.getSimpleName()+"] value given. Level wrapper object must be one given by the DH API (it can't be a custom implementation), specifically of type ["+ILevelWrapper.class.getName()+"]."); throw new ClassCastException("Invalid ["+IDhApiLevelWrapper.class.getSimpleName()+"] value given. Level wrapper object must be one given by the DH API (it can't be a custom implementation), specifically of type ["+ILevelWrapper.class.getName()+"].");
} }
return BlockStateWrapper.deserialize(resourceLocationString, (ILevelWrapper)levelWrapper); return BlockStateWrapper.deserialize(resourceLocationString, (ILevelWrapper)levelWrapper);
} }
@Override @Override
public IBiomeWrapper deserializeBiomeWrapper(String str, ILevelWrapper levelWrapper) throws IOException { return BiomeWrapper.deserialize(str, levelWrapper); } public IBiomeWrapper deserializeBiomeWrapper(String str, ILevelWrapper levelWrapper) throws IOException { return BiomeWrapper.deserialize(str, levelWrapper); }
@Override @Override
public IBiomeWrapper getPlainsBiomeWrapper(ILevelWrapper levelWrapper) public IBiomeWrapper getPlainsBiomeWrapper(ILevelWrapper levelWrapper)
{ {
try try
{ {
return BiomeWrapper.deserialize(BiomeWrapper.PLAINS_RESOURCE_LOCATION_STRING, levelWrapper); return BiomeWrapper.deserialize(BiomeWrapper.PLAINS_RESOURCE_LOCATION_STRING, levelWrapper);
} }
catch (IOException e) catch (IOException e)
{ {
throw new LodUtil.AssertFailureException("Unable to parse plains resource string ["+BiomeWrapper.PLAINS_RESOURCE_LOCATION_STRING+"], error:\n " + e.getMessage()); throw new LodUtil.AssertFailureException("Unable to parse plains resource string ["+BiomeWrapper.PLAINS_RESOURCE_LOCATION_STRING+"], error:\n " + e.getMessage());
} }
@@ -172,7 +185,8 @@ public class WrapperFactory implements IWrapperFactory
*/ */
public IChunkWrapper createChunkWrapper(Object[] objectArray) throws ClassCastException public IChunkWrapper createChunkWrapper(Object[] objectArray) throws ClassCastException
{ {
if (objectArray.length == 1 && objectArray[0] instanceof IChunkWrapper) if (objectArray.length == 1
&& objectArray[0] instanceof IChunkWrapper)
{ {
try try
{ {
@@ -186,41 +200,102 @@ public class WrapperFactory implements IWrapperFactory
} }
} }
//#if MC_VER <= MC_1_XX_X else if (objectArray.length != 2)
else if (objectArray.length == 2)
{
// correct number of parameters from the API
// chunk
if (!(objectArray[0] instanceof ChunkAccess))
{
throw new ClassCastException(createChunkWrapperErrorMessage(objectArray));
}
ChunkAccess chunk = (ChunkAccess) objectArray[0];
// level / light source
if (!(objectArray[1] instanceof Level))
{
throw new ClassCastException(createChunkWrapperErrorMessage(objectArray));
}
// the level is needed for the DH level wrapper...
Level level = (Level) objectArray[1];
// level wrapper
ILevelWrapper levelWrapper = level.isClientSide()
? ClientLevelWrapper.getWrapper((ClientLevel)level)
: ServerLevelWrapper.getWrapper((ServerLevel)level);
return new ChunkWrapper(chunk, levelWrapper);
}
// incorrect number of parameters from the API
else
{ {
throw new ClassCastException(createChunkWrapperErrorMessage(objectArray)); throw new ClassCastException(createChunkWrapperErrorMessage(objectArray));
} }
//#endif
// correct number of parameters from the API
//=======//
// chunk //
//=======//
//region
boolean chunkClassCorrect;
#if MC_VER <= MC_1_12_2
chunkClassCorrect = (objectArray[0] instanceof Chunk);
#else
chunkClassCorrect = (objectArray[0] instanceof ChunkAccess);
#endif
if (!chunkClassCorrect)
{
throw new ClassCastException(createChunkWrapperErrorMessage(objectArray));
}
#if MC_VER <= MC_1_12_2
Chunk chunk = (Chunk) objectArray[0];
#else
ChunkAccess chunk = (ChunkAccess) objectArray[0];
#endif
//endregion
//=======//
// level //
//=======//
//region
boolean levelClassCorrect;
#if MC_VER <= MC_1_12_2
levelClassCorrect = (objectArray[1] instanceof World);
#else
levelClassCorrect = (objectArray[1] instanceof Level);
#endif
if (!levelClassCorrect)
{
throw new ClassCastException(createChunkWrapperErrorMessage(objectArray));
}
#if MC_VER <= MC_1_12_2
World level = (World) objectArray[1];
#else
Level level = (Level) objectArray[1];
#endif
//endregion
//===============//
// level wrapper //
//===============//
//region
boolean isClientSide;
#if MC_VER <= MC_1_12_2
isClientSide = !level.isRemote;
#else
isClientSide = level.isClientSide();
#endif
ILevelWrapper levelWrapper;
if (isClientSide)
{
#if MC_VER <= MC_1_12_2
levelWrapper = ClientLevelWrapper.getWrapper((WorldClient)level);
#else
levelWrapper = ClientLevelWrapper.getWrapper((ClientLevel)level);
#endif
}
else
{
#if MC_VER <= MC_1_12_2
levelWrapper = ServerLevelWrapper.getWrapper((WorldServer)level);
#else
levelWrapper = ServerLevelWrapper.getWrapper((ServerLevel)level);
#endif
}
//endregion
return new ChunkWrapper(chunk, levelWrapper);
} }
/** /**
* Note: when this is updated for different MC versions, * Note: when this is updated for different MC versions,
@@ -230,13 +305,19 @@ public class WrapperFactory implements IWrapperFactory
{ {
String[] expectedClassNames; String[] expectedClassNames;
//#if MC_VER <= MC_1_XX_X #if MC_VER <= MC_1_12_2
expectedClassNames = new String[] expectedClassNames = new String[]
{ {
ChunkAccess.class.getName(), Chunk.class.getName(),
"[ServerLevel] or [ClientLevel]" // Classes are not referenced by names to avoid exception when one of them is missing "[WorldClient] or [WorldServer]" // Classes are not referenced by names to avoid exception when one of them is missing
}; };
//#endif #else
expectedClassNames = new String[]
{
ChunkAccess.class.getName(),
"[ServerLevel] or [ClientLevel]" // Classes are not referenced by names to avoid exception when one of them is missing
};
#endif
return createWrapperErrorMessage("Chunk wrapper", expectedClassNames, objectArray); return createWrapperErrorMessage("Chunk wrapper", expectedClassNames, objectArray);
} }
@@ -258,7 +339,7 @@ public class WrapperFactory implements IWrapperFactory
// documentation should be in the API interface // documentation should be in the API interface
public IDhApiBiomeWrapper getBiomeWrapper(Object[] objectArray, IDhApiLevelWrapper levelWrapper) public IDhApiBiomeWrapper getBiomeWrapper(Object[] objectArray, IDhApiLevelWrapper levelWrapper)
{ {
// confirm the API level wrapper is also a Core wrapper // confirm the API level wrapper is also a Core wrapper
if (!(levelWrapper instanceof ILevelWrapper)) if (!(levelWrapper instanceof ILevelWrapper))
@@ -322,19 +403,29 @@ public class WrapperFactory implements IWrapperFactory
//#if MC_VER <= MC_1_XX_X
if (objectArray.length != 1) if (objectArray.length != 1)
{ {
throw new ClassCastException(createBlockStateWrapperErrorMessage(objectArray)); throw new ClassCastException(createBlockStateWrapperErrorMessage(objectArray));
} }
if (!(objectArray[0] instanceof BlockState))
boolean blockClassCorrect;
#if MC_VER <= MC_1_12_2
blockClassCorrect = (objectArray[0] instanceof IBlockState);
#else
blockClassCorrect = (objectArray[0] instanceof BlockState);
#endif
if (!blockClassCorrect)
{ {
throw new ClassCastException(createBlockStateWrapperErrorMessage(objectArray)); throw new ClassCastException(createBlockStateWrapperErrorMessage(objectArray));
} }
#if MC_VER <= MC_1_12_2
IBlockState blockState = (IBlockState) objectArray[0];
return BlockStateWrapper.fromBlockState(blockState, coreLevelWrapper);
#else
BlockState blockState = (BlockState) objectArray[0]; BlockState blockState = (BlockState) objectArray[0];
return BlockStateWrapper.fromBlockState(blockState, coreLevelWrapper); return BlockStateWrapper.fromBlockState(blockState, coreLevelWrapper);
//#endif #endif
} }
/** /**
* Note: when this is updated for different MC versions, * Note: when this is updated for different MC versions,
@@ -344,7 +435,9 @@ public class WrapperFactory implements IWrapperFactory
{ {
String[] expectedClassNames; String[] expectedClassNames;
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 #if MC_VER <= MC_1_12_2
expectedClassNames = new String[] { IBlockState.class.getName() };
#elif MC_VER <= MC_1_17_1
expectedClassNames = new String[] { Biome.class.getName() }; expectedClassNames = new String[] { Biome.class.getName() };
#else #else
expectedClassNames = new String[] { Holder.class.getName()+"<"+Biome.class.getName()+">" }; expectedClassNames = new String[] { Holder.class.getName()+"<"+Biome.class.getName()+">" };
@@ -357,7 +450,6 @@ public class WrapperFactory implements IWrapperFactory
//================// //================//
// helper methods // // helper methods //
//================// //================//
@@ -367,8 +459,8 @@ public class WrapperFactory implements IWrapperFactory
{ {
// error header // error header
StringBuilder message = new StringBuilder( StringBuilder message = new StringBuilder(
wrapperName + " creation failed. \n" + wrapperName + " creation failed. \n" +
"Expected object array parameters: \n"); "Expected object array parameters: \n");
// expected parameters // expected parameters
@@ -1,5 +1,5 @@
package com.seibel.distanthorizons.common.wrappers.block; package com.seibel.distanthorizons.common.wrappers.block;
#if MC_VER > MC_1_12_2
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dataObjects.BlockBiomeWrapperPair; import com.seibel.distanthorizons.core.dataObjects.BlockBiomeWrapperPair;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
@@ -11,10 +11,14 @@ import com.seibel.distanthorizons.core.util.FullDataPointUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
#if MC_VER <= MC_1_12_2
import net.minecraft.world.biome.Biome;
#else
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.world.level.ColorResolver; import net.minecraft.world.level.ColorResolver;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
#endif
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@@ -45,8 +49,6 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
#endif #endif
private static final ConcurrentHashMap<BlockBiomeWrapperPair, Integer> COLOR_BY_BLOCK_BIOME_PAIR = new ConcurrentHashMap<>(); private static final ConcurrentHashMap<BlockBiomeWrapperPair, Integer> COLOR_BY_BLOCK_BIOME_PAIR = new ConcurrentHashMap<>();
/** returned if the color cache is incomplete */
public static final int INVALID_COLOR = -1;
protected BiomeWrapper biomeWrapper; protected BiomeWrapper biomeWrapper;
@@ -98,7 +100,7 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
* Can be called by DH directly, skipping some of MC's logic * Can be called by DH directly, skipping some of MC's logic
* to speed up tint getting slightly. * to speed up tint getting slightly.
* *
* @return {@link AbstractDhTintGetter#INVALID_COLOR} if any of the biomes needed for this position * @return {@link ClientBlockStateColorCache#INVALID_COLOR} if any of the biomes needed for this position
* were not cached. In that case calling {@link AbstractDhTintGetter#getBlockTint(BlockPos, ColorResolver)} * were not cached. In that case calling {@link AbstractDhTintGetter#getBlockTint(BlockPos, ColorResolver)}
* will need to be called by MC's ColorResolver so we can * will need to be called by MC's ColorResolver so we can
* populate the color cache. * populate the color cache.
@@ -159,9 +161,9 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
int id = FullDataPointUtil.getId(dataPoint); int id = FullDataPointUtil.getId(dataPoint);
BiomeWrapper biomeWrapper = (BiomeWrapper) this.fullDataSource.mapping.getBiomeWrapper(id); BiomeWrapper biomeWrapper = (BiomeWrapper) this.fullDataSource.mapping.getBiomeWrapper(id);
int color = this.tryGetClientBiomeColor(colorResolver, biomeWrapper); int color = this.tryGetClientBiomeColor(colorResolver, biomeWrapper);
if (color == INVALID_COLOR) if (color == ClientBlockStateColorCache.INVALID_COLOR)
{ {
return INVALID_COLOR; return ClientBlockStateColorCache.INVALID_COLOR;
} }
@@ -210,7 +212,7 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
// no color resolver is present, // no color resolver is present,
// the cache needs to be populated before // the cache needs to be populated before
// we can use the fast path // we can use the fast path
return INVALID_COLOR; return ClientBlockStateColorCache.INVALID_COLOR;
} }
@@ -363,3 +365,4 @@ public abstract class AbstractDhTintGetter implements BlockAndTintGetter
} }
#endif
@@ -28,12 +28,15 @@ import java.util.concurrent.ConcurrentMap;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import net.minecraft.world.level.Level;
import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1 #if MC_VER > MC_1_12_2
import net.minecraft.world.level.Level;
#endif
#if MC_VER <= MC_1_12_2
#elif MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
#elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2 #elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
@@ -45,14 +48,21 @@ import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
#endif #endif
#if MC_VER <= MC_1_21_10 #if MC_VER <= MC_1_12_2
import net.minecraft.util.ResourceLocation;
#elif MC_VER <= MC_1_21_10
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
#else #else
import net.minecraft.resources.Identifier; import net.minecraft.resources.Identifier;
import net.minecraft.core.component.DataComponentMap; import net.minecraft.core.component.DataComponentMap;
#endif #endif
#if MC_VER <= MC_1_12_2
import net.minecraft.world.biome.Biome;
#else
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
#endif
#if MC_VER >= MC_1_18_2 #if MC_VER >= MC_1_18_2
import net.minecraft.world.level.biome.Biomes; import net.minecraft.world.level.biome.Biomes;
@@ -108,8 +118,13 @@ public class BiomeWrapper implements IBiomeWrapper
//==============// //==============//
// constructors // // constructors //
//==============// //==============//
//region
public static BiomeWrapper getBiomeWrapper(#if MC_VER < MC_1_18_2 Biome #else Holder<Biome> #endif biome, ILevelWrapper levelWrapper) #if MC_VER < MC_1_18_2
public static BiomeWrapper getBiomeWrapper(Biome biome, ILevelWrapper levelWrapper)
#else
public static BiomeWrapper getBiomeWrapper(Holder<Biome> biome, ILevelWrapper levelWrapper)
#endif
{ {
if (biome == null) if (biome == null)
{ {
@@ -129,7 +144,12 @@ public class BiomeWrapper implements IBiomeWrapper
return newWrapper; return newWrapper;
} }
} }
private BiomeWrapper(#if MC_VER < MC_1_18_2 Biome #else Holder<Biome> #endif biome, ILevelWrapper levelWrapper)
#if MC_VER < MC_1_18_2
private BiomeWrapper(Biome biome, ILevelWrapper levelWrapper)
#else
private BiomeWrapper(Holder<Biome> biome, ILevelWrapper levelWrapper)
#endif
{ {
this.biome = biome; this.biome = biome;
this.serialString = this.serialize(levelWrapper); this.serialString = this.serialize(levelWrapper);
@@ -138,11 +158,14 @@ public class BiomeWrapper implements IBiomeWrapper
//LOGGER.trace("Created BiomeWrapper ["+this.serialString+"] for ["+biome+"]"); //LOGGER.trace("Created BiomeWrapper ["+this.serialString+"] for ["+biome+"]");
} }
//endregion
//=========// //=========//
// methods // // methods //
//=========// //=========//
//region
@Override @Override
public String getName() public String getName()
@@ -188,11 +211,14 @@ public class BiomeWrapper implements IBiomeWrapper
@Override @Override
public String toString() { return this.getSerialString(); } public String toString() { return this.getSerialString(); }
//endregion
//=======================// //=======================//
// serialization methods // // serialization methods //
//=======================// //=======================//
//region
public String serialize(ILevelWrapper levelWrapper) public String serialize(ILevelWrapper levelWrapper)
{ {
@@ -219,8 +245,10 @@ public class BiomeWrapper implements IBiomeWrapper
// generate the serial string // // generate the serial string //
#if MC_VER > MC_1_12_2
Level level = (Level)levelWrapper.getWrappedMcObject(); Level level = (Level)levelWrapper.getWrappedMcObject();
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess(); net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
#endif
#if MC_VER <= MC_1_21_10 #if MC_VER <= MC_1_21_10
ResourceLocation resourceLocation; ResourceLocation resourceLocation;
@@ -228,7 +256,9 @@ public class BiomeWrapper implements IBiomeWrapper
Identifier resourceLocation; Identifier resourceLocation;
#endif #endif
#if MC_VER <= MC_1_17_1 #if MC_VER <= MC_1_12_2
resourceLocation = biome.getRegistryName();
#elif MC_VER <= MC_1_17_1
resourceLocation = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).getKey(this.biome); resourceLocation = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).getKey(this.biome);
#elif MC_VER <= MC_1_19_2 #elif MC_VER <= MC_1_19_2
resourceLocation = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).getKey(this.biome.value()); resourceLocation = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).getKey(this.biome.value());
@@ -293,11 +323,16 @@ public class BiomeWrapper implements IBiomeWrapper
{ {
try try
{ {
#if MC_VER > MC_1_12_2
Level level = (Level) levelWrapper.getWrappedMcObject(); Level level = (Level) levelWrapper.getWrappedMcObject();
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess(); net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
#endif
#if MC_VER <= MC_1_12_2
BiomeDeserializeResult deserializeResult = deserializeBiome(resourceLocationString);
#else
BiomeDeserializeResult deserializeResult = deserializeBiome(resourceLocationString, registryAccess); BiomeDeserializeResult deserializeResult = deserializeBiome(resourceLocationString, registryAccess);
#endif
if (!deserializeResult.success) if (!deserializeResult.success)
@@ -325,7 +360,11 @@ public class BiomeWrapper implements IBiomeWrapper
} }
} }
#if MC_VER <= MC_1_12_2
public static BiomeDeserializeResult deserializeBiome(String resourceLocationString) throws IOException
#else
public static BiomeDeserializeResult deserializeBiome(String resourceLocationString, net.minecraft.core.RegistryAccess registryAccess) throws IOException public static BiomeDeserializeResult deserializeBiome(String resourceLocationString, net.minecraft.core.RegistryAccess registryAccess) throws IOException
#endif
{ {
// parse the resource location // parse the resource location
int separatorIndex = resourceLocationString.indexOf(":"); int separatorIndex = resourceLocationString.indexOf(":");
@@ -356,7 +395,10 @@ public class BiomeWrapper implements IBiomeWrapper
boolean success; boolean success;
#if MC_VER <= MC_1_17_1 #if MC_VER <= MC_1_12_2
Biome biome = Biome.REGISTRY.getObject(resourceLocation);
success = (biome != null);
#elif MC_VER <= MC_1_17_1
Biome biome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation); Biome biome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation);
success = (biome != null); success = (biome != null);
#elif MC_VER <= MC_1_19_2 #elif MC_VER <= MC_1_19_2
@@ -400,10 +442,14 @@ public class BiomeWrapper implements IBiomeWrapper
return new BiomeDeserializeResult(success, biome); return new BiomeDeserializeResult(success, biome);
} }
//endregion
//================// //================//
// helper classes // // helper classes //
//================// //================//
//region
public static class BiomeDeserializeResult public static class BiomeDeserializeResult
{ {
@@ -413,14 +459,21 @@ public class BiomeWrapper implements IBiomeWrapper
public final Biome biome; public final Biome biome;
#else #else
public final Holder<Biome> biome; public final Holder<Biome> biome;
#endif #endif
public BiomeDeserializeResult(boolean success, #if MC_VER < MC_1_18_2 Biome #else Holder<Biome> #endif biome) #if MC_VER < MC_1_18_2
public BiomeDeserializeResult(boolean success, Biome biome)
#else
public BiomeDeserializeResult(boolean success, Holder<Biome> biome)
#endif
{ {
this.success = success; this.success = success;
this.biome = biome; this.biome = biome;
} }
} }
//endregion
} }
@@ -32,12 +32,20 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrappe
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector; import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
#if MC_VER <= MC_1_12_2
import net.minecraft.block.*;
import net.minecraft.init.Blocks;
import net.minecraft.block.state.IBlockState;
import net.minecraft.block.properties.IProperty;
import net.minecraftforge.fluids.IFluidBlock;
#else
import net.minecraft.tags.BlockTags; import net.minecraft.tags.BlockTags;
import net.minecraft.world.level.block.BeaconBeamBlock; import net.minecraft.world.level.block.BeaconBeamBlock;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
#endif
import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLogger;
import java.awt.*; import java.awt.*;
@@ -61,7 +69,7 @@ import net.minecraft.world.level.Level;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.world.level.EmptyBlockGetter; import net.minecraft.world.level.EmptyBlockGetter;
#else #elif MC_VER > MC_1_12_2
import net.minecraft.tags.TagKey; import net.minecraft.tags.TagKey;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@@ -70,12 +78,15 @@ import net.minecraft.world.level.EmptyBlockGetter;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
#endif #endif
#if MC_VER <= MC_1_21_10 #if MC_VER <= MC_1_12_2
import net.minecraft.util.ResourceLocation;
#elif MC_VER <= MC_1_21_10
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
#else #else
import net.minecraft.resources.Identifier; import net.minecraft.resources.Identifier;
#endif #endif
public class BlockStateWrapper implements IBlockStateWrapper public class BlockStateWrapper implements IBlockStateWrapper
{ {
/** example "minecraft:water" */ /** example "minecraft:water" */
@@ -87,7 +98,11 @@ public class BlockStateWrapper implements IBlockStateWrapper
// must be defined before AIR, otherwise a null pointer will be thrown // must be defined before AIR, otherwise a null pointer will be thrown
private static final DhLogger LOGGER = new DhLoggerBuilder().build(); private static final DhLogger LOGGER = new DhLoggerBuilder().build();
#if MC_VER <= MC_1_12_2
public static final ConcurrentHashMap<IBlockState, BlockStateWrapper> WRAPPER_BY_BLOCK_STATE = new ConcurrentHashMap<>();
#else
public static final ConcurrentHashMap<BlockState, BlockStateWrapper> WRAPPER_BY_BLOCK_STATE = new ConcurrentHashMap<>(); public static final ConcurrentHashMap<BlockState, BlockStateWrapper> WRAPPER_BY_BLOCK_STATE = new ConcurrentHashMap<>();
#endif
public static final ConcurrentHashMap<String, BlockStateWrapper> WRAPPER_BY_RESOURCE_LOCATION = new ConcurrentHashMap<>(); public static final ConcurrentHashMap<String, BlockStateWrapper> WRAPPER_BY_RESOURCE_LOCATION = new ConcurrentHashMap<>();
public static final String AIR_STRING = "AIR"; public static final String AIR_STRING = "AIR";
@@ -114,7 +129,11 @@ public class BlockStateWrapper implements IBlockStateWrapper
// properties // // properties //
@Nullable @Nullable
#if MC_VER <= MC_1_12_2
public final IBlockState blockState;
#else
public final BlockState blockState; public final BlockState blockState;
#endif
/** technically final, but since it requires a method call to generate it can't be marked as such */ /** technically final, but since it requires a method call to generate it can't be marked as such */
private String serialString; private String serialString;
private final int hashCode; private final int hashCode;
@@ -139,27 +158,71 @@ public class BlockStateWrapper implements IBlockStateWrapper
// constructors // // constructors //
//==============// //==============//
//region //region
/** /**
* Can be faster than {@link BlockStateWrapper#fromBlockState(BlockState, ILevelWrapper)} * Can be faster than BlockStateWrapper#fromBlockState(BlockState, ILevelWrapper)
* in cases where the same block state is expected to be referenced multiple times. * in cases where the same block state is expected to be referenced multiple times.
*/ */
#if MC_VER <= MC_1_12_2
public static BlockStateWrapper fromBlockState(IBlockState blockState, ILevelWrapper levelWrapper, IBlockStateWrapper guess)
#else
public static BlockStateWrapper fromBlockState(BlockState blockState, ILevelWrapper levelWrapper, IBlockStateWrapper guess) public static BlockStateWrapper fromBlockState(BlockState blockState, ILevelWrapper levelWrapper, IBlockStateWrapper guess)
#endif
{ {
BlockState guessBlockState = (guess == null || guess.isAir()) ? null : (BlockState) guess.getWrappedMcObject(); if (guess == null)
BlockState inputBlockState = (blockState == null || blockState.isAir()) ? null : blockState;
if (guess instanceof BlockStateWrapper
&& guessBlockState == inputBlockState)
{
return (BlockStateWrapper) guess;
}
else
{ {
return fromBlockState(blockState, levelWrapper); return fromBlockState(blockState, levelWrapper);
} }
// guess block state
BlockStateWrapper wrapperGuess = (BlockStateWrapper) guess;
#if MC_VER <= MC_1_12_2
IBlockState guessBlockState;
#else
BlockState guessBlockState;
#endif
if(isAir(wrapperGuess.blockState))
{
guessBlockState = null;
}
else
{
#if MC_VER <= MC_1_12_2
guessBlockState = (IBlockState) guess.getWrappedMcObject();
#else
guessBlockState = (BlockState) guess.getWrappedMcObject();
#endif
}
// input block state
#if MC_VER <= MC_1_12_2
IBlockState inputBlockState;
#else
BlockState inputBlockState;
#endif
if (isAir(blockState))
{
inputBlockState = null;
}
else
{
inputBlockState = blockState;
}
if (guessBlockState == inputBlockState)
{
return (BlockStateWrapper) guess;
}
return fromBlockState(blockState, levelWrapper);
} }
#if MC_VER <= MC_1_12_2
public static BlockStateWrapper fromBlockState(@Nullable IBlockState blockState, ILevelWrapper levelWrapper)
#else
public static BlockStateWrapper fromBlockState(@Nullable BlockState blockState, ILevelWrapper levelWrapper) public static BlockStateWrapper fromBlockState(@Nullable BlockState blockState, ILevelWrapper levelWrapper)
#endif
{ {
// air is a special case // air is a special case
if (isAir(blockState)) if (isAir(blockState))
@@ -208,9 +271,12 @@ public class BlockStateWrapper implements IBlockStateWrapper
} }
} }
} }
private BlockStateWrapper(
@Nullable BlockState blockState, ILevelWrapper levelWrapper, #if MC_VER <= MC_1_12_2
@Nullable DhApiBlockStateWrapperCreatedEvent.EventParam overrideEventParam) private BlockStateWrapper(@Nullable IBlockState blockState, ILevelWrapper levelWrapper, @Nullable DhApiBlockStateWrapperCreatedEvent.EventParam overrideEventParam)
#else
private BlockStateWrapper(@Nullable BlockState blockState, ILevelWrapper levelWrapper, @Nullable DhApiBlockStateWrapperCreatedEvent.EventParam overrideEventParam)
#endif
{ {
this.blockState = blockState; this.blockState = blockState;
this.serialString = serialize(blockState, levelWrapper); this.serialString = serialize(blockState, levelWrapper);
@@ -228,11 +294,13 @@ public class BlockStateWrapper implements IBlockStateWrapper
} }
else else
{ {
#if MC_VER < MC_1_20_1 #if MC_VER <= MC_1_12_2
this.isLiquid = this.blockState.getMaterial().isLiquid() || !this.blockState.getFluidState().isEmpty(); this.isLiquid = this.blockState.getMaterial().isLiquid() || this.blockState.getBlock() instanceof IFluidBlock;
#else #elif MC_VER < MC_1_20_1
this.isLiquid = this.blockState.getMaterial().isLiquid() || !this.blockState.getFluidState().isEmpty();
#else
this.isLiquid = !this.blockState.getFluidState().isEmpty(); this.isLiquid = !this.blockState.getFluidState().isEmpty();
#endif #endif
} }
} }
@@ -332,9 +400,21 @@ public class BlockStateWrapper implements IBlockStateWrapper
&& !this.isBeaconBlock) && !this.isBeaconBlock)
{ {
Block block = this.blockState.getBlock(); Block block = this.blockState.getBlock();
int colorInt;
#if MC_VER <= MC_1_12_2
if (block instanceof BlockStainedGlass)
{
colorInt = blockState.getValue(BlockStainedGlass.COLOR).getColorValue();
beaconTintColor = ColorUtil.toColorObjRGB(colorInt);
}
else if (block instanceof BlockStainedGlassPane)
{
colorInt = blockState.getValue(BlockStainedGlassPane.COLOR).getColorValue();
beaconTintColor = ColorUtil.toColorObjRGB(colorInt);
}
#else
if (block instanceof BeaconBeamBlock) if (block instanceof BeaconBeamBlock)
{ {
int colorInt;
#if MC_VER <= MC_1_19_4 #if MC_VER <= MC_1_19_4
colorInt = ((BeaconBeamBlock) block).getColor().getMaterialColor().col; colorInt = ((BeaconBeamBlock) block).getColor().getMaterialColor().col;
#else #else
@@ -343,6 +423,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
beaconTintColor = ColorUtil.toColorObjRGB(colorInt); beaconTintColor = ColorUtil.toColorObjRGB(colorInt);
} }
#endif
} }
this.beaconTintColor = beaconTintColor; this.beaconTintColor = beaconTintColor;
@@ -392,8 +473,10 @@ public class BlockStateWrapper implements IBlockStateWrapper
if (this.blockState != null) if (this.blockState != null)
{ {
int mcColor = 0; int mcColor = 0;
#if MC_VER < MC_1_20_1 #if MC_VER <= MC_1_12_2
mcColor = this.blockState.getMaterial().getMaterialMapColor().colorValue;
#elif MC_VER < MC_1_20_1
mcColor = this.blockState.getMaterial().getColor().col; mcColor = this.blockState.getMaterial().getColor().col;
#else #else
mcColor = this.blockState.getMapColor(EmptyBlockGetter.INSTANCE, BlockPos.ZERO).col; mcColor = this.blockState.getMapColor(EmptyBlockGetter.INSTANCE, BlockPos.ZERO).col;
@@ -420,7 +503,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
#if MC_VER < MC_1_20_1 #if MC_VER < MC_1_20_1
this.isSolid = this.blockState.getMaterial().isSolid(); this.isSolid = this.blockState.getMaterial().isSolid();
#else #else
this.isSolid = !this.blockState.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO).isEmpty(); this.isSolid = !this.blockState.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO).isEmpty();
#endif #endif
} }
} }
@@ -431,76 +514,193 @@ public class BlockStateWrapper implements IBlockStateWrapper
// static constructor helpers // // static constructor helpers //
//region //region
private static EDhApiBlockMaterial calculateEDhApiBlockMaterialId( #if MC_VER <= MC_1_12_2
@Nullable BlockState blockState, private static EDhApiBlockMaterial calculateEDhApiBlockMaterialId(@Nullable IBlockState blockState, String lowercaseSerialString, boolean isLiquid)
String lowercaseSerialString, #else
boolean isLiquid private static EDhApiBlockMaterial calculateEDhApiBlockMaterialId(@Nullable BlockState blockState, String lowercaseSerialString, boolean isLiquid)
) #endif
{ {
if (blockState == null) if (isAir(blockState))
{ {
return EDhApiBlockMaterial.AIR; return EDhApiBlockMaterial.AIR;
} }
if (blockState.is(BlockTags.LEAVES)
//========//
// leaves //
//========//
//region
boolean isLeafBlock;
#if MC_VER <= MC_1_12_2
isLeafBlock = blockState.getBlock() instanceof BlockLeaves;
#else
isLeafBlock = blockState.is(BlockTags.LEAVES);
#endif
if (isLeafBlock
|| lowercaseSerialString.contains("bamboo") || lowercaseSerialString.contains("bamboo")
|| lowercaseSerialString.contains("cactus") || lowercaseSerialString.contains("cactus")
|| lowercaseSerialString.contains("chorus_flower") || lowercaseSerialString.contains("chorus_flower")
|| lowercaseSerialString.contains("mushroom") || lowercaseSerialString.contains("mushroom")
) )
{ {
return EDhApiBlockMaterial.LEAVES; return EDhApiBlockMaterial.LEAVES;
} }
else if (blockState.is(Blocks.LAVA))
//endregion
//======//
// lava //
//======//
//region
boolean isLavaBlock;
#if MC_VER <= MC_1_12_2
isLavaBlock = blockState.getBlock() == Blocks.LAVA || blockState.getBlock() == Blocks.FLOWING_LAVA;
#else
isLavaBlock = blockState.is(Blocks.LAVA);
#endif
if (isLavaBlock)
{ {
return EDhApiBlockMaterial.LAVA; return EDhApiBlockMaterial.LAVA;
} }
else if (isLiquid
|| blockState.is(Blocks.WATER)) //endregion
//=======//
// water //
//=======//
//region
boolean isWaterBlock;
#if MC_VER <= MC_1_12_2
isWaterBlock = blockState.getBlock() == Blocks.WATER || blockState.getBlock() == Blocks.FLOWING_WATER;
#else
isWaterBlock = blockState.is(Blocks.WATER);
#endif
if (isLiquid
|| isWaterBlock)
{ {
return EDhApiBlockMaterial.WATER; return EDhApiBlockMaterial.WATER;
} }
else if (blockState.getSoundType() == SoundType.WOOD
//endregion
//======//
// wood //
//======//
//region
boolean isWoodSoundingBlock;
#if MC_VER <= MC_1_12_2
isWoodSoundingBlock = blockState.getBlock().getSoundType() == SoundType.WOOD;
#else
isWoodSoundingBlock = blockState.getSoundType() == SoundType.WOOD;
#endif
boolean isCherryWood;
#if MC_VER <= MC_1_19_2
isCherryWood = false;
#else
isCherryWood = blockState.getSoundType() == SoundType.CHERRY_WOOD;
#endif
if (isWoodSoundingBlock
|| lowercaseSerialString.contains("root") || lowercaseSerialString.contains("root")
#if MC_VER >= MC_1_19_4 || isCherryWood
|| blockState.getSoundType() == SoundType.CHERRY_WOOD )
#endif
)
{ {
return EDhApiBlockMaterial.WOOD; return EDhApiBlockMaterial.WOOD;
} }
else if (blockState.getSoundType() == SoundType.METAL
#if MC_VER >= MC_1_19_2 //endregion
|| blockState.getSoundType() == SoundType.COPPER
#endif
#if MC_VER >= MC_1_20_4
|| blockState.getSoundType() == SoundType.COPPER_BULB //=======//
|| blockState.getSoundType() == SoundType.COPPER_GRATE // metal //
#endif //=======//
) //region
boolean isMetalSoundingBlock;
#if MC_VER <= MC_1_12_2
isMetalSoundingBlock = blockState.getBlock().getSoundType() == SoundType.METAL;
#else
isMetalSoundingBlock = blockState.getSoundType() == SoundType.METAL;
#endif
boolean isCopperSounding;
#if MC_VER <= MC_1_18_2
isCopperSounding = false;
#elif MC_VER <= MC_1_20_2
isCopperSounding = blockState.getSoundType() == SoundType.COPPER;
#else
isCopperSounding
= blockState.getSoundType() == SoundType.COPPER
|| blockState.getSoundType() == SoundType.COPPER_BULB
|| blockState.getSoundType() == SoundType.COPPER_GRATE;
#endif
if (isMetalSoundingBlock
|| isCopperSounding)
{ {
return EDhApiBlockMaterial.METAL; return EDhApiBlockMaterial.METAL;
} }
else if (
lowercaseSerialString.contains("grass_block") //endregion
|| lowercaseSerialString.contains("grass_slab")
)
//=======//
// grass //
//=======//
//region
if (lowercaseSerialString.contains("grass_block")
|| lowercaseSerialString.contains("grass_slab")
)
{ {
return EDhApiBlockMaterial.GRASS; return EDhApiBlockMaterial.GRASS;
} }
else if (
//endregion
//======//
// dirt //
//======//
//region
if (
lowercaseSerialString.contains("dirt") lowercaseSerialString.contains("dirt")
|| lowercaseSerialString.contains("gravel") || lowercaseSerialString.contains("gravel")
|| lowercaseSerialString.contains("mud") || lowercaseSerialString.contains("mud")
|| lowercaseSerialString.contains("podzol") || lowercaseSerialString.contains("podzol")
|| lowercaseSerialString.contains("mycelium") || lowercaseSerialString.contains("mycelium")
) )
{ {
return EDhApiBlockMaterial.DIRT; return EDhApiBlockMaterial.DIRT;
} }
//endregion
//===========//
// deepslate //
//===========//
//region
#if MC_VER >= MC_1_17_1 #if MC_VER >= MC_1_17_1
else if (blockState.getSoundType() == SoundType.DEEPSLATE if (blockState.getSoundType() == SoundType.DEEPSLATE
|| blockState.getSoundType() == SoundType.DEEPSLATE_BRICKS || blockState.getSoundType() == SoundType.DEEPSLATE_BRICKS
|| blockState.getSoundType() == SoundType.DEEPSLATE_TILES || blockState.getSoundType() == SoundType.DEEPSLATE_TILES
|| blockState.getSoundType() == SoundType.POLISHED_DEEPSLATE || blockState.getSoundType() == SoundType.POLISHED_DEEPSLATE
@@ -509,41 +709,75 @@ public class BlockStateWrapper implements IBlockStateWrapper
return EDhApiBlockMaterial.DEEPSLATE; return EDhApiBlockMaterial.DEEPSLATE;
} }
#endif #endif
else if (lowercaseSerialString.contains("snow"))
{ //endregion
return EDhApiBlockMaterial.SNOW;
}
else if (lowercaseSerialString.contains("sand"))
{ //============//
return EDhApiBlockMaterial.SAND; // netherrack //
} //============//
else if (lowercaseSerialString.contains("terracotta")) //region
{
return EDhApiBlockMaterial.TERRACOTTA; boolean isNetherRack;
} #if MC_VER <= MC_1_12_2
else if (blockState.is(BlockTags.BASE_STONE_NETHER)) isNetherRack = blockState.getBlock() == Blocks.NETHERRACK;
#else
isNetherRack = blockState.is(BlockTags.BASE_STONE_NETHER);
#endif
if (isNetherRack)
{ {
return EDhApiBlockMaterial.NETHER_STONE; return EDhApiBlockMaterial.NETHER_STONE;
} }
else if (lowercaseSerialString.contains("stone")
//endregion
//=============//
// misc/simple //
//=============//
//region
if (lowercaseSerialString.contains("snow"))
{
return EDhApiBlockMaterial.SNOW;
}
if (lowercaseSerialString.contains("sand"))
{
return EDhApiBlockMaterial.SAND;
}
if (lowercaseSerialString.contains("terracotta"))
{
return EDhApiBlockMaterial.TERRACOTTA;
}
if (lowercaseSerialString.contains("stone")
|| lowercaseSerialString.contains("ore")) || lowercaseSerialString.contains("ore"))
{ {
return EDhApiBlockMaterial.STONE; return EDhApiBlockMaterial.STONE;
} }
else if (blockState.getLightEmission() > 0)
if (getLightEmission(blockState) > 0)
{ {
return EDhApiBlockMaterial.ILLUMINATED; return EDhApiBlockMaterial.ILLUMINATED;
} }
else
{ //endregion
return EDhApiBlockMaterial.UNKNOWN;
}
return EDhApiBlockMaterial.UNKNOWN;
} }
private static int calculateOpacity( #if MC_VER <= MC_1_12_2
@Nullable BlockState blockState, private static int calculateOpacity(@Nullable IBlockState blockState, boolean isAir, boolean isLiquid)
boolean isAir, boolean isLiquid #else
) private static int calculateOpacity(@Nullable BlockState blockState, boolean isAir, boolean isLiquid)
#endif
{ {
// get block properties (defaults to the values used by air) // get block properties (defaults to the values used by air)
boolean canOcclude = getCanOcclude(blockState); boolean canOcclude = getCanOcclude(blockState);
@@ -582,24 +816,40 @@ public class BlockStateWrapper implements IBlockStateWrapper
return opacity; return opacity;
} }
#if MC_VER <= MC_1_12_2
private static boolean getCanOcclude(@Nullable IBlockState blockState)
#else
private static boolean getCanOcclude(@Nullable BlockState blockState) private static boolean getCanOcclude(@Nullable BlockState blockState)
#endif
{ {
// defaults to the value used by air // defaults to the value used by air
boolean canOcclude = false; boolean canOcclude = false;
if (blockState != null) if (blockState != null)
{ {
#if MC_VER <= MC_1_12_2
canOcclude = blockState.getMaterial().isSolid();
#else
canOcclude = blockState.canOcclude(); canOcclude = blockState.canOcclude();
#endif
} }
return canOcclude; return canOcclude;
} }
#if MC_VER <= MC_1_12_2
private static boolean getPropagatesSkyLightDown(@Nullable IBlockState blockState)
#else
private static boolean getPropagatesSkyLightDown(@Nullable BlockState blockState) private static boolean getPropagatesSkyLightDown(@Nullable BlockState blockState)
#endif
{ {
// defaults to the value used by air // defaults to the value used by air
boolean propagatesSkyLightDown = true; boolean propagatesSkyLightDown = true;
if (blockState != null) if (blockState != null)
{ {
#if MC_VER < MC_1_21_3 #if MC_VER <= MC_1_12_2
propagatesSkyLightDown = blockState.getBlock().getLightOpacity(blockState) == 0;
#elif MC_VER < MC_1_21_3
propagatesSkyLightDown = blockState.propagatesSkylightDown(EmptyBlockGetter.INSTANCE, BlockPos.ZERO); propagatesSkyLightDown = blockState.propagatesSkylightDown(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
#else #else
propagatesSkyLightDown = blockState.propagatesSkylightDown(); propagatesSkyLightDown = blockState.propagatesSkylightDown();
@@ -659,8 +909,10 @@ public class BlockStateWrapper implements IBlockStateWrapper
return waterSurfaceReplacementBlocks; return waterSurfaceReplacementBlocks;
} }
ObjectOpenHashSet<String> baseIgnoredBlock = new ObjectOpenHashSet<>(); ObjectOpenHashSet<String> baseIgnoredBlockResourceSet = new ObjectOpenHashSet<>();
waterSurfaceReplacementBlocks = getAllBlockWrappers(Config.Client.Advanced.Graphics.Culling.waterSurfaceBlockReplacementCsv, baseIgnoredBlock, levelWrapper); waterSurfaceReplacementBlocks = getAllBlockWrappers(Config.Client.Advanced.Graphics.Culling.waterSurfaceBlockReplacementCsv, baseIgnoredBlockResourceSet, levelWrapper);
waterSubsurfaceReplacementBlocks.remove(AIR);
return waterSurfaceReplacementBlocks; return waterSurfaceReplacementBlocks;
} }
public static ObjectOpenHashSet<IBlockStateWrapper> getWaterSubsurfaceReplacementBlocks(ILevelWrapper levelWrapper) public static ObjectOpenHashSet<IBlockStateWrapper> getWaterSubsurfaceReplacementBlocks(ILevelWrapper levelWrapper)
@@ -671,8 +923,12 @@ public class BlockStateWrapper implements IBlockStateWrapper
return waterSubsurfaceReplacementBlocks; return waterSubsurfaceReplacementBlocks;
} }
ObjectOpenHashSet<String> baseIgnoredBlock = new ObjectOpenHashSet<>(); ObjectOpenHashSet<String> baseIgnoredBlockResourceSet = new ObjectOpenHashSet<>();
waterSubsurfaceReplacementBlocks = getAllBlockWrappers(Config.Client.Advanced.Graphics.Culling.waterSubSurfaceBlockReplacementCsv, baseIgnoredBlock, levelWrapper); waterSubsurfaceReplacementBlocks = getAllBlockWrappers(Config.Client.Advanced.Graphics.Culling.waterSubSurfaceBlockReplacementCsv, baseIgnoredBlockResourceSet, levelWrapper);
// air will be present if any invalid resource locations are present
// but we don't want to replace air with water, that'll cause monoliths
waterSubsurfaceReplacementBlocks.remove(AIR);
return waterSubsurfaceReplacementBlocks; return waterSubsurfaceReplacementBlocks;
} }
public static IBlockStateWrapper getWaterBlockStateWrapper(ILevelWrapper levelWrapper) public static IBlockStateWrapper getWaterBlockStateWrapper(ILevelWrapper levelWrapper)
@@ -740,8 +996,17 @@ public class BlockStateWrapper implements IBlockStateWrapper
if (defaultBlockStateToIgnore != AIR) if (defaultBlockStateToIgnore != AIR)
{ {
// add all possible blockstates (to account for light blocks with different light values and such) // add all possible blockstates (to account for light blocks with different light values and such)
#if MC_VER <= MC_1_12_2
List<IBlockState> blockStatesToIgnore = defaultBlockStateToIgnore.blockState.getBlock().getBlockState().getValidStates();
#else
List<BlockState> blockStatesToIgnore = defaultBlockStateToIgnore.blockState.getBlock().getStateDefinition().getPossibleStates(); List<BlockState> blockStatesToIgnore = defaultBlockStateToIgnore.blockState.getBlock().getStateDefinition().getPossibleStates();
#endif
#if MC_VER <= MC_1_12_2
for (IBlockState blockState : blockStatesToIgnore)
#else
for (BlockState blockState : blockStatesToIgnore) for (BlockState blockState : blockStatesToIgnore)
#endif
{ {
BlockStateWrapper newBlockToIgnore = fromBlockState(blockState, levelWrapper); BlockStateWrapper newBlockToIgnore = fromBlockState(blockState, levelWrapper);
blockStateWrappers.add(newBlockToIgnore); blockStateWrappers.add(newBlockToIgnore);
@@ -788,7 +1053,25 @@ public class BlockStateWrapper implements IBlockStateWrapper
public int getOpacity() { return this.opacity; } public int getOpacity() { return this.opacity; }
@Override @Override
public int getLightEmission() { return (this.blockState != null) ? this.blockState.getLightEmission() : 0; } public int getLightEmission() { return getLightEmission(this.blockState); }
#if MC_VER <= MC_1_12_2
public static int getLightEmission(IBlockState blockState)
#else
public static int getLightEmission(BlockState blockState)
#endif
{
if (blockState == null)
{
return 0;
}
#if MC_VER <= MC_1_12_2
return blockState.getLightValue();
#else
return blockState.getLightEmission();
#endif
}
@Override @Override
public String getSerialString() { return this.serialString; } public String getSerialString() { return this.serialString; }
@@ -798,7 +1081,23 @@ public class BlockStateWrapper implements IBlockStateWrapper
@Override @Override
public boolean isAir() { return isAir(this.blockState); } public boolean isAir() { return isAir(this.blockState); }
public static boolean isAir(BlockState blockState) { return blockState == null || blockState.isAir(); } #if MC_VER <= MC_1_12_2
public static boolean isAir(IBlockState blockState)
#else
public static boolean isAir(BlockState blockState)
#endif
{
if (blockState == null)
{
return true;
}
#if MC_VER <= MC_1_12_2
return blockState.getBlock() == Blocks.AIR;
#else
return blockState.isAir();
#endif
}
@Override @Override
public boolean isSolid() { return this.isSolid; } public boolean isSolid() { return this.isSolid; }
@@ -832,7 +1131,11 @@ public class BlockStateWrapper implements IBlockStateWrapper
//=======================// //=======================//
//region //region
#if MC_VER <= MC_1_12_2
private static String serialize(IBlockState blockState, ILevelWrapper levelWrapper)
#else
private static String serialize(BlockState blockState, ILevelWrapper levelWrapper) private static String serialize(BlockState blockState, ILevelWrapper levelWrapper)
#endif
{ {
if (blockState == null) if (blockState == null)
{ {
@@ -854,7 +1157,9 @@ public class BlockStateWrapper implements IBlockStateWrapper
Identifier resourceLocation; Identifier resourceLocation;
#endif #endif
#if MC_VER <= MC_1_17_1 #if MC_VER <= MC_1_12_2
resourceLocation = blockState.getBlock().getRegistryName();
#elif MC_VER <= MC_1_17_1
resourceLocation = Registry.BLOCK.getKey(blockState.getBlock()); resourceLocation = Registry.BLOCK.getKey(blockState.getBlock());
#elif MC_VER <= MC_1_19_2 #elif MC_VER <= MC_1_19_2
resourceLocation = registryAccess.registryOrThrow(Registry.BLOCK_REGISTRY).getKey(blockState.getBlock()); resourceLocation = registryAccess.registryOrThrow(Registry.BLOCK_REGISTRY).getKey(blockState.getBlock());
@@ -953,7 +1258,9 @@ public class BlockStateWrapper implements IBlockStateWrapper
#endif #endif
Block block; Block block;
#if MC_VER <= MC_1_17_1 #if MC_VER <= MC_1_12_2
block = Block.REGISTRY.getObject(resourceLocation);
#elif MC_VER <= MC_1_17_1
block = Registry.BLOCK.get(resourceLocation); block = Registry.BLOCK.get(resourceLocation);
#elif MC_VER <= MC_1_19_2 #elif MC_VER <= MC_1_19_2
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess(); net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
@@ -982,11 +1289,24 @@ public class BlockStateWrapper implements IBlockStateWrapper
// attempt to find the blockstate from all possibilities // attempt to find the blockstate from all possibilities
#if MC_VER <= MC_1_12_2
IBlockState foundState = null;
#else
BlockState foundState = null; BlockState foundState = null;
#endif
if (blockStatePropertiesString != null) if (blockStatePropertiesString != null)
{ {
#if MC_VER <= MC_1_12_2
List<IBlockState> possibleStateList = block.getBlockState().getValidStates();
#else
List<BlockState> possibleStateList = block.getStateDefinition().getPossibleStates(); List<BlockState> possibleStateList = block.getStateDefinition().getPossibleStates();
#endif
#if MC_VER <= MC_1_12_2
for (IBlockState possibleState : possibleStateList)
#else
for (BlockState possibleState : possibleStateList) for (BlockState possibleState : possibleStateList)
#endif
{ {
String possibleStatePropertiesString = serializeBlockStateProperties(possibleState); String possibleStatePropertiesString = serializeBlockStateProperties(possibleState);
if (possibleStatePropertiesString.equals(blockStatePropertiesString)) if (possibleStatePropertiesString.equals(blockStatePropertiesString))
@@ -1010,7 +1330,12 @@ public class BlockStateWrapper implements IBlockStateWrapper
} }
} }
foundState = block.defaultBlockState();
#if MC_VER <= MC_1_12_2
foundState = block.getDefaultState();
#else
foundState = block.defaultBlockState();
#endif
} }
foundWrapper = fromBlockState(foundState, levelWrapper); foundWrapper = fromBlockState(foundState, levelWrapper);
@@ -1035,26 +1360,44 @@ public class BlockStateWrapper implements IBlockStateWrapper
} }
/** used to compare and save BlockStates based on their properties */ /** used to compare and save BlockStates based on their properties */
#if MC_VER <= MC_1_12_2
private static String serializeBlockStateProperties(IBlockState blockState)
#else
private static String serializeBlockStateProperties(BlockState blockState) private static String serializeBlockStateProperties(BlockState blockState)
#endif
{ {
// get the property list for this block (doesn't contain this block state's values, just the names and possible values) // get the property list for this block (doesn't contain this block state's values, just the names and possible values)
java.util.Collection<net.minecraft.world.level.block.state.properties.Property<?>> blockPropertyCollection = blockState.getProperties(); #if MC_VER <= MC_1_12_2
java.util.Collection<IProperty<?>> blockPropertyCollection = blockState.getPropertyKeys();
List<IProperty<?>> sortedBlockPropteryList = new ArrayList<>(blockPropertyCollection);
#else
java.util.Collection<net.minecraft.world.level.block.state.properties.Property<?>> blockPropertyCollection = blockState.getProperties();;
List<net.minecraft.world.level.block.state.properties.Property<?>> sortedBlockPropteryList = new ArrayList<>(blockPropertyCollection);
#endif
// alphabetically sort the list so they are always in the same order // alphabetically sort the list so they are always in the same order
List<net.minecraft.world.level.block.state.properties.Property<?>> sortedBlockPropteryList = new ArrayList<>(blockPropertyCollection);
sortedBlockPropteryList.sort((a, b) -> a.getName().compareTo(b.getName())); sortedBlockPropteryList.sort((a, b) -> a.getName().compareTo(b.getName()));
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
#if MC_VER <= MC_1_12_2
for (IProperty<?> property : sortedBlockPropteryList)
#else
for (net.minecraft.world.level.block.state.properties.Property<?> property : sortedBlockPropteryList) for (net.minecraft.world.level.block.state.properties.Property<?> property : sortedBlockPropteryList)
#endif
{ {
String propertyName = property.getName(); String propertyName = property.getName();
String value = "NULL"; String value = "NULL";
#if MC_VER <= MC_1_12_2
value = blockState.getValue(property).toString();
#else
if (blockState.hasProperty(property)) if (blockState.hasProperty(property))
{ {
value = blockState.getValue(property).toString(); value = blockState.getValue(property).toString();
} }
#endif
stringBuilder.append("{"); stringBuilder.append("{");
stringBuilder.append(propertyName).append(RESOURCE_LOCATION_SEPARATOR).append(value); stringBuilder.append(propertyName).append(RESOURCE_LOCATION_SEPARATOR).append(value);
@@ -32,22 +32,31 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapp
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector; import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureAtlasSprite;
#if MC_VER <= MC_1_12_2
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.EnumFacing;
import net.minecraft.block.BlockRotatedPillar;
import net.minecraft.block.*;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.renderer.color.BlockColors;
import net.minecraft.util.math.BlockPos;
#else
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.world.level.block.*; import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import com.seibel.distanthorizons.core.logging.DhLogger;
import net.minecraft.world.level.block.state.properties.SlabType; import net.minecraft.world.level.block.state.properties.SlabType;
#endif
import com.seibel.distanthorizons.core.logging.DhLogger;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.*;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
#if MC_VER >= MC_1_19_2 #if MC_VER >= MC_1_19_2
import net.minecraft.util.RandomSource; import net.minecraft.util.RandomSource;
#else #else
import java.util.Random;
#endif #endif
#if MC_VER < MC_1_21_5 #if MC_VER < MC_1_21_5
@@ -64,19 +73,32 @@ import net.minecraft.client.color.block.BlockTintSource;
/** /**
* This stores and calculates the colors * This stores and calculates the colors
* the given {@link BlockState} should have based * the given BlockState should have based
* on the given {@link IClientLevelWrapper}. * on the given {@link IClientLevelWrapper}.
* *
* @see ColorUtil * @see ColorUtil
*/ */
public class ClientBlockStateColorCache public class ClientBlockStateColorCache
{ {
private static final DhLogger LOGGER = new DhLoggerBuilder().build(); private static final DhLogger LOGGER = new DhLoggerBuilder().build();
#if MC_VER <= MC_1_12_2
private static final Minecraft MC = Minecraft.getMinecraft();
#else
private static final Minecraft MC = Minecraft.getInstance(); private static final Minecraft MC = Minecraft.getInstance();
#endif
#if MC_VER <= MC_1_12_2
#else
private static final HashSet<BlockState> BLOCK_STATES_THAT_NEED_LEVEL = new HashSet<>(); private static final HashSet<BlockState> BLOCK_STATES_THAT_NEED_LEVEL = new HashSet<>();
#endif
#if MC_VER <= MC_1_12_2
private static final HashSet<IBlockState> BROKEN_BLOCK_STATES = new HashSet<>();
#else
private static final HashSet<BlockState> BROKEN_BLOCK_STATES = new HashSet<>(); private static final HashSet<BlockState> BROKEN_BLOCK_STATES = new HashSet<>();
#endif
/** /**
* Methods using MC's "RandomSource" object aren't thread safe <br> * Methods using MC's "RandomSource" object aren't thread safe <br>
@@ -88,18 +110,33 @@ public class ClientBlockStateColorCache
*/ */
private static final ReentrantLock RESOLVE_LOCK = new ReentrantLock(); private static final ReentrantLock RESOLVE_LOCK = new ReentrantLock();
public static final int INVALID_COLOR = -1;
/** This is the order each direction on a block is processed when attempting to get the texture/color */ /** This is the order each direction on a block is processed when attempting to get the texture/color */
#if MC_VER <= MC_1_12_2
private static final @Nullable EnumFacing[] COLOR_RESOLUTION_DIRECTION_ORDER =
{
EnumFacing.UP,
null, // null represents "unculled" faces, IE the top of farmland
EnumFacing.NORTH,
EnumFacing.EAST,
EnumFacing.WEST,
EnumFacing.SOUTH,
EnumFacing.DOWN
};
#else
private static final @Nullable Direction[] COLOR_RESOLUTION_DIRECTION_ORDER = private static final @Nullable Direction[] COLOR_RESOLUTION_DIRECTION_ORDER =
{ {
Direction.UP, Direction.UP,
null, // null represents "unculled" faces, IE the top of farmland null, // null represents "unculled" faces, IE the top of farmland
Direction.NORTH, Direction.NORTH,
Direction.EAST, Direction.EAST,
Direction.WEST, Direction.WEST,
Direction.SOUTH, Direction.SOUTH,
Direction.DOWN Direction.DOWN
}; };
#endif
private static final int FLOWER_COLOR_SCALE = 5; private static final int FLOWER_COLOR_SCALE = 5;
@@ -113,7 +150,11 @@ public class ClientBlockStateColorCache
#endif #endif
private final IClientLevelWrapper clientLevelWrapper; private final IClientLevelWrapper clientLevelWrapper;
#if MC_VER <= MC_1_12_2
private final IBlockState blockState;
#else
private final BlockState blockState; private final BlockState blockState;
#endif
private final BlockStateWrapper blockStateWrapper; private final BlockStateWrapper blockStateWrapper;
private boolean isColorResolved = false; private boolean isColorResolved = false;
@@ -191,8 +232,10 @@ public class ClientBlockStateColorCache
}; };
// these are threadlocals since AbstractDhTintGetter use local variables to handle color queries // these are threadlocals since AbstractDhTintGetter use local variables to handle color queries
#if MC_VER > MC_1_12_2
private static final ThreadLocal<TintWithoutLevelOverrider> TintWithoutLevelOverrideGetter = ThreadLocal.withInitial(TintWithoutLevelOverrider::new); private static final ThreadLocal<TintWithoutLevelOverrider> TintWithoutLevelOverrideGetter = ThreadLocal.withInitial(TintWithoutLevelOverrider::new);
private static final ThreadLocal<TintGetterOverride> TintOverrideGetter = ThreadLocal.withInitial(TintGetterOverride::new); private static final ThreadLocal<TintGetterOverride> TintOverrideGetter = ThreadLocal.withInitial(TintGetterOverride::new);
#endif
private static final ThreadLocal<DhApiBlockColorOverrideEvent.EventParam> ColorOverrideEventParamGetter = ThreadLocal.withInitial(DhApiBlockColorOverrideEvent.EventParam::new); private static final ThreadLocal<DhApiBlockColorOverrideEvent.EventParam> ColorOverrideEventParamGetter = ThreadLocal.withInitial(DhApiBlockColorOverrideEvent.EventParam::new);
//endregion //endregion
@@ -204,7 +247,11 @@ public class ClientBlockStateColorCache
//=============// //=============//
//region //region
#if MC_VER <= MC_1_12_2
public ClientBlockStateColorCache(IBlockState blockState, IClientLevelWrapper clientLevelWrapper)
#else
public ClientBlockStateColorCache(BlockState blockState, IClientLevelWrapper clientLevelWrapper) public ClientBlockStateColorCache(BlockState blockState, IClientLevelWrapper clientLevelWrapper)
#endif
{ {
this.blockState = blockState; this.blockState = blockState;
this.blockStateWrapper = BlockStateWrapper.fromBlockState(blockState, clientLevelWrapper); this.blockStateWrapper = BlockStateWrapper.fromBlockState(blockState, clientLevelWrapper);
@@ -220,6 +267,7 @@ public class ClientBlockStateColorCache
//===================// //===================//
// color calculation // // color calculation //
//===================// //===================//
//region
private void resolveColors() private void resolveColors()
{ {
@@ -233,17 +281,44 @@ public class ClientBlockStateColorCache
// getQuads() isn't thread safe so we need to put this logic in a lock // getQuads() isn't thread safe so we need to put this logic in a lock
RESOLVE_LOCK.lock(); RESOLVE_LOCK.lock();
if (this.blockState.getFluidState().isEmpty()) #if MC_VER <= MC_1_12_2
if (this.blockState.getRenderType() == EnumBlockRenderType.ENTITYBLOCK_ANIMATED)
{
this.needPostTinting = false;
this.tintIndex = 0;
this.baseColor = ColorUtil.argbToInt(255,
this.blockStateWrapper.getMapColor().getRed(),
this.blockStateWrapper.getMapColor().getGreen(),
this.blockStateWrapper.getMapColor().getBlue());
this.isColorResolved = true;
return;
}
#endif
if (!this.blockStateWrapper.isLiquid())
{ {
// look for the first non-empty direction // look for the first non-empty direction
List<BakedQuad> quads = null; List<BakedQuad> quads = null;
for (Direction direction : COLOR_RESOLUTION_DIRECTION_ORDER)
#if MC_VER <= MC_1_12_2
EnumFacing direction;
#else
Direction direction;
#endif
for (int i = 0; i < COLOR_RESOLUTION_DIRECTION_ORDER.length; i++)
{ {
direction = COLOR_RESOLUTION_DIRECTION_ORDER[i];
quads = this.getQuadsForDirection(direction); quads = this.getQuadsForDirection(direction);
if (quads != null && !quads.isEmpty() if (quads != null && !quads.isEmpty()
&& !( && !(
#if MC_VER <= MC_1_12_2
this.blockState.getBlock() instanceof BlockRotatedPillar
&& direction == EnumFacing.UP
#else
this.blockState.getBlock() instanceof RotatedPillarBlock this.blockState.getBlock() instanceof RotatedPillarBlock
&& direction == Direction.UP && direction == Direction.UP
#endif
) )
) )
{ {
@@ -263,8 +338,10 @@ public class ClientBlockStateColorCache
try try
{ {
BakedQuad firstQuad = quads.get(0); BakedQuad firstQuad = quads.get(0);
#if MC_VER <= MC_1_21_11 #if MC_VER <= MC_1_12_2
this.needPostTinting = firstQuad.hasTintIndex();
#elif MC_VER <= MC_1_21_11
this.needPostTinting = firstQuad.isTinted(); this.needPostTinting = firstQuad.isTinted();
#else #else
this.needPostTinting = firstQuad.materialInfo().isTinted(); this.needPostTinting = firstQuad.materialInfo().isTinted();
@@ -278,7 +355,7 @@ public class ClientBlockStateColorCache
this.tintIndex = firstQuad.materialInfo().tintIndex(); this.tintIndex = firstQuad.materialInfo().tintIndex();
#endif #endif
#if MC_VER < MC_1_17_1 #if MC_VER < MC_1_17_1 && MC_VER > MC_1_12_2
this.baseColor = calculateColorFromTexture( this.baseColor = calculateColorFromTexture(
firstQuad.sprite, firstQuad.sprite,
EColorMode.getColorMode(this.blockState.getBlock())); EColorMode.getColorMode(this.blockState.getBlock()));
@@ -338,20 +415,43 @@ public class ClientBlockStateColorCache
@Nullable @Nullable
private List<BakedQuad> getUnculledQuads() { return this.getQuadsForDirection(null); } private List<BakedQuad> getUnculledQuads() { return this.getQuadsForDirection(null); }
@Nullable @Nullable
#if MC_VER <= MC_1_12_2
private List<BakedQuad> getQuadsForDirection(@Nullable EnumFacing direction)
#else
private List<BakedQuad> getQuadsForDirection(@Nullable Direction direction) private List<BakedQuad> getQuadsForDirection(@Nullable Direction direction)
#endif
{ {
#if MC_VER <= MC_1_12_2
IBlockState effectiveBlockState = this.blockState;
#else
BlockState effectiveBlockState = this.blockState; BlockState effectiveBlockState = this.blockState;
#endif
// if this block is a slab, use it's double variant so we can get the top face, // if this block is a slab, use it's double variant so we can get the top face,
// otherwise the color will use the side, which isn't as accurate // otherwise the color will use the side, which isn't as accurate
#if MC_VER <= MC_1_12_2
if (this.blockState.getBlock() instanceof BlockSlab && !((BlockSlab) this.blockState.getBlock()).isDouble())
{
effectiveBlockState = this.blockState.withProperty(BlockSlab.HALF, BlockSlab.EnumBlockHalf.TOP);
}
#else
if (this.blockState.getBlock() instanceof SlabBlock) if (this.blockState.getBlock() instanceof SlabBlock)
{ {
effectiveBlockState = this.blockState.setValue( SlabBlock.TYPE, SlabType.DOUBLE ); effectiveBlockState = this.blockState.setValue( SlabBlock.TYPE, SlabType.DOUBLE );
} }
#endif
List<BakedQuad> quads; List<BakedQuad> quads;
#if MC_VER < MC_1_21_5 #if MC_VER <= MC_1_12_2
try {
quads = MC.getBlockRendererDispatcher().getModelForState(effectiveBlockState).getQuads(effectiveBlockState, direction, RANDOM.nextLong());
}
catch (Exception e)
{
quads = Collections.emptyList();
}
#elif MC_VER < MC_1_21_5
quads = MC.getModelManager().getBlockModelShaper(). quads = MC.getModelManager().getBlockModelShaper().
getBlockModel(effectiveBlockState).getQuads(effectiveBlockState, direction, RANDOM); getBlockModel(effectiveBlockState).getQuads(effectiveBlockState, direction, RANDOM);
#elif MC_VER <= MC_1_21_11 #elif MC_VER <= MC_1_21_11
@@ -408,10 +508,18 @@ public class ClientBlockStateColorCache
//_ OpenGL RGBA format Java Order: 0xAA BB GG RR //_ OpenGL RGBA format Java Order: 0xAA BB GG RR
tempColor = TextureAtlasSpriteWrapper.getPixelRGBA(texture, 0, u, v); tempColor = TextureAtlasSpriteWrapper.getPixelRGBA(texture, 0, u, v);
#if MC_VER <= MC_1_12_2
int b = (tempColor & 0x000000FF);
int g = (tempColor & 0x0000FF00) >>> 8;
int r = (tempColor & 0x00FF0000) >>> 16;
int a = (tempColor & 0xFF000000) >>> 24;
#else
int r = (tempColor & 0x000000FF); int r = (tempColor & 0x000000FF);
int g = (tempColor & 0x0000FF00) >>> 8; int g = (tempColor & 0x0000FF00) >>> 8;
int b = (tempColor & 0x00FF0000) >>> 16; int b = (tempColor & 0x00FF0000) >>> 16;
int a = (tempColor & 0xFF000000) >>> 24; int a = (tempColor & 0xFF000000) >>> 24;
#endif
int scale = 1; int scale = 1;
if (colorMode == EColorMode.Leaves) if (colorMode == EColorMode.Leaves)
{ {
@@ -468,7 +576,9 @@ public class ClientBlockStateColorCache
} }
private static int getTextureWidth(TextureAtlasSprite texture) private static int getTextureWidth(TextureAtlasSprite texture)
{ {
#if MC_VER < MC_1_19_4 #if MC_VER <= MC_1_12_2
return texture.getIconWidth();
#elif MC_VER < MC_1_19_4
return texture.getWidth(); return texture.getWidth();
#else #else
return texture.contents().width(); return texture.contents().width();
@@ -476,7 +586,9 @@ public class ClientBlockStateColorCache
} }
private static int getTextureHeight(TextureAtlasSprite texture) private static int getTextureHeight(TextureAtlasSprite texture)
{ {
#if MC_VER < MC_1_19_4 #if MC_VER <= MC_1_12_2
return texture.getIconHeight();
#elif MC_VER < MC_1_19_4
return texture.getHeight(); return texture.getHeight();
#else #else
return texture.contents().height(); return texture.contents().height();
@@ -510,7 +622,9 @@ public class ClientBlockStateColorCache
private int getParticleIconColor() private int getParticleIconColor()
{ {
return calculateColorFromTexture( return calculateColorFromTexture(
#if MC_VER <= MC_1_21_11 #if MC_VER <= MC_1_12_2
Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes().getTexture(this.blockState),
#elif MC_VER <= MC_1_21_11
Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(this.blockState), Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(this.blockState),
#else #else
Minecraft.getInstance().getModelManager().getBlockStateModelSet().get(this.blockState).particleMaterial().sprite(), Minecraft.getInstance().getModelManager().getBlockStateModelSet().get(this.blockState).particleMaterial().sprite(),
@@ -518,16 +632,20 @@ public class ClientBlockStateColorCache
EColorMode.getColorMode(this.blockState.getBlock())); EColorMode.getColorMode(this.blockState.getBlock()));
} }
//endregion
//===============// //===============//
// public getter // // public getter //
//===============// //===============//
//region
public int getColor(BiomeWrapper biomeWrapper, FullDataSourceV2 fullDataSource, DhBlockPos blockPos) public int getColor(BiomeWrapper biomeWrapper, FullDataSourceV2 fullDataSource, DhBlockPos blockPos)
{ {
// only get the tint if the block needs to be tinted // only get the tint if the block needs to be tinted
int tintColor = AbstractDhTintGetter.INVALID_COLOR; int tintColor = ClientBlockStateColorCache.INVALID_COLOR;
if (this.needPostTinting) if (this.needPostTinting)
{ {
// don't try tinting blocks that don't support our method of tint getting // don't try tinting blocks that don't support our method of tint getting
@@ -540,28 +658,62 @@ public class ClientBlockStateColorCache
// attempt to get the tint // attempt to get the tint
try try
{ {
#if MC_VER <= MC_1_12_2
// 1.12.2 doesn't have BlockAndTintGetter -> get tintColor from biome
WorldClient world = (WorldClient) this.clientLevelWrapper.getWrappedMcObject();
BlockPos mcPos = new BlockPos(blockPos.getX(), blockPos.getY(), blockPos.getZ());
Block block = this.blockState.getBlock();
if (block instanceof BlockGrass
|| block instanceof BlockBush)
{
tintColor = biomeWrapper.biome.getGrassColorAtPos(mcPos);
}
else if (block instanceof BlockLeaves)
{
tintColor = biomeWrapper.biome.getFoliageColorAtPos(mcPos);
}
else if (block instanceof BlockLiquid) // We don't want lava to fall into the else block
{
if(block == Blocks.WATER
|| block == Blocks.FLOWING_WATER)
{
tintColor = biomeWrapper.biome.getWaterColor();
}
}
else
{
BlockColors blockColors = Minecraft.getMinecraft().getBlockColors();
tintColor = blockColors.colorMultiplier(blockState, world, mcPos, this.tintIndex);
if (tintColor == ClientBlockStateColorCache.INVALID_COLOR)
{
tintColor = blockColors.getColor(blockState, world, mcPos);
}
}
#else
// try to use the fast tint getter logic first // try to use the fast tint getter logic first
if (!BLOCK_STATES_THAT_NEED_LEVEL.contains(this.blockState)) if (!BLOCK_STATES_THAT_NEED_LEVEL.contains(this.blockState))
{ {
try try
{ {
TintWithoutLevelOverrider tintOverride = TintWithoutLevelOverrideGetter.get(); TintWithoutLevelOverrider tintOverride = TintWithoutLevelOverrideGetter.get();
tintOverride.update(biomeWrapper, this.blockStateWrapper, fullDataSource, this.clientLevelWrapper); tintOverride.update(biomeWrapper, this.blockStateWrapper, fullDataSource, this.clientLevelWrapper);
// try using DH's cached tint values first if possible // try using DH's cached tint values first if possible
tintColor = tintOverride.tryGetBlockTint(new DhBlockPosMutable(blockPos)); tintColor = tintOverride.tryGetBlockTint(new DhBlockPosMutable(blockPos));
if (tintColor == AbstractDhTintGetter.INVALID_COLOR) if (tintColor == ClientBlockStateColorCache.INVALID_COLOR)
{ {
// one or more tint values weren't calculated, // one or more tint values weren't calculated,
// we need MC's color resolver // we need MC's color resolver
#if MC_VER <= MC_1_21_11 #if MC_VER <= MC_1_21_11
tintColor = Minecraft.getInstance() tintColor = Minecraft.getInstance()
.getBlockColors() .getBlockColors()
.getColor(this.blockState, .getColor(this.blockState,
tintOverride, // tintOverride will save the result of this query to speed up future queries tintOverride, // tintOverride will save the result of this query to speed up future queries
McObjectConverter.Convert(blockPos), McObjectConverter.Convert(blockPos),
this.tintIndex); this.tintIndex);
#else #else
BlockTintSource tintSource = Minecraft.getInstance() BlockTintSource tintSource = Minecraft.getInstance()
.getBlockColors() .getBlockColors()
.getTintSource(this.blockState, this.tintIndex); .getTintSource(this.blockState, this.tintIndex);
@@ -572,18 +724,12 @@ public class ClientBlockStateColorCache
{ {
BlockPos mcPos = McObjectConverter.Convert(blockPos); BlockPos mcPos = McObjectConverter.Convert(blockPos);
tintColor = tintSource.colorInWorld(this.blockState, tintOverride, mcPos); tintColor = tintSource.colorInWorld(this.blockState, tintOverride, mcPos);
if (tintColor == -1) if (tintColor == ClientBlockStateColorCache.INVALID_COLOR)
{ {
tintColor = tintSource.colorAsTerrainParticle(this.blockState, tintOverride, mcPos); tintColor = tintSource.colorAsTerrainParticle(this.blockState, tintOverride, mcPos);
} }
} }
if (tintColor == -1)
{
// no color found, use the base color
tintColor = AbstractDhTintGetter.INVALID_COLOR;
}
// save this color to speed up future queries // save this color to speed up future queries
TintWithoutLevelOverrider.setStaticColor(this.blockStateWrapper, biomeWrapper, tintColor); TintWithoutLevelOverrider.setStaticColor(this.blockStateWrapper, biomeWrapper, tintColor);
// try to get the blended color with this new information // try to get the blended color with this new information
@@ -593,44 +739,47 @@ public class ClientBlockStateColorCache
} }
catch (Exception e) catch (Exception e)
{ {
#if MC_VER <= MC_1_21_11 #if MC_VER <= MC_1_21_11
// this exception generally occurs if the tint requires other blocks besides itself // 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: [" + biomeWrapper + "] at pos: " + blockPos + ". Error: [" + e.getMessage() + "]. Attempting to use backup method...", e); LOGGER.debug("Unable to use ["+ TintWithoutLevelOverrider.class.getSimpleName()+"] to get the block tint for block: [" + this.blockState + "] and biome: [" + biomeWrapper + "] at pos: " + blockPos + ". Error: [" + e.getMessage() + "]. Attempting to use backup method...", e);
BLOCK_STATES_THAT_NEED_LEVEL.add(this.blockState); BLOCK_STATES_THAT_NEED_LEVEL.add(this.blockState);
#else #else
// only display the error once per block/biome type to reduce log spam // only display the error once per block/biome type to reduce log spam
if (!BROKEN_BLOCK_STATES.contains(this.blockState)) if (!BROKEN_BLOCK_STATES.contains(this.blockState))
{ {
LOGGER.warn("Failed to get block color for block: [" + this.blockState + "] and biome: [" + biomeWrapper + "] at pos: " + blockPos + ". Error: [" + e.getMessage() + "]. Note: future errors for this block/biome will be ignored.", e); LOGGER.warn("Failed to get block color for block: [" + this.blockState + "] and biome: [" + biomeWrapper + "] at pos: " + blockPos + ". Error: [" + e.getMessage() + "]. Note: future errors for this block/biome will be ignored.", e);
BROKEN_BLOCK_STATES.add(this.blockState); BROKEN_BLOCK_STATES.add(this.blockState);
} }
#endif #endif
} }
} }
#endif
// level-specific logic is only needed for MC 1.21.11 and older // level-specific logic is only needed for MC 1.21.11 and older
#if MC_VER <= MC_1_21_11 #if MC_VER <= MC_1_21_11 && MC_VER > MC_1_12_2
// use the level logic only if requested // use the level logic only if requested
if (BLOCK_STATES_THAT_NEED_LEVEL.contains(this.blockState)) if (BLOCK_STATES_THAT_NEED_LEVEL.contains(this.blockState))
{
// the level shouldn't be used all the time due to it breaking some blocks tinting
// specifically oceans don't render correctly
TintGetterOverride tintOverride = TintOverrideGetter.get();
tintOverride.update(biomeWrapper, this.blockStateWrapper, fullDataSource, this.clientLevelWrapper);
tintColor = tintOverride.tryGetBlockTint(new DhBlockPosMutable(blockPos));
if (tintColor == AbstractDhTintGetter.INVALID_COLOR)
{ {
tintColor = Minecraft.getInstance() // the level shouldn't be used all the time due to it breaking some blocks tinting
.getBlockColors() // specifically oceans don't render correctly
.getColor(this.blockState,
tintOverride, TintGetterOverride tintOverride = TintOverrideGetter.get();
McObjectConverter.Convert(blockPos), tintOverride.update(biomeWrapper, this.blockStateWrapper, fullDataSource, this.clientLevelWrapper);
this.tintIndex);
tintColor = tintOverride.tryGetBlockTint(new DhBlockPosMutable(blockPos));
if (tintColor == ClientBlockStateColorCache.INVALID_COLOR)
{
tintColor = Minecraft.getInstance()
.getBlockColors()
.getColor(this.blockState,
tintOverride,
McObjectConverter.Convert(blockPos),
this.tintIndex);
}
} }
} #endif
#endif
} }
catch (Exception e) catch (Exception e)
{ {
@@ -645,7 +794,7 @@ public class ClientBlockStateColorCache
int returnColor; int returnColor;
if (tintColor != AbstractDhTintGetter.INVALID_COLOR) if (tintColor != ClientBlockStateColorCache.INVALID_COLOR)
{ {
returnColor = ColorUtil.multiplyARGBwithRGB(this.baseColor, tintColor); returnColor = ColorUtil.multiplyARGBwithRGB(this.baseColor, tintColor);
} }
@@ -675,6 +824,8 @@ public class ClientBlockStateColorCache
return returnColor; return returnColor;
} }
//endregion
//================// //================//
@@ -692,14 +843,54 @@ public class ClientBlockStateColorCache
static EColorMode getColorMode(Block block) static EColorMode getColorMode(Block block)
{ {
if (block instanceof LeavesBlock)
//========//
// leaves //
//========//
//region
boolean isLeavesBlock;
#if MC_VER <= MC_1_12_2
isLeavesBlock = block instanceof BlockLeaves;
#else
isLeavesBlock = block instanceof LeavesBlock;
#endif
if (isLeavesBlock)
{ {
return Leaves; return Leaves;
} }
if (block instanceof FlowerBlock)
//endregion
//========//
// flower //
//========//
//region
boolean isFlowerBlock;
#if MC_VER <= MC_1_12_2
isFlowerBlock = block instanceof BlockFlower;
#else
isFlowerBlock = block instanceof FlowerBlock;
#endif
if (isFlowerBlock)
{ {
return Flower; return Flower;
} }
//endregion
//=============//
// misc/simple //
//=============//
//region
if (block.toString().contains("glass")) if (block.toString().contains("glass"))
{ {
return Glass; return Glass;
@@ -708,6 +899,11 @@ public class ClientBlockStateColorCache
{ {
return Chisel; return Chisel;
} }
//endregion
return Default; return Default;
} }
} }
@@ -38,7 +38,10 @@ public class TextureAtlasSpriteWrapper
{ {
public static int getPixelRGBA(TextureAtlasSprite sprite, int frameIndex, int x, int y) public static int getPixelRGBA(TextureAtlasSprite sprite, int frameIndex, int x, int y)
{ {
#if MC_VER < MC_1_17_1 #if MC_VER <= MC_1_12_2
int[][] frameData = sprite.getFrameTextureData(frameIndex);
return frameData[0][y * sprite.getIconWidth() + x];
#elif MC_VER < MC_1_17_1
return sprite.mainImage[0].getPixelRGBA( return sprite.mainImage[0].getPixelRGBA(
x + sprite.framesX[frameIndex] * sprite.getWidth(), x + sprite.framesX[frameIndex] * sprite.getWidth(),
y + sprite.framesY[frameIndex] * sprite.getHeight()); y + sprite.framesY[frameIndex] * sprite.getHeight());
@@ -18,7 +18,7 @@
*/ */
package com.seibel.distanthorizons.common.wrappers.block; package com.seibel.distanthorizons.common.wrappers.block;
#if MC_VER > MC_1_12_2
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@@ -189,3 +189,4 @@ public class TintGetterOverride extends AbstractDhTintGetter
} }
#endif
@@ -18,7 +18,7 @@
*/ */
package com.seibel.distanthorizons.common.wrappers.block; package com.seibel.distanthorizons.common.wrappers.block;
#if MC_VER > MC_1_12_2
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.LevelReader;
@@ -109,3 +109,4 @@ public class TintWithoutLevelOverrider extends AbstractDhTintGetter
} }
#endif
@@ -31,12 +31,19 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IMutableBlockPosWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IMutableBlockPosWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
#if MC_VER <= MC_1_12_2
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
#else
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ProtoChunk; import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.level.levelgen.Heightmap;
#endif
import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLogger;
@@ -67,9 +74,10 @@ import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.LevelChunkSection; import net.minecraft.world.level.chunk.LevelChunkSection;
#endif #endif
#if MC_VER <= MC_1_20_4 #if MC_VER <= MC_1_12_2
#elif MC_VER <= MC_1_20_4
import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.ChunkStatus;
#else #elif MC_VER > MC_1_12_2
import net.minecraft.world.level.chunk.status.ChunkStatus; import net.minecraft.world.level.chunk.status.ChunkStatus;
#endif #endif
@@ -86,8 +94,12 @@ public class ChunkWrapper implements IChunkWrapper
private static boolean heightmapThreadWarningLogged = false; private static boolean heightmapThreadWarningLogged = false;
#if MC_VER <= MC_1_12_2
private final Chunk chunk;
#else
private final ChunkAccess chunk; private final ChunkAccess chunk;
#endif
private final DhChunkPos chunkPos; private final DhChunkPos chunkPos;
private final ILevelWrapper wrappedLevel; private final ILevelWrapper wrappedLevel;
@@ -112,13 +124,17 @@ public class ChunkWrapper implements IChunkWrapper
//=============// //=============//
// constructor // // constructor //
//=============// //=============//
//region
/** /**
* Note: this constructor should be very * Note: this constructor should be very
* fast since it will be called frequently on the MC * fast since it will be called frequently on the MC
* server thread and a slow method will cause server lag. * server thread and a slow method will cause server lag.
*/ */
#if MC_VER <= MC_1_12_2
public ChunkWrapper(Chunk chunk, ILevelWrapper wrappedLevel)
#else
public ChunkWrapper(ChunkAccess chunk, ILevelWrapper wrappedLevel) public ChunkWrapper(ChunkAccess chunk, ILevelWrapper wrappedLevel)
#endif
{ {
this.chunk = chunk; this.chunk = chunk;
this.wrappedLevel = wrappedLevel; this.wrappedLevel = wrappedLevel;
@@ -133,15 +149,22 @@ public class ChunkWrapper implements IChunkWrapper
@Override @Override
public ChunkWrapper copy() { return new ChunkWrapper(this.chunk, this.wrappedLevel); } public ChunkWrapper copy() { return new ChunkWrapper(this.chunk, this.wrappedLevel); }
//endregion
//=========// //=========//
// getters // // getters //
//=========// //=========//
//region
@Override @Override
public int getHeight() { return getHeight(this.chunk); } public int getHeight() { return getHeight(this.chunk); }
#if MC_VER <= MC_1_12_2
public static int getHeight(Chunk chunk)
#else
public static int getHeight(ChunkAccess chunk) public static int getHeight(ChunkAccess chunk)
#endif
{ {
#if MC_VER < MC_1_17_1 #if MC_VER < MC_1_17_1
return 255; return 255;
@@ -152,7 +175,11 @@ public class ChunkWrapper implements IChunkWrapper
@Override @Override
public int getInclusiveMinBuildHeight() { return getInclusiveMinBuildHeight(this.chunk); } public int getInclusiveMinBuildHeight() { return getInclusiveMinBuildHeight(this.chunk); }
#if MC_VER <= MC_1_12_2
public static int getInclusiveMinBuildHeight(Chunk chunk)
#else
public static int getInclusiveMinBuildHeight(ChunkAccess chunk) public static int getInclusiveMinBuildHeight(ChunkAccess chunk)
#endif
{ {
#if MC_VER < MC_1_17_1 #if MC_VER < MC_1_17_1
return 0; return 0;
@@ -165,9 +192,15 @@ public class ChunkWrapper implements IChunkWrapper
@Override @Override
public int getExclusiveMaxBuildHeight() { return getExclusiveMaxBuildHeight(this.chunk); } public int getExclusiveMaxBuildHeight() { return getExclusiveMaxBuildHeight(this.chunk); }
#if MC_VER <= MC_1_12_2
public static int getExclusiveMaxBuildHeight(Chunk chunk)
#else
public static int getExclusiveMaxBuildHeight(ChunkAccess chunk) public static int getExclusiveMaxBuildHeight(ChunkAccess chunk)
#endif
{ {
#if MC_VER < MC_1_21_3 #if MC_VER <= MC_1_12_2
return 256;
#elif MC_VER < MC_1_21_3
return chunk.getMaxBuildHeight(); return chunk.getMaxBuildHeight();
#else #else
// +1 since Minecraft made the max value inclusive // +1 since Minecraft made the max value inclusive
@@ -188,7 +221,11 @@ public class ChunkWrapper implements IChunkWrapper
this.minNonEmptyHeight = this.getInclusiveMinBuildHeight(); this.minNonEmptyHeight = this.getInclusiveMinBuildHeight();
// determine the lowest empty section (bottom up) // determine the lowest empty section (bottom up)
#if MC_VER <= MC_1_12_2
ExtendedBlockStorage[] sections = this.chunk.getBlockStorageArray();
#else
LevelChunkSection[] sections = this.chunk.getSections(); LevelChunkSection[] sections = this.chunk.getSections();
#endif
for (int index = 0; index < sections.length; index++) for (int index = 0; index < sections.length; index++)
{ {
if (sections[index] == null) if (sections[index] == null)
@@ -220,7 +257,11 @@ public class ChunkWrapper implements IChunkWrapper
this.maxNonEmptyHeight = this.getExclusiveMaxBuildHeight(); this.maxNonEmptyHeight = this.getExclusiveMaxBuildHeight();
// determine the highest empty section (top down) // determine the highest empty section (top down)
#if MC_VER <= MC_1_12_2
ExtendedBlockStorage[] sections = this.chunk.getBlockStorageArray();
#else
LevelChunkSection[] sections = this.chunk.getSections(); LevelChunkSection[] sections = this.chunk.getSections();
#endif
for (int index = sections.length-1; index >= 0; index--) for (int index = sections.length-1; index >= 0; index--)
{ {
// update at each position to fix using the max height if the chunk is empty // update at each position to fix using the max height if the chunk is empty
@@ -240,11 +281,13 @@ public class ChunkWrapper implements IChunkWrapper
return this.maxNonEmptyHeight; return this.maxNonEmptyHeight;
} }
#if MC_VER <= MC_1_12_2
private static boolean isChunkSectionEmpty(ExtendedBlockStorage section)
#else
private static boolean isChunkSectionEmpty(LevelChunkSection section) private static boolean isChunkSectionEmpty(LevelChunkSection section)
#endif
{ {
#if MC_VER == MC_1_16_5 #if MC_VER <= MC_1_17_1
return section.isEmpty();
#elif MC_VER == MC_1_17_1
return section.isEmpty(); return section.isEmpty();
#else #else
return section.hasOnlyAir(); return section.hasOnlyAir();
@@ -322,7 +365,11 @@ public class ChunkWrapper implements IChunkWrapper
// will be null if we want to use MC heightmaps // will be null if we want to use MC heightmaps
if (this.solidHeightMap == null) if (this.solidHeightMap == null)
{ {
#if MC_VER <= MC_1_12_2
return this.chunk.getHeightValue(xRel, zRel);
#else
return this.chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE).getFirstAvailable(xRel, zRel); return this.chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE).getFirstAvailable(xRel, zRel);
#endif
} }
else else
{ {
@@ -337,19 +384,30 @@ public class ChunkWrapper implements IChunkWrapper
if (this.lightBlockingHeightMap == null) if (this.lightBlockingHeightMap == null)
{ {
#if MC_VER <= MC_1_12_2
return this.chunk.getHeightValue(xRel, zRel);
#else
return this.chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.MOTION_BLOCKING).getFirstAvailable(xRel, zRel); return this.chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.MOTION_BLOCKING).getFirstAvailable(xRel, zRel);
#endif
} }
else else
{ {
return this.lightBlockingHeightMap[xRel][zRel]; return this.lightBlockingHeightMap[xRel][zRel];
} }
} }
@Override @Override
public IBiomeWrapper getBiome(int relX, int relY, int relZ) public IBiomeWrapper getBiome(int relX, int relY, int relZ)
{ {
#if MC_VER < MC_1_17_1 #if MC_VER <= MC_1_12_2
BlockPos.MutableBlockPos blockPos = MUTABLE_BLOCK_POS_REF.get();
blockPos.setPos(relX, relY, relZ);
World world = (World) this.wrappedLevel.getWrappedMcObject();
return BiomeWrapper.getBiomeWrapper(this.chunk.getBiome(blockPos, world.getBiomeProvider()), wrappedLevel);
#elif MC_VER < MC_1_17_1
return BiomeWrapper.getBiomeWrapper(this.chunk.getBiomes().getNoiseBiome( return BiomeWrapper.getBiomeWrapper(this.chunk.getBiomes().getNoiseBiome(
relX >> 2, relY >> 2, relZ >> 2), relX >> 2, relY >> 2, relZ >> 2),
this.wrappedLevel); this.wrappedLevel);
@@ -357,10 +415,6 @@ public class ChunkWrapper implements IChunkWrapper
return BiomeWrapper.getBiomeWrapper(this.chunk.getBiomes().getNoiseBiome( return BiomeWrapper.getBiomeWrapper(this.chunk.getBiomes().getNoiseBiome(
QuartPos.fromBlock(relX), QuartPos.fromBlock(relY), QuartPos.fromBlock(relZ)), QuartPos.fromBlock(relX), QuartPos.fromBlock(relY), QuartPos.fromBlock(relZ)),
this.wrappedLevel); this.wrappedLevel);
#elif MC_VER < MC_1_18_2
return BiomeWrapper.getBiomeWrapper(this.chunk.getNoiseBiome(
QuartPos.fromBlock(relX), QuartPos.fromBlock(relY), QuartPos.fromBlock(relZ)),
this.wrappedLevel);
#else #else
//Now returns a Holder<Biome> instead of Biome //Now returns a Holder<Biome> instead of Biome
return BiomeWrapper.getBiomeWrapper(this.chunk.getNoiseBiome( return BiomeWrapper.getBiomeWrapper(this.chunk.getNoiseBiome(
@@ -376,9 +430,13 @@ public class ChunkWrapper implements IChunkWrapper
BlockPos.MutableBlockPos blockPos = MUTABLE_BLOCK_POS_REF.get(); BlockPos.MutableBlockPos blockPos = MUTABLE_BLOCK_POS_REF.get();
#if MC_VER <= MC_1_12_2
blockPos.setPos(relX, relY, relZ);
#else
blockPos.setX(relX); blockPos.setX(relX);
blockPos.setY(relY); blockPos.setY(relY);
blockPos.setZ(relZ); blockPos.setZ(relZ);
#endif
try try
{ {
@@ -401,9 +459,13 @@ public class ChunkWrapper implements IChunkWrapper
this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, relY, relZ); this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(relX, relY, relZ);
BlockPos.MutableBlockPos pos = (BlockPos.MutableBlockPos)mcBlockPos.getWrappedMcObject(); BlockPos.MutableBlockPos pos = (BlockPos.MutableBlockPos)mcBlockPos.getWrappedMcObject();
#if MC_VER <= MC_1_12_2
pos.setPos(relX, relY, relZ);
#else
pos.setX(relX); pos.setX(relX);
pos.setY(relY); pos.setY(relY);
pos.setZ(relZ); pos.setZ(relZ);
#endif
try try
{ {
@@ -513,8 +575,14 @@ public class ChunkWrapper implements IChunkWrapper
@Override @Override
public DhChunkPos getChunkPos() { return this.chunkPos; } public DhChunkPos getChunkPos() { return this.chunkPos; }
public ChunkAccess getChunk() { return this.chunk; } #if MC_VER <= MC_1_12_2
public Chunk getChunk()
#else
public ChunkAccess getChunk()
#endif
{ return this.chunk; }
#if MC_VER > MC_1_12_2
public void trySetStatus(ChunkStatus status) { trySetStatus(this.getChunk(), status); } public void trySetStatus(ChunkStatus status) { trySetStatus(this.getChunk(), status); }
/** does nothing if the chunk object doesn't support setting it's status */ /** does nothing if the chunk object doesn't support setting it's status */
public static void trySetStatus(ChunkAccess chunk, ChunkStatus status) public static void trySetStatus(ChunkAccess chunk, ChunkStatus status)
@@ -538,21 +606,53 @@ public class ChunkWrapper implements IChunkWrapper
return chunk.getPersistedStatus(); return chunk.getPersistedStatus();
#endif #endif
} }
#endif
@Override @Override
public int getMaxBlockX() { return this.chunk.getPos().getMaxBlockX(); } public int getMaxBlockX()
{
#if MC_VER <= MC_1_12_2
return this.chunk.getPos().getXEnd();
#else
return this.chunk.getPos().getMaxBlockX();
#endif
}
@Override @Override
public int getMaxBlockZ() { return this.chunk.getPos().getMaxBlockZ(); } public int getMaxBlockZ()
{
#if MC_VER <= MC_1_12_2
return this.chunk.getPos().getZEnd();
#else
return this.chunk.getPos().getMaxBlockZ();
#endif
}
@Override @Override
public int getMinBlockX() { return this.chunk.getPos().getMinBlockX(); } public int getMinBlockX()
{
#if MC_VER <= MC_1_12_2
return this.chunk.getPos().getXStart();
#else
return this.chunk.getPos().getMinBlockX();
#endif
}
@Override @Override
public int getMinBlockZ() { return this.chunk.getPos().getMinBlockZ(); } public int getMinBlockZ()
{
#if MC_VER <= MC_1_12_2
return this.chunk.getPos().getZStart();
#else
return this.chunk.getPos().getMinBlockZ();
#endif
}
//endregion
//==========// //==========//
// lighting // // lighting //
//==========// //==========//
//region
@Override @Override
public void setIsDhSkyLightCorrect(boolean isDhLightCorrect) { this.isDhSkyLightCorrect = isDhLightCorrect; } public void setIsDhSkyLightCorrect(boolean isDhLightCorrect) { this.isDhSkyLightCorrect = isDhLightCorrect; }
@@ -629,8 +729,23 @@ public class ChunkWrapper implements IChunkWrapper
{ {
this.blockLightPosList = new ArrayList<>(); this.blockLightPosList = new ArrayList<>();
//1.12.2 doesn't store lights we must bruteforce it
#if MC_VER < MC_1_20_1 #if MC_VER <= MC_1_12_2
for (int x = 0; x < 16; x++)
{
for (int z = 0; z < 16; z++)
{
for (int y = 0; y < 256; y++)
{
IBlockState blockState = this.chunk.getBlockState(x, y, z);
if (blockState.getLightValue() > 0)
{
this.blockLightPosList.add(new DhBlockPos(this.chunk.getPos().getXStart() + x, y, this.chunk.getPos().getZStart() + z));
}
}
}
}
#elif MC_VER < MC_1_20_1
this.chunk.getLights().forEach((blockPos) -> this.chunk.getLights().forEach((blockPos) ->
{ {
this.blockLightPosList.add(new DhBlockPos(blockPos.getX(), blockPos.getY(), blockPos.getZ())); this.blockLightPosList.add(new DhBlockPos(blockPos.getX(), blockPos.getY(), blockPos.getZ()));
@@ -652,11 +767,14 @@ public class ChunkWrapper implements IChunkWrapper
return this.blockLightPosList; return this.blockLightPosList;
} }
//endregion
//================// //================//
// base overrides // // base overrides //
//================// //================//
//region
@Override @Override
public String toString() { return this.chunk.getClass().getSimpleName() + this.chunk.getPos(); } public String toString() { return this.chunk.getClass().getSimpleName() + this.chunk.getPos(); }
@@ -672,4 +790,8 @@ public class ChunkWrapper implements IChunkWrapper
// return this.blockBiomeHashCode; // return this.blockBiomeHashCode;
//} //}
//endregion
} }
@@ -1,12 +1,19 @@
package com.seibel.distanthorizons.common.wrappers.gui; package com.seibel.distanthorizons.common.wrappers.gui;
#if MC_VER <= MC_1_12_2
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.util.text.ITextComponent;
#else
import net.minecraft.client.gui.Font; import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
#endif
#if MC_VER < MC_1_20_1 #if MC_VER <= MC_1_12_2
#elif MC_VER < MC_1_20_1
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
#elif MC_VER <= MC_1_21_11 #elif MC_VER <= MC_1_21_11
import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.GuiGraphics;
@@ -16,26 +23,73 @@ import net.minecraft.client.gui.GuiGraphicsExtractor;
import java.util.List; import java.util.List;
#if MC_VER <= MC_1_12_2
public class DhScreen extends GuiScreen
#else
public class DhScreen extends Screen public class DhScreen extends Screen
#endif
{ {
#if MC_VER <= MC_1_12_2
protected ITextComponent title;
#endif
protected DhScreen(Component $$0) #if MC_VER <= MC_1_12_2
protected DhScreen(ITextComponent title)
{ {
super($$0); this.title = title;
} }
#else
protected DhScreen(Component title)
{
super(title);
}
#endif
// addRenderableWidget in 1.17 and over // addRenderableWidget in 1.17 and over
// addButton in 1.16 and below // addButton in 1.16 and below
#if MC_VER <= MC_1_12_2
protected GuiButton addBtn(GuiButton button)
#else
protected Button addBtn(Button button) protected Button addBtn(Button button)
#endif
{ {
#if MC_VER < MC_1_17_1 #if MC_VER <= MC_1_12_2
this.buttonList.add(button);
return button;
#elif MC_VER < MC_1_17_1
return this.addButton(button); return this.addButton(button);
#else #else
return this.addRenderableWidget(button); return this.addRenderableWidget(button);
#endif #endif
} }
#if MC_VER < MC_1_20_1 #if MC_VER <= MC_1_12_2
@Override
protected void actionPerformed(GuiButton button)
{
OnPressed handler = GuiHelper.HANDLER_BY_BUTTON.get(button);
if (handler != null)
{
handler.pressed(button);
}
}
protected void DhDrawCenteredString(ITextComponent text, int x, int y, int color) {
drawCenteredString(fontRenderer, text.getFormattedText(), x, y, color);
}
protected void DhDrawString(ITextComponent text, int x, int y, int color) {
drawString(fontRenderer, text.getFormattedText(), x, y, color);
}
protected void DhRenderComponentTooltip(List<ITextComponent> list, int x, int y) {
drawHoveringText(list.stream().map(ITextComponent::getFormattedText).toList(), x, y, fontRenderer);
}
protected void DhRenderTooltip(ITextComponent text, int x, int y) {
drawHoveringText(List.of(text.getFormattedText()), x, y, fontRenderer);
}
#elif MC_VER < MC_1_20_1
protected void DhDrawCenteredString(PoseStack guiStack, Font font, Component text, int x, int y, int color) protected void DhDrawCenteredString(PoseStack guiStack, Font font, Component text, int x, int y, int color)
{ {
drawCenteredString(guiStack, font, text, x, y, color); drawCenteredString(guiStack, font, text, x, y, color);
@@ -112,7 +166,4 @@ public class DhScreen extends Screen
guiStack.setTooltipForNextFrame(font, text, x, y); guiStack.setTooltipForNextFrame(font, text, x, y);
} }
#endif #endif
} }
@@ -4,14 +4,22 @@ import com.seibel.distanthorizons.common.wrappers.gui.classicConfig.ClassicConfi
import com.seibel.distanthorizons.core.config.ConfigHandler; import com.seibel.distanthorizons.core.config.ConfigHandler;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.ModInfo;
#if MC_VER <= MC_1_12_2
import net.minecraft.client.gui.GuiScreen;
#else
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
#endif
import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLogger;
public class GetConfigScreen public class GetConfigScreen
{ {
protected static final DhLogger LOGGER = new DhLoggerBuilder().build(); protected static final DhLogger LOGGER = new DhLoggerBuilder().build();
#if MC_VER <= MC_1_12_2
public static GuiScreen getScreen(GuiScreen parent)
#else
public static Screen getScreen(Screen parent) public static Screen getScreen(Screen parent)
#endif
{ {
if (ModInfo.IS_DEV_BUILD) if (ModInfo.IS_DEV_BUILD)
{ {
@@ -1,11 +1,21 @@
package com.seibel.distanthorizons.common.wrappers.gui; package com.seibel.distanthorizons.common.wrappers.gui;
#if MC_VER <= MC_1_12_2
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiTextField;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextComponentTranslation;
import java.util.HashMap;
import java.util.Map;
#else
import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Button;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.MutableComponent;
#endif
#if MC_VER < MC_1_19_2 #if MC_VER < MC_1_19_2 && MC_VER > MC_1_12_2
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.network.chat.TranslatableComponent;
#endif #endif
@@ -15,57 +25,99 @@ public class GuiHelper
/** /**
* Helper static methods for versional compat * Helper static methods for versional compat
*/ */
#if MC_VER <= MC_1_12_2
public static final Map<GuiButton, OnPressed> HANDLER_BY_BUTTON = new HashMap<>();
#endif
#if MC_VER <= MC_1_12_2
public static GuiButton MakeBtn(ITextComponent base, int posX, int posZ, int width, int height, OnPressed action)
#else
public static Button MakeBtn(Component base, int posX, int posZ, int width, int height, Button.OnPress action) public static Button MakeBtn(Component base, int posX, int posZ, int width, int height, Button.OnPress action)
#endif
{ {
#if MC_VER < MC_1_19_4 #if MC_VER <= MC_1_12_2
GuiButton button = new GuiButton(HANDLER_BY_BUTTON.size(), posX, posZ, width, height, base.getFormattedText());
HANDLER_BY_BUTTON.put(button, action);
return button;
#elif MC_VER < MC_1_19_4
return new Button(posX, posZ, width, height, base, action); return new Button(posX, posZ, width, height, base, action);
#else #else
return Button.builder(base, action).bounds(posX, posZ, width, height).build(); return Button.builder(base, action).bounds(posX, posZ, width, height).build();
#endif #endif
} }
#if MC_VER <= MC_1_12_2
public static ITextComponent TextOrLiteral(String text)
#else
public static MutableComponent TextOrLiteral(String text) public static MutableComponent TextOrLiteral(String text)
#endif
{ {
#if MC_VER < MC_1_19_2 #if MC_VER <= MC_1_12_2
return new TextComponentString(text);
#elif MC_VER < MC_1_19_2
return new TextComponent(text); return new TextComponent(text);
#else #else
return Component.literal(text); return Component.literal(text);
#endif #endif
} }
#if MC_VER <= MC_1_12_2
public static ITextComponent TextOrTranslatable(String text)
#else
public static MutableComponent TextOrTranslatable(String text) public static MutableComponent TextOrTranslatable(String text)
#endif
{ {
#if MC_VER < MC_1_19_2 #if MC_VER <= MC_1_12_2
return new TextComponentString(text);
#elif MC_VER < MC_1_19_2
return new TextComponent(text); return new TextComponent(text);
#else #else
return Component.translatable(text); return Component.translatable(text);
#endif #endif
} }
#if MC_VER <= MC_1_12_2
public static ITextComponent Translatable(String text, Object... args)
#else
public static MutableComponent Translatable(String text, Object... args) public static MutableComponent Translatable(String text, Object... args)
#endif
{ {
#if MC_VER < MC_1_19_2 #if MC_VER <= MC_1_12_2
return new TextComponentTranslation(text, args);
#elif MC_VER < MC_1_19_2
return new TranslatableComponent(text, args); return new TranslatableComponent(text, args);
#else #else
return Component.translatable(text, args); return Component.translatable(text, args);
#endif #endif
} }
public static void SetX(AbstractWidget w, int x) #if MC_VER <= MC_1_12_2
public static void SetX(GuiButton widget, int x)
#else
public static void SetX(AbstractWidget widget, int x)
#endif
{ {
#if MC_VER < MC_1_19_4 #if MC_VER < MC_1_19_4
w.x = x; widget.x = x;
#else #else
w.setX(x); widget.setX(x);
#endif #endif
} }
public static void SetY(AbstractWidget w, int y) #if MC_VER <= MC_1_12_2
public static void SetY(GuiTextField textField, int y) { textField.y = y; }
#endif
#if MC_VER <= MC_1_12_2
public static void SetY(GuiButton widget, int y)
#else
public static void SetY(AbstractWidget widget, int y)
#endif
{ {
#if MC_VER < MC_1_19_4 #if MC_VER < MC_1_19_4
w.y = y; widget.y = y;
#else #else
w.setY(y); widget.setY(y);
#endif #endif
} }
@@ -1,21 +1,34 @@
package com.seibel.distanthorizons.common.wrappers.gui; package com.seibel.distanthorizons.common.wrappers.gui;
import com.seibel.distanthorizons.core.wrapperInterfaces.config.ILangWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.config.ILangWrapper;
#if MC_VER <= MC_1_12_2
import net.minecraft.client.resources.I18n;
#else
import net.minecraft.client.resources.language.I18n; import net.minecraft.client.resources.language.I18n;
#endif
public class LangWrapper implements ILangWrapper public class LangWrapper implements ILangWrapper
{ {
public static final LangWrapper INSTANCE = new LangWrapper(); public static final LangWrapper INSTANCE = new LangWrapper();
@Override @Override
public boolean langExists(String str) public boolean langExists(String str)
{ {
#if MC_VER <= MC_1_12_2
return I18n.hasKey(str);
#else
return I18n.exists(str); return I18n.exists(str);
#endif
} }
@Override @Override
public String getLang(String str) public String getLang(String str)
{ {
#if MC_VER <= MC_1_12_2
return I18n.format(str);
#else
return I18n.get(str); return I18n.get(str);
#endif
} }
} }
@@ -1,17 +1,27 @@
package com.seibel.distanthorizons.common.wrappers.gui; package com.seibel.distanthorizons.common.wrappers.gui;
#if MC_VER <= MC_1_12_2
import org.lwjglx.opengl.Display;
#else
import com.mojang.blaze3d.platform.Window; import com.mojang.blaze3d.platform.Window;
#endif
import com.seibel.distanthorizons.core.config.gui.AbstractScreen; import com.seibel.distanthorizons.core.config.gui.AbstractScreen;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
#if MC_VER > MC_1_12_2
import net.minecraft.client.gui.components.ContainerObjectSelectionList; import net.minecraft.client.gui.components.ContainerObjectSelectionList;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
#endif
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
#if MC_VER < MC_1_20_1 #if MC_VER <= MC_1_12_2
import net.minecraft.client.gui.GuiListExtended;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiSlot;
#elif MC_VER < MC_1_20_1
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
#elif MC_VER <= MC_1_21_11 #elif MC_VER <= MC_1_21_11
import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.GuiGraphics;
@@ -24,19 +34,29 @@ import java.util.*;
public class MinecraftScreen public class MinecraftScreen
{ {
#if MC_VER <= MC_1_12_2
public static GuiScreen getScreen(GuiScreen parent, AbstractScreen screen, String translationName)
#else
public static Screen getScreen(Screen parent, AbstractScreen screen, String translationName) public static Screen getScreen(Screen parent, AbstractScreen screen, String translationName)
#endif
{ {
return new ConfigScreenRenderer(parent, screen, translationName); return new ConfigScreenRenderer(parent, screen, translationName);
} }
private static class ConfigScreenRenderer extends DhScreen private static class ConfigScreenRenderer extends DhScreen
{ {
#if MC_VER <= MC_1_12_2
private final GuiScreen parent;
#else
private final Screen parent; private final Screen parent;
#endif
private ConfigListWidget configListWidget; private ConfigListWidget configListWidget;
private AbstractScreen screen; private AbstractScreen screen;
#if MC_VER <= MC_1_12_2
#if MC_VER < MC_1_19_2 public static net.minecraft.util.text.TextComponentTranslation translate(String str, Object... args)
{ return new net.minecraft.util.text.TextComponentTranslation(str, args); }
#elif MC_VER < MC_1_19_2
public static net.minecraft.network.chat.TranslatableComponent translate(String str, Object... args) 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 #else
@@ -44,10 +64,16 @@ public class MinecraftScreen
{ return net.minecraft.network.chat.Component.translatable(str, args); } { return net.minecraft.network.chat.Component.translatable(str, args); }
#endif #endif
#if MC_VER <= MC_1_12_2
protected ConfigScreenRenderer(GuiScreen parent, AbstractScreen screen, String translationName)
#else
protected ConfigScreenRenderer(Screen parent, AbstractScreen screen, String translationName) protected ConfigScreenRenderer(Screen parent, AbstractScreen screen, String translationName)
#endif
{ {
super(translate(translationName)); super(translate(translationName));
#if MC_VER < MC_1_21_9 #if MC_VER <= MC_1_12_2
screen.minecraftWindow = Display.getWindow();
#elif MC_VER < MC_1_21_9
screen.minecraftWindow = Minecraft.getInstance().getWindow().getWindow(); screen.minecraftWindow = Minecraft.getInstance().getWindow().getWindow();
#else #else
screen.minecraftWindow = Minecraft.getInstance().getWindow().handle(); screen.minecraftWindow = Minecraft.getInstance().getWindow().handle();
@@ -57,30 +83,53 @@ public class MinecraftScreen
} }
@Override @Override
#if MC_VER <= MC_1_12_2
public void initGui()
#else
protected void init() protected void init()
#endif
{ {
super.init(); // Init Minecraft's screen #if MC_VER <= MC_1_12_2
super.initGui();
#else
super.init();
#endif
#if MC_VER <= MC_1_12_2
this.screen.width = Display.getWidth();
this.screen.height = Display.getHeight();
#else
Window mcWindow = this.minecraft.getWindow(); Window mcWindow = this.minecraft.getWindow();
this.screen.width = mcWindow.getWidth(); this.screen.width = mcWindow.getWidth();
this.screen.height = mcWindow.getHeight(); this.screen.height = mcWindow.getHeight();
#endif
this.screen.scaledWidth = this.width; this.screen.scaledWidth = this.width;
this.screen.scaledHeight = this.height; this.screen.scaledHeight = this.height;
this.screen.init(); // Init our own config screen this.screen.init(); // Init our own config screen
#if MC_VER <= MC_1_12_2
this.configListWidget = new ConfigListWidget(this.mc, this.width, this.height, 0, 0, 25); // Select the area to tint
#else
this.configListWidget = 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
#endif
#if MC_VER < MC_1_20_6 // no background is rendered in MC 1.20.6+ #if MC_VER <= MC_1_12_2
#elif MC_VER < MC_1_20_6 // no background is rendered in MC 1.20.6+
if (this.minecraft != null && this.minecraft.level != null) // Check if in game if (this.minecraft != null && this.minecraft.level != null) // Check if in game
{ {
this.configListWidget.setRenderBackground(false); // Disable from rendering this.configListWidget.setRenderBackground(false); // Disable from rendering
} }
#endif #endif
#if MC_VER > MC_1_12_2
this.addWidget(this.configListWidget); // Add the tint to the things to be rendered this.addWidget(this.configListWidget); // Add the tint to the things to be rendered
#endif
} }
@Override @Override
#if MC_VER < MC_1_20_1 #if MC_VER <= MC_1_12_2
public void drawScreen(int mouseX, int mouseY, float delta)
#elif MC_VER < MC_1_20_1
public void render(PoseStack matrices, int mouseX, int mouseY, float delta) public void render(PoseStack matrices, int mouseX, int mouseY, float delta)
#elif MC_VER <= MC_1_21_11 #elif MC_VER <= MC_1_21_11
public void render(GuiGraphics matrices, int mouseX, int mouseY, float delta) public void render(GuiGraphics matrices, int mouseX, int mouseY, float delta)
@@ -88,7 +137,9 @@ public class MinecraftScreen
public void extractRenderState(GuiGraphicsExtractor matrices, int mouseX, int mouseY, float delta) public void extractRenderState(GuiGraphicsExtractor matrices, int mouseX, int mouseY, float delta)
#endif #endif
{ {
#if MC_VER < MC_1_20_2 #if MC_VER <= MC_1_12_2
this.drawDefaultBackground();
#elif MC_VER < MC_1_20_2
this.renderBackground(matrices); // Render background this.renderBackground(matrices); // Render background
#elif MC_VER < MC_1_21_6 #elif MC_VER < MC_1_21_6
this.renderBackground(matrices, mouseX, mouseY, delta); // Render background this.renderBackground(matrices, mouseX, mouseY, delta); // Render background
@@ -96,7 +147,9 @@ public class MinecraftScreen
// background blur is already being rendered, rendering again causes the game to crash // background blur is already being rendered, rendering again causes the game to crash
#endif #endif
#if MC_VER <= MC_1_21_11 #if MC_VER <= MC_1_12_2
this.configListWidget.drawScreen(mouseX, mouseY, delta);
#elif MC_VER <= MC_1_21_11
this.configListWidget.render(matrices, mouseX, mouseY, delta); // Renders the items in the render list (currently only used to tint background darker) this.configListWidget.render(matrices, mouseX, mouseY, delta); // Renders the items in the render list (currently only used to tint background darker)
#else #else
this.configListWidget.extractRenderState(matrices, mouseX, mouseY, delta); // Renders the items in the render list (currently only used to tint background darker) this.configListWidget.extractRenderState(matrices, mouseX, mouseY, delta); // Renders the items in the render list (currently only used to tint background darker)
@@ -106,55 +159,86 @@ public class MinecraftScreen
this.screen.mouseY = mouseY; this.screen.mouseY = mouseY;
this.screen.render(delta); // Render everything on the main screen this.screen.render(delta); // Render everything on the main screen
#if MC_VER <= MC_1_21_11 #if MC_VER <= MC_1_12_2
super.drawScreen(mouseX, mouseY, delta); // Render the vanilla stuff (currently only used for the background and tint)
#elif MC_VER <= MC_1_21_11
super.render(matrices, mouseX, mouseY, delta); // Render the vanilla stuff (currently only used for the background and tint) super.render(matrices, mouseX, mouseY, delta); // Render the vanilla stuff (currently only used for the background and tint)
#else #else
super.extractRenderState(matrices, mouseX, mouseY, delta); // Renders the items in the render list (currently only used to tint background darker) super.extractRenderState(matrices, mouseX, mouseY, delta); // Renders the items in the render list (currently only used to tint background darker)
#endif #endif
} }
#if MC_VER <= MC_1_21_10
@Override @Override
#if MC_VER <= MC_1_12_2
public void setWorldAndResolution(Minecraft mc, int width, int height)
#elif MC_VER <= MC_1_21_10
public void resize(Minecraft mc, int width, int height) public void resize(Minecraft mc, int width, int height)
#else #else
@Override
public void resize(int width, int height) public void resize(int width, int height)
#endif #endif
{ {
// Resize Minecraft's screen // Resize Minecraft's screen
#if MC_VER <= MC_1_21_10 #if MC_VER <= MC_1_12_2
super.setWorldAndResolution(mc, width, height);
#elif MC_VER <= MC_1_21_10
super.resize(mc, width, height); super.resize(mc, width, height);
#else #else
super.resize(width, height); super.resize(width, height);
#endif #endif
#if MC_VER <= MC_1_12_2
this.screen.width = Display.getWidth();
this.screen.height = Display.getHeight();
#else
Window mcWindow = this.minecraft.getWindow(); Window mcWindow = this.minecraft.getWindow();
this.screen.width = mcWindow.getWidth(); this.screen.width = mcWindow.getWidth();
this.screen.height = mcWindow.getHeight(); this.screen.height = mcWindow.getHeight();
#endif;
this.screen.scaledWidth = this.width; this.screen.scaledWidth = this.width;
this.screen.scaledHeight = this.height; this.screen.scaledHeight = this.height;
this.screen.onResize(); // Resize our screen this.screen.onResize(); // Resize our screen
} }
@Override @Override
#if MC_VER <= MC_1_12_2
public void updateScreen()
#else
public void tick() public void tick()
#endif
{ {
#if MC_VER <= MC_1_12_2
super.updateScreen(); // Tick Minecraft's screen
#else
super.tick(); // Tick Minecraft's screen super.tick(); // Tick Minecraft's screen
#endif
this.screen.tick(); // Tick our screen this.screen.tick(); // Tick our screen
if (this.screen.close) // If we decide to close the screen, then actually close the screen if (this.screen.close) // If we decide to close the screen, then actually close the screen
{ {
#if MC_VER <= MC_1_12_2
this.onGuiClosed();
#else
this.onClose(); this.onClose();
#endif
} }
} }
@Override @Override
#if MC_VER <= MC_1_12_2
public void onGuiClosed()
#else
public void onClose() public void onClose()
#endif
{ {
this.screen.onClose(); // Close our screen this.screen.onClose(); // Close our screen
#if MC_VER <= MC_1_12_2
Objects.requireNonNull(this.mc).displayGuiScreen(this.parent); // Goto the parent screen
#else
Objects.requireNonNull(this.minecraft).setScreen(this.parent); // Goto the parent screen Objects.requireNonNull(this.minecraft).setScreen(this.parent); // Goto the parent screen
#endif
} }
#if MC_VER > MC_1_12_2
@Override @Override
public void onFilesDrop(@NotNull List<Path> files) public void onFilesDrop(@NotNull List<Path> files)
{ this.screen.onFilesDrop(files); } { this.screen.onFilesDrop(files); }
@@ -163,10 +247,14 @@ public class MinecraftScreen
@Override @Override
public boolean shouldCloseOnEsc() public boolean shouldCloseOnEsc()
{ return this.screen.shouldCloseOnEsc; } { return this.screen.shouldCloseOnEsc; }
#endif
} }
#if MC_VER <= MC_1_12_2
public static class ConfigListWidget extends GuiListExtended
#else
public static class ConfigListWidget extends ContainerObjectSelectionList public static class ConfigListWidget extends ContainerObjectSelectionList
#endif
{ {
public ConfigListWidget(Minecraft minecraftClient, int canvasWidth, int canvasHeight, int topMargin, int botMargin, int itemSpacing) public ConfigListWidget(Minecraft minecraftClient, int canvasWidth, int canvasHeight, int topMargin, int botMargin, int itemSpacing)
{ {
@@ -178,6 +266,18 @@ public class MinecraftScreen
this.centerListVertically = false; this.centerListVertically = false;
} }
#if MC_VER <= MC_1_12_2
@Override
protected int getSize()
{
return 0;
}
@Override
public IGuiListEntry getListEntry(int index)
{
return null;
}
#endif
} }
} }
@@ -0,0 +1,9 @@
package com.seibel.distanthorizons.common.wrappers.gui;
#if MC_VER <= MC_1_12_2
import net.minecraft.client.gui.GuiButton;
public interface OnPressed {
void pressed(GuiButton button);
}
#endif
@@ -19,13 +19,21 @@
package com.seibel.distanthorizons.common.wrappers.gui; package com.seibel.distanthorizons.common.wrappers.gui;
#if MC_VER > MC_1_12_2
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
#endif
#if MC_VER >= MC_1_17_1 #if MC_VER >= MC_1_17_1
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Button;
#endif #endif
#if MC_VER < MC_1_17_1
#if MC_VER <= MC_1_12_2
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.util.ResourceLocation;
#elif MC_VER < MC_1_17_1
import net.minecraft.client.gui.components.ImageButton; import net.minecraft.client.gui.components.ImageButton;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
@@ -53,7 +61,9 @@ import net.minecraft.client.gui.GuiGraphicsExtractor;
import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.client.renderer.RenderPipelines;
#endif #endif
#if MC_VER <= MC_1_21_10 #if MC_VER <= MC_1_12_2
import net.minecraft.util.ResourceLocation;
#elif MC_VER <= MC_1_21_10
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
#else #else
import net.minecraft.resources.Identifier; import net.minecraft.resources.Identifier;
@@ -65,7 +75,10 @@ import net.minecraft.resources.Identifier;
* @author coolGi * @author coolGi
* @version 2023-10-03 * @version 2023-10-03
*/ */
#if MC_VER < MC_1_20_2 #if MC_VER <= MC_1_12_2
@SuppressWarnings("deprecation") // we use a few deprecated Mojang functions (as expected when running on old MC versions)
public class TexturedButtonWidget extends GuiButton
#elif MC_VER < MC_1_20_2
@SuppressWarnings("deprecation") // we use a few deprecated Mojang functions (as expected when running on old MC versions) @SuppressWarnings("deprecation") // we use a few deprecated Mojang functions (as expected when running on old MC versions)
public class TexturedButtonWidget extends ImageButton public class TexturedButtonWidget extends ImageButton
#else #else
@@ -75,7 +88,7 @@ public class TexturedButtonWidget extends Button
{ {
public final boolean renderBackground; public final boolean renderBackground;
#if MC_VER >= MC_1_20_2 #if MC_VER >= MC_1_20_2 || MC_VER <= MC_1_12_2
private final int u; private final int u;
private final int v; private final int v;
private final int hoveredVOffset; private final int hoveredVOffset;
@@ -90,30 +103,41 @@ public class TexturedButtonWidget extends Button
private final int textureHeight; private final int textureHeight;
#endif #endif
#if MC_VER <= MC_1_12_2
public TexturedButtonWidget( public TexturedButtonWidget(int id, int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation textureResourceLocation, int textureWidth, int textureHeight, String text)
int x, int y, int width, int height, int u, int v, int hoveredVOffset, {
#if MC_VER <= MC_1_21_10 ResourceLocation textureResourceLocation, this(id, x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, text, true);
#else Identifier textureResourceLocation, }
#endif #elif MC_VER <= MC_1_21_10
int textureWidth, int textureHeight, OnPress pressAction, Component text) public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation textureResourceLocation, int textureWidth, int textureHeight, OnPress pressAction, Component text)
{ {
this(x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, pressAction, text, true); this(x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, pressAction, text, true);
} }
public TexturedButtonWidget( #else
int x, int y, int width, int height, int u, int v, int hoveredVOffset, public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, Identifier textureResourceLocation, int textureWidth, int textureHeight, OnPress pressAction, Component text)
#if MC_VER <= MC_1_21_10 ResourceLocation textureResourceLocation,
#else Identifier textureResourceLocation,
#endif
int textureWidth, int textureHeight, OnPress pressAction, Component text,
boolean renderBackground)
{ {
#if MC_VER < MC_1_20_2 this(x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, pressAction, text, true);
}
#endif
#if MC_VER <= MC_1_12_2
public TexturedButtonWidget(int id, int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation textureResourceLocation, int textureWidth, int textureHeight, String text, boolean renderBackground)
#elif MC_VER <= MC_1_21_10
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation textureResourceLocation, int textureWidth, int textureHeight, OnPress pressAction, Component text, boolean renderBackground)
#else
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, Identifier textureResourceLocation, int textureWidth, int textureHeight, OnPress pressAction, Component text, boolean renderBackground)
#endif
{
#if MC_VER <= MC_1_12_2
super(id, x, y, width, height, text);
#elif MC_VER < MC_1_20_2
super(x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, pressAction, text); super(x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, pressAction, text);
#else #else
// We don't pass in the text option since it will render (we normally pass it in for narration) // We don't pass in the text option since it will render (we normally pass it in for narration)
super(x, y, width, height, Component.empty(), pressAction, DEFAULT_NARRATION); super(x, y, width, height, Component.empty(), pressAction, DEFAULT_NARRATION);
#endif
#if MC_VER >= MC_1_20_2 || MC_VER <= MC_1_12_2
this.u = u; this.u = u;
this.v = v; this.v = v;
this.hoveredVOffset = hoveredVOffset; this.hoveredVOffset = hoveredVOffset;
@@ -127,7 +151,27 @@ public class TexturedButtonWidget extends Button
this.renderBackground = renderBackground; this.renderBackground = renderBackground;
} }
#if MC_VER < MC_1_20_2 #if MC_VER <= MC_1_12_2
@Override
public void drawButton(Minecraft mc, int mouseX, int mouseY, float partialTicks) {
if (this.visible) {
//Render vanilla background
mc.getTextureManager().bindTexture(BUTTON_TEXTURES);
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
this.hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;
int i = this.getHoverState(this.hovered);
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO);
GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
this.drawTexturedModalRect(this.x, this.y, 0, 46 + i * 20, this.width / 2, this.height);
this.drawTexturedModalRect(this.x + this.width / 2, this.y, 200 - this.width / 2, 46 + i * 20, this.width / 2, this.height);
//Render DH texture
mc.getTextureManager().bindTexture(textureResourceLocation);
drawModalRectWithCustomSizedTexture(this.x, this.y, this.u, (hoveredVOffset * (i - 1)), this.width, this.height, this.textureWidth, this.textureHeight);
}
}
#elif MC_VER < MC_1_20_2
#if MC_VER < MC_1_19_4 #if MC_VER < MC_1_19_4
@Override @Override
public void renderButton(PoseStack matrices, int mouseX, int mouseY, float delta) public void renderButton(PoseStack matrices, int mouseX, int mouseY, float delta)
@@ -12,17 +12,24 @@ import com.seibel.distanthorizons.core.config.types.enums.EConfigCommentTextPosi
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.config.IConfigGui; import com.seibel.distanthorizons.core.wrapperInterfaces.config.IConfigGui;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
#if MC_VER <= MC_1_12_2
import net.minecraft.client.gui.*;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.util.text.ITextComponent;
#else
import net.minecraft.client.gui.Font; import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.ContainerObjectSelectionList; import net.minecraft.client.gui.components.ContainerObjectSelectionList;
import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
#endif
import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLogger;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
#if MC_VER <= MC_1_12_2
#if MC_VER < MC_1_20_1 #elif MC_VER < MC_1_20_1
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.GuiComponent; import net.minecraft.client.gui.GuiComponent;
#elif MC_VER <= MC_1_21_11 #elif MC_VER <= MC_1_21_11
@@ -67,6 +74,7 @@ public class ClassicConfigGUI
//==============// //==============//
// Initializers // // Initializers //
//==============// //==============//
//region
// Some regexes to check if an input is valid // Some regexes to check if an input is valid
public static final Pattern INTEGER_ONLY_REGEX = Pattern.compile("(-?[0-9]*)"); public static final Pattern INTEGER_ONLY_REGEX = Pattern.compile("(-?[0-9]*)");
@@ -87,25 +95,46 @@ public class ClassicConfigGUI
} }
//endregion
//==============// //==============//
// GUI handling // // GUI handling //
//==============// //==============//
//region
/** if you want to get this config gui's screen call this */ /** if you want to get this config gui's screen call this */
#if MC_VER <= MC_1_12_2
public static GuiScreen getScreen(GuiScreen parent, String category)
#else
public static Screen getScreen(Screen parent, String category) public static Screen getScreen(Screen parent, String category)
#endif
{ return new DhConfigScreen(parent, category); } { return new DhConfigScreen(parent, category); }
//endregion
//================// //================//
// helper classes // // helper classes //
//================// //================//
//region
#if MC_VER <= MC_1_12_2
public static class ConfigListWidget extends GuiListExtended
#else
public static class ConfigListWidget extends ContainerObjectSelectionList<DhButtonEntry> public static class ConfigListWidget extends ContainerObjectSelectionList<DhButtonEntry>
#endif
{ {
#if MC_VER <= MC_1_12_2
public List<DhButtonEntry> children = new ArrayList<>();
#endif
#if MC_VER <= MC_1_12_2
FontRenderer textRenderer;
#else
Font textRenderer; Font textRenderer;
#endif
public ConfigListWidget(Minecraft minecraftClient, int canvasWidth, int canvasHeight, int topMargin, int botMargin, int itemSpacing) public ConfigListWidget(Minecraft minecraftClient, int canvasWidth, int canvasHeight, int topMargin, int botMargin, int itemSpacing)
{ {
@@ -116,40 +145,121 @@ public class ClassicConfigGUI
#endif #endif
this.centerListVertically = false; this.centerListVertically = false;
#if MC_VER <= MC_1_12_2
this.textRenderer = minecraftClient.fontRenderer;
#else
this.textRenderer = minecraftClient.font; this.textRenderer = minecraftClient.font;
#endif
} }
public void addButton(DhConfigScreen gui, AbstractConfigBase dhConfigType, AbstractWidget button, AbstractWidget resetButton, AbstractWidget indexButton, Component text) #if MC_VER <= MC_1_12_2
{ this.addEntry(new DhButtonEntry(gui, dhConfigType, button, text, resetButton, indexButton)); } @Override
protected int getSize()
{
return this.children.size();
}
@Override @Override
public int getRowWidth() { return 10_000; } public IGuiListEntry getListEntry(int index)
public AbstractWidget getHoveredButton(double mouseX, double mouseY)
{ {
for (DhButtonEntry buttonEntry : this.children()) return this.children.get(index);
}
@Override
protected void drawContainerBackground(Tessellator tessellator)
{
if (this.mc.world != null)
{ {
AbstractWidget button = buttonEntry.button; return; // in-game don't draw dirt background
if (button != null }
&& button.visible) super.drawContainerBackground(tessellator);
}
#endif
#if MC_VER <= MC_1_12_2
public void addButton(DhConfigScreen gui, AbstractConfigBase dhConfigType, Gui button, GuiButton resetButton, GuiButton indexButton, ITextComponent text)
#else
public void addButton(DhConfigScreen gui, AbstractConfigBase dhConfigType, AbstractWidget button, AbstractWidget resetButton, AbstractWidget indexButton, Component text)
#endif
{
#if MC_VER <= MC_1_12_2
this.children.add(new DhButtonEntry(gui, dhConfigType, button, text, resetButton, indexButton));
#else
this.addEntry(new DhButtonEntry(gui, dhConfigType, button, text, resetButton, indexButton));
#endif
}
@Override
#if MC_VER <= MC_1_12_2
public int getListWidth()
#else
public int getRowWidth()
#endif
{ return 10_000; }
#if MC_VER <= MC_1_12_2
public Gui getHoveredButton(double mouseX, double mouseY)
#else
public AbstractWidget getHoveredButton(double mouseX, double mouseY)
#endif
{
#if MC_VER <= MC_1_12_2
for (DhButtonEntry buttonEntry : this.children)
#else
for (DhButtonEntry buttonEntry : this.children())
#endif
{
#if MC_VER <= MC_1_12_2
Gui gui = buttonEntry.button;
if (gui == null) continue;
double minX, minY, maxX, maxY;
if (gui instanceof GuiButton button)
{ {
#if MC_VER < MC_1_19_4 if (!button.visible) continue;
double minX = button.x; minX = button.x;
double minY = button.y; minY = button.y;
#else maxX = minX + button.width;
double minX = button.getX(); maxY = minY + button.height;
double minY = button.getY();
#endif
double maxX = minX + button.getWidth();
double maxY = minY + button.getHeight();
if (mouseX >= minX && mouseX < maxX
&& mouseY >= minY && mouseY < maxY)
{
return button;
}
} }
else if (gui instanceof GuiTextField field)
{
if (!field.getVisible()) continue;
minX = field.x;
minY = field.y;
maxX = minX + field.width;
maxY = minY + field.height;
}
else
{
continue;
}
if (mouseX >= minX && mouseX < maxX && mouseY >= minY && mouseY < maxY)
{
return gui;
}
#else
AbstractWidget button = (AbstractWidget) buttonEntry.button;
if (button == null || !button.visible) continue;
#if MC_VER < MC_1_19_4
double minX = button.x;
double minY = button.y;
#else
double minX = button.getX();
double minY = button.getY();
#endif
double maxX = minX + button.getWidth();
double maxY = minY + button.getHeight();
if (mouseX >= minX && mouseX < maxX && mouseY >= minY && mouseY < maxY)
{
return button;
}
#endif
} }
return null; return null;
@@ -157,32 +267,60 @@ public class ClassicConfigGUI
} }
#if MC_VER <= MC_1_12_2
public static class DhButtonEntry implements GuiListExtended.IGuiListEntry
#else
public static class DhButtonEntry extends ContainerObjectSelectionList.Entry<DhButtonEntry> public static class DhButtonEntry extends ContainerObjectSelectionList.Entry<DhButtonEntry>
#endif
{ {
#if MC_VER <= MC_1_12_2
private static final FontRenderer textRenderer = Minecraft.getMinecraft().fontRenderer;
#else
private static final Font textRenderer = Minecraft.getInstance().font; private static final Font textRenderer = Minecraft.getInstance().font;
#endif
private final AbstractWidget button;
private final DhConfigScreen gui; private final DhConfigScreen gui;
#if MC_VER <= MC_1_12_2
private final AbstractWidget resetButton; public final Gui button;
public final Gui resetButton;
public final Gui indexButton;
#else
private final AbstractWidget indexButton; private final AbstractWidget indexButton;
private final AbstractWidget resetButton;
private final AbstractWidget button;
#endif
#if MC_VER <= MC_1_12_2
private final ITextComponent text;
#else
private final Component text; private final Component text;
#endif
#if MC_VER <= MC_1_12_2
private final List<Gui> children = new ArrayList<>();
#else
private final List<AbstractWidget> children = new ArrayList<>(); private final List<AbstractWidget> children = new ArrayList<>();
#endif
@NotNull @NotNull
private final EConfigCommentTextPosition textPosition; private final EConfigCommentTextPosition textPosition;
public final AbstractConfigBase dhConfigType; public final AbstractConfigBase dhConfigType;
#if MC_VER <= MC_1_12_2
public static final Map<Gui, ITextComponent> TEXT_BY_WIDGET = new HashMap<>();
public static final Map<Gui, DhButtonEntry> BUTTON_BY_WIDGET = new HashMap<>();
#else
public static final Map<AbstractWidget, Component> TEXT_BY_WIDGET = new HashMap<>(); public static final Map<AbstractWidget, Component> TEXT_BY_WIDGET = new HashMap<>();
public static final Map<AbstractWidget, DhButtonEntry> BUTTON_BY_WIDGET = new HashMap<>(); public static final Map<AbstractWidget, DhButtonEntry> BUTTON_BY_WIDGET = new HashMap<>();
#endif
public DhButtonEntry( #if MC_VER <= MC_1_12_2
DhConfigScreen gui, AbstractConfigBase dhConfigType, public DhButtonEntry(DhConfigScreen gui, AbstractConfigBase dhConfigType, Gui button, ITextComponent text, GuiButton resetButton, GuiButton indexButton)
AbstractWidget button, Component text, AbstractWidget resetButton, AbstractWidget indexButton) #else
public DhButtonEntry(DhConfigScreen gui, AbstractConfigBase dhConfigType, AbstractWidget button, Component text, AbstractWidget resetButton, AbstractWidget indexButton)
#endif
{ {
TEXT_BY_WIDGET.put(button, text); TEXT_BY_WIDGET.put(button, text);
BUTTON_BY_WIDGET.put(button, this); BUTTON_BY_WIDGET.put(button, this);
@@ -225,7 +363,9 @@ public class ClassicConfigGUI
@Override @Override
#if MC_VER < MC_1_20_1 #if MC_VER <= MC_1_12_2
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, boolean isSelected, float tickDelta)
#elif MC_VER < MC_1_20_1
public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta)
#elif MC_VER < MC_1_21_9 #elif MC_VER < MC_1_21_9
public void render(GuiGraphics matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) public void render(GuiGraphics matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta)
@@ -250,18 +390,40 @@ public class ClassicConfigGUI
if (this.button != null) if (this.button != null)
{ {
SetY(this.button, y); #if MC_VER <= MC_1_12_2
#if MC_VER <= MC_1_21_11 if (this.button instanceof GuiButton guiButton)
this.button.render(matrices, mouseX, mouseY, tickDelta); {
SetY(guiButton, y);
guiButton.drawButton(Minecraft.getMinecraft(), mouseX, mouseY, tickDelta);
}
if (this.button instanceof GuiTextField guiTextField)
{
SetY(guiTextField, y);
guiTextField.drawTextBox();
}
#else #else
this.button.extractRenderState(matrices, mouseX, mouseY, tickDelta); SetY(this.button, y);
{
#if MC_VER <= MC_1_21_11
this.button.render(matrices, mouseX, mouseY, tickDelta);
#else
this.button.extractRenderState(matrices, mouseX, mouseY, tickDelta);
#endif
}
#endif #endif
} }
if (this.resetButton != null) if (this.resetButton != null)
{ {
#if MC_VER <= MC_1_12_2
SetY((GuiButton) this.resetButton, y);
#else
SetY(this.resetButton, y); SetY(this.resetButton, y);
#if MC_VER <= MC_1_21_11 #endif
#if MC_VER <= MC_1_12_2
((GuiButton) this.resetButton).drawButton(Minecraft.getMinecraft(), mouseX, mouseY, tickDelta);
#elif MC_VER <= MC_1_21_11
this.resetButton.render(matrices, mouseX, mouseY, tickDelta); this.resetButton.render(matrices, mouseX, mouseY, tickDelta);
#else #else
this.resetButton.extractRenderState(matrices, mouseX, mouseY, tickDelta); this.resetButton.extractRenderState(matrices, mouseX, mouseY, tickDelta);
@@ -270,8 +432,15 @@ public class ClassicConfigGUI
if (this.indexButton != null) if (this.indexButton != null)
{ {
#if MC_VER <= MC_1_12_2
SetY((GuiButton) this.indexButton, y);
#else
SetY(this.indexButton, y); SetY(this.indexButton, y);
#if MC_VER <= MC_1_21_11 #endif
#if MC_VER <= MC_1_12_2
((GuiButton) this.indexButton).drawButton(Minecraft.getMinecraft(), mouseX, mouseY, tickDelta);
#elif MC_VER <= MC_1_21_11
this.indexButton.render(matrices, mouseX, mouseY, tickDelta); this.indexButton.render(matrices, mouseX, mouseY, tickDelta);
#else #else
this.indexButton.extractRenderState(matrices, mouseX, mouseY, tickDelta); this.indexButton.extractRenderState(matrices, mouseX, mouseY, tickDelta);
@@ -280,7 +449,11 @@ public class ClassicConfigGUI
if (this.text != null) if (this.text != null)
{ {
#if MC_VER <= MC_1_12_2
int translatedLength = textRenderer.getStringWidth(this.text.getFormattedText());
#else
int translatedLength = textRenderer.width(this.text); int translatedLength = textRenderer.width(this.text);
#endif
int textXPos; int textXPos;
if (this.textPosition == EConfigCommentTextPosition.RIGHT_JUSTIFIED) if (this.textPosition == EConfigCommentTextPosition.RIGHT_JUSTIFIED)
@@ -313,17 +486,21 @@ public class ClassicConfigGUI
throw new UnsupportedOperationException("No text position render defined for [" + this.textPosition + "]"); throw new UnsupportedOperationException("No text position render defined for [" + this.textPosition + "]");
} }
#if MC_VER <= MC_1_12_2
#if MC_VER < MC_1_20_1 textRenderer.drawString(
this.text.getFormattedText(),
textXPos, y + 5,
0xFFFFFF);
#elif MC_VER < MC_1_20_1
GuiComponent.drawString(matrices, textRenderer, GuiComponent.drawString(matrices, textRenderer,
this.text, this.text,
textXPos, y + 5, textXPos, y + 5,
0xFFFFFF); 0xFFFFFF);
#elif MC_VER < MC_1_21_6 #elif MC_VER < MC_1_21_6
matrices.drawString(textRenderer, matrices.drawString(textRenderer,
this.text, this.text,
textXPos, y + 5, textXPos, y + 5,
0xFFFFFF); 0xFFFFFF);
#elif MC_VER <= MC_1_21_11 #elif MC_VER <= MC_1_21_11
matrices.drawString(textRenderer, matrices.drawString(textRenderer,
this.text, this.text,
@@ -344,9 +521,25 @@ public class ClassicConfigGUI
} }
} }
#if MC_VER <= MC_1_12_2
@Override
public void updatePosition(int slotIndex, int x, int y, float partialTicks) { }
@Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY)
{
return false; // handled in DhConfigScreen.mouseClicked
}
@Override
public void mouseReleased(int slotIndex, int x, int y, int mouseEvent, int relativeX, int relativeY) { }
#endif
#if MC_VER > MC_1_12_2
@Override @Override
public @NotNull List<? extends GuiEventListener> children() public @NotNull List<? extends GuiEventListener> children()
{ return this.children; } { return this.children; }
#endif
#if MC_VER >= MC_1_17_1 #if MC_VER >= MC_1_17_1
@Override @Override
@@ -358,11 +551,14 @@ public class ClassicConfigGUI
} }
//endregion
//================// //================//
// event handling // // event handling //
//================// //================//
//region
public static class ConfigCoreInterface implements IConfigGui public static class ConfigCoreInterface implements IConfigGui
{ {
@@ -381,4 +577,5 @@ public class ClassicConfigGUI
} }
//endregion
} }
@@ -13,14 +13,18 @@ import java.util.regex.Pattern;
import com.seibel.distanthorizons.api.enums.config.DisallowSelectingViaConfigGui; import com.seibel.distanthorizons.api.enums.config.DisallowSelectingViaConfigGui;
import com.seibel.distanthorizons.common.wrappers.gui.DhScreen; import com.seibel.distanthorizons.common.wrappers.gui.DhScreen;
import com.seibel.distanthorizons.common.wrappers.gui.GuiHelper;
import com.seibel.distanthorizons.common.wrappers.gui.TexturedButtonWidget; import com.seibel.distanthorizons.common.wrappers.gui.TexturedButtonWidget;
import com.seibel.distanthorizons.common.wrappers.gui.config.ConfigGuiInfo; import com.seibel.distanthorizons.common.wrappers.gui.config.ConfigGuiInfo;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftClientWrapper; import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftClientWrapper;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.config.ConfigHandler; import com.seibel.distanthorizons.core.config.ConfigHandler;
import com.seibel.distanthorizons.core.config.types.*; import com.seibel.distanthorizons.core.config.types.*;
#if MC_VER <= MC_1_12_2
import com.seibel.distanthorizons.common.wrappers.gui.OnPressed;
#else
import com.seibel.distanthorizons.common.wrappers.gui.updater.ChangelogScreen; import com.seibel.distanthorizons.common.wrappers.gui.updater.ChangelogScreen;
#endif
import com.seibel.distanthorizons.core.config.types.enums.EConfigCommentTextPosition; import com.seibel.distanthorizons.core.config.types.enums.EConfigCommentTextPosition;
import com.seibel.distanthorizons.core.config.types.enums.EConfigValidity; import com.seibel.distanthorizons.core.config.types.enums.EConfigValidity;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
@@ -30,8 +34,15 @@ import com.seibel.distanthorizons.core.util.AnnotationUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.config.IConfigGui; import com.seibel.distanthorizons.core.wrapperInterfaces.config.IConfigGui;
import com.seibel.distanthorizons.core.wrapperInterfaces.config.ILangWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.config.ILangWrapper;
import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.ModInfo;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
#if MC_VER <= MC_1_12_2
import net.minecraft.client.gui.*;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.Style;
import net.minecraft.util.text.TextFormatting;
#else
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.Font; import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Button;
@@ -40,12 +51,13 @@ import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
#endif
import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLogger;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
#if MC_VER <= MC_1_12_2
#if MC_VER < MC_1_20_1 #elif MC_VER < MC_1_20_1
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.GuiComponent; import net.minecraft.client.gui.GuiComponent;
#elif MC_VER <= MC_1_21_11 #elif MC_VER <= MC_1_21_11
@@ -58,14 +70,18 @@ import net.minecraft.client.gui.GuiGraphicsExtractor;
import net.minecraft.client.gui.narration.NarratableEntry; import net.minecraft.client.gui.narration.NarratableEntry;
#endif #endif
#if MC_VER <= MC_1_21_10 #if MC_VER <= MC_1_12_2
import net.minecraft.util.ResourceLocation;
#elif MC_VER <= MC_1_21_10
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
#else #else
import net.minecraft.resources.Identifier; import net.minecraft.resources.Identifier;
#endif #endif
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
#if MC_VER > MC_1_12_2
import com.mojang.blaze3d.platform.InputConstants; import com.mojang.blaze3d.platform.InputConstants;
#endif
import static com.seibel.distanthorizons.common.wrappers.gui.GuiHelper.*; import static com.seibel.distanthorizons.common.wrappers.gui.GuiHelper.*;
import static com.seibel.distanthorizons.common.wrappers.gui.GuiHelper.Translatable; import static com.seibel.distanthorizons.common.wrappers.gui.GuiHelper.Translatable;
@@ -79,21 +95,34 @@ class DhConfigScreen extends DhScreen
private static final MinecraftClientWrapper MC_CLIENT = MinecraftClientWrapper.INSTANCE; private static final MinecraftClientWrapper MC_CLIENT = MinecraftClientWrapper.INSTANCE;
#if MC_VER <= MC_1_12_2
private final GuiScreen parent;
#else
private final Screen parent; private final Screen parent;
#endif
private final String category; private final String category;
private ClassicConfigGUI.ConfigListWidget configListWidget; private ClassicConfigGUI.ConfigListWidget configListWidget;
private boolean reload = false; private boolean reload = false;
#if MC_VER <= MC_1_12_2
private GuiButton doneButton;
#else
private Button doneButton; private Button doneButton;
#endif
//=============// //=============//
// constructor // // constructor //
//=============// //=============//
//region
#if MC_VER <= MC_1_12_2
protected DhConfigScreen(GuiScreen parent, String category)
#else
protected DhConfigScreen(Screen parent, String category) protected DhConfigScreen(Screen parent, String category)
#endif
{ {
super(Translatable( super(Translatable(
LANG_WRAPPER.langExists(ModInfo.ID + ".config" + (category.isEmpty() ? "." + category : "") + ".title") ? LANG_WRAPPER.langExists(ModInfo.ID + ".config" + (category.isEmpty() ? "." + category : "") + ".title") ?
@@ -104,25 +133,50 @@ class DhConfigScreen extends DhScreen
this.category = category; this.category = category;
} }
//endregion
//===================//
// menu UI lifecycle //
//===================//
//region
@Override @Override
#if MC_VER <= MC_1_12_2
public void updateScreen() { super.updateScreen(); }
#else
public void tick() { super.tick(); } public void tick() { super.tick(); }
#endif
//endregion
//==================// //==================//
// menu UI creation // // menu UI creation //
//==================// //==================//
//region
@Override @Override
#if MC_VER <= MC_1_12_2
public void initGui()
#else
protected void init() protected void init()
#endif
{ {
#if MC_VER <= MC_1_12_2
super.initGui();
#else
super.init(); super.init();
#endif
if (!this.reload) if (!this.reload)
{ {
ConfigHandler.INSTANCE.configFileHandler.loadFromFile(); ConfigHandler.INSTANCE.configFileHandler.loadFromFile();
} }
#if MC_VER > MC_1_12_2
// Changelog button // Changelog button
if (Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get() if (Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get()
// we only have changelogs for stable builds // we only have changelogs for stable builds
@@ -161,6 +215,7 @@ class DhConfigScreen extends DhScreen
Translatable(ModInfo.ID + ".updater.title") Translatable(ModInfo.ID + ".updater.title")
)); ));
} }
#endif
// back button // back button
@@ -170,7 +225,11 @@ class DhConfigScreen extends DhScreen
(button) -> (button) ->
{ {
ConfigHandler.INSTANCE.configFileHandler.loadFromFile(); ConfigHandler.INSTANCE.configFileHandler.loadFromFile();
#if MC_VER <= MC_1_12_2
Objects.requireNonNull(this.mc).displayGuiScreen(this.parent);
#else
Objects.requireNonNull(this.minecraft).setScreen(this.parent); Objects.requireNonNull(this.minecraft).setScreen(this.parent);
#endif
})); }));
// done/close button // done/close button
@@ -181,19 +240,30 @@ class DhConfigScreen extends DhScreen
(button) -> (button) ->
{ {
ConfigHandler.INSTANCE.configFileHandler.saveToFile(); ConfigHandler.INSTANCE.configFileHandler.saveToFile();
#if MC_VER <= MC_1_12_2
Objects.requireNonNull(this.mc).displayGuiScreen(this.parent);
#else
Objects.requireNonNull(this.minecraft).setScreen(this.parent); Objects.requireNonNull(this.minecraft).setScreen(this.parent);
#endif
})); }));
#if MC_VER <= MC_1_12_2
this.configListWidget = new ClassicConfigGUI.ConfigListWidget(this.mc, this.width * 2, this.height, 32, 32, 25);
#else
this.configListWidget = new ClassicConfigGUI.ConfigListWidget(this.minecraft, this.width * 2, this.height, 32, 32, 25); this.configListWidget = new ClassicConfigGUI.ConfigListWidget(this.minecraft, this.width * 2, this.height, 32, 32, 25);
#endif
#if MC_VER < MC_1_20_6 // no background is rendered in MC 1.20.6+ #if MC_VER <= MC_1_12_2
#elif MC_VER < MC_1_20_6 // no background is rendered in MC 1.20.6+
if (this.minecraft != null && this.minecraft.level != null) if (this.minecraft != null && this.minecraft.level != null)
{ {
this.configListWidget.setRenderBackground(false); this.configListWidget.setRenderBackground(false);
} }
#endif #endif
#if MC_VER > MC_1_12_2
this.addWidget(this.configListWidget); this.addWidget(this.configListWidget);
#endif
for (AbstractConfigBase<?> configEntry : ConfigHandler.INSTANCE.configBaseList) for (AbstractConfigBase<?> configEntry : ConfigHandler.INSTANCE.configBaseList)
{ {
@@ -356,18 +426,35 @@ class DhConfigScreen extends DhScreen
private static void setupBooleanMenuOption(ConfigEntry<Boolean> booleanConfigEntry) private static void setupBooleanMenuOption(ConfigEntry<Boolean> booleanConfigEntry)
{ {
// For boolean // For boolean
#if MC_VER <= MC_1_12_2
Function<Object, ITextComponent> func = value -> Translatable("distanthorizons.general."+((Boolean) value ? "true" : "false")).setStyle(new Style().setColor((Boolean) value ? TextFormatting.GREEN : TextFormatting.RED));
#else
Function<Object, Component> func = value -> Translatable("distanthorizons.general." + ((Boolean) value ? "true" : "false")).withStyle((Boolean) value ? ChatFormatting.GREEN : ChatFormatting.RED); Function<Object, Component> func = value -> Translatable("distanthorizons.general." + ((Boolean) value ? "true" : "false")).withStyle((Boolean) value ? ChatFormatting.GREEN : ChatFormatting.RED);
#endif
final ConfigGuiInfo configGuiInfo = ((ConfigGuiInfo) booleanConfigEntry.guiValue); final ConfigGuiInfo configGuiInfo = ((ConfigGuiInfo) booleanConfigEntry.guiValue);
configGuiInfo.buttonOptionMap = configGuiInfo.buttonOptionMap =
#if MC_VER <= MC_1_12_2
new AbstractMap.SimpleEntry<OnPressed, Function<Object, ITextComponent>>(
#else
new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>( new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>(
#endif
(button) -> (button) ->
{ {
#if MC_VER <= MC_1_12_2
button.enabled = !booleanConfigEntry.apiIsOverriding();
#else
button.active = !booleanConfigEntry.apiIsOverriding(); button.active = !booleanConfigEntry.apiIsOverriding();
#endif
booleanConfigEntry.uiSetWithoutSaving(!booleanConfigEntry.get()); booleanConfigEntry.uiSetWithoutSaving(!booleanConfigEntry.get());
#if MC_VER <= MC_1_12_2
button.displayString = func.apply(booleanConfigEntry.get()).getFormattedText();
#else
button.setMessage(func.apply(booleanConfigEntry.get())); button.setMessage(func.apply(booleanConfigEntry.get()));
#endif
}, func); }, func);
} }
private static void setupEnumMenuOption(ConfigEntry<Enum<?>> enumConfigEntry, Class<? extends Enum<?>> enumClass) private static void setupEnumMenuOption(ConfigEntry<Enum<?>> enumConfigEntry, Class<? extends Enum<?>> enumClass)
@@ -376,20 +463,29 @@ class DhConfigScreen extends DhScreen
final ConfigGuiInfo configGuiInfo = ((ConfigGuiInfo) enumConfigEntry.guiValue); final ConfigGuiInfo configGuiInfo = ((ConfigGuiInfo) enumConfigEntry.guiValue);
#if MC_VER <= MC_1_12_2
Function<Object, ITextComponent > getEnumTranslatableFunc = (value) -> Translatable(TRANSLATION_PREFIX + "enum." + enumClass.getSimpleName() + "." + enumConfigEntry.get().toString());
#else
Function<Object, Component> getEnumTranslatableFunc = (value) -> Translatable(TRANSLATION_PREFIX + "enum." + enumClass.getSimpleName() + "." + enumConfigEntry.get().toString()); Function<Object, Component> getEnumTranslatableFunc = (value) -> Translatable(TRANSLATION_PREFIX + "enum." + enumClass.getSimpleName() + "." + enumConfigEntry.get().toString());
#endif
configGuiInfo.buttonOptionMap = configGuiInfo.buttonOptionMap =
#if MC_VER <= MC_1_12_2
new AbstractMap.SimpleEntry<OnPressed, Function<Object, ITextComponent>>(
#else
new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>( new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>(
#endif
(button) -> (button) ->
{ {
// get the currently selected enum and enum index // get the currently selected enum and enum index
int startingIndex = enumList.indexOf(enumConfigEntry.get()); int startingIndex = enumList.indexOf(enumConfigEntry.get());
Enum<?> enumValue = enumList.get(startingIndex); Enum<?> enumValue = enumList.get(startingIndex);
boolean shiftPressed = #if MC_VER <= MC_1_12_2
InputConstants.isKeyDown(MC_CLIENT.getGlfwWindowId(), GLFW.GLFW_KEY_LEFT_SHIFT) boolean shiftPressed = GuiScreen.isShiftKeyDown();
|| InputConstants.isKeyDown(MC_CLIENT.getGlfwWindowId(), GLFW.GLFW_KEY_RIGHT_SHIFT); #else
boolean shiftPressed = InputConstants.isKeyDown(MC_CLIENT.getGlfwWindowId(), GLFW.GLFW_KEY_LEFT_SHIFT) || InputConstants.isKeyDown(MC_CLIENT.getGlfwWindowId(), GLFW.GLFW_KEY_RIGHT_SHIFT);
#endif
// move forward or backwards depending on if the shift key is pressed // move forward or backwards depending on if the shift key is pressed
int index = shiftPressed ? startingIndex - 1 : startingIndex + 1; int index = shiftPressed ? startingIndex - 1 : startingIndex + 1;
@@ -441,9 +537,13 @@ class DhConfigScreen extends DhScreen
enumConfigEntry.uiSetWithoutSaving(enumValue); enumConfigEntry.uiSetWithoutSaving(enumValue);
#if MC_VER <= MC_1_12_2
button.enabled = !enumConfigEntry.apiIsOverriding();
button.displayString = getEnumTranslatableFunc.apply(enumConfigEntry.get()).getFormattedText();
#else
button.active = !enumConfigEntry.apiIsOverriding(); button.active = !enumConfigEntry.apiIsOverriding();
button.setMessage(getEnumTranslatableFunc.apply(enumConfigEntry.get())); button.setMessage(getEnumTranslatableFunc.apply(enumConfigEntry.get()));
#endif
}, getEnumTranslatableFunc); }, getEnumTranslatableFunc);
} }
@@ -459,12 +559,18 @@ class DhConfigScreen extends DhScreen
//==============// //==============//
// reset button // // reset button //
//==============// //==============//
//region
Button.OnPress btnAction = (button) -> #if MC_VER <= MC_1_12_2 OnPressed #else Button.OnPress #endif btnAction = (button) ->
{ {
configEntry.uiSetWithoutSaving(configEntry.getDefaultValue()); configEntry.uiSetWithoutSaving(configEntry.getDefaultValue());
this.reload = true; this.reload = true;
Objects.requireNonNull(this.minecraft).setScreen(this);
#if MC_VER <= MC_1_12_2
Objects.requireNonNull(this.mc).displayGuiScreen(ClassicConfigGUI.getScreen(this.parent, this.category));
#else
Objects.requireNonNull(this.minecraft).setScreen(this.parent);
#endif
}; };
int resetButtonPosX = this.width int resetButtonPosX = this.width
@@ -472,29 +578,60 @@ class DhConfigScreen extends DhScreen
- ClassicConfigGUI.ConfigScreenConfigs.SPACE_FROM_RIGHT_SCREEN; - ClassicConfigGUI.ConfigScreenConfigs.SPACE_FROM_RIGHT_SCREEN;
int resetButtonPosZ = 0; int resetButtonPosZ = 0;
Button resetButton = MakeBtn( #if MC_VER <= MC_1_12_2 GuiButton #else Button #endif resetButton = MakeBtn(
#if MC_VER <= MC_1_12_2
Translatable("distanthorizons.general.reset").setStyle(new Style().setColor(TextFormatting.RED)),
#else
Translatable("distanthorizons.general.reset").withStyle(ChatFormatting.RED), Translatable("distanthorizons.general.reset").withStyle(ChatFormatting.RED),
#endif
resetButtonPosX, resetButtonPosZ, resetButtonPosX, resetButtonPosZ,
ClassicConfigGUI.ConfigScreenConfigs.RESET_BUTTON_WIDTH, ClassicConfigGUI.ConfigScreenConfigs.RESET_BUTTON_HEIGHT, ClassicConfigGUI.ConfigScreenConfigs.RESET_BUTTON_WIDTH, ClassicConfigGUI.ConfigScreenConfigs.RESET_BUTTON_HEIGHT,
btnAction); btnAction);
if (configEntry.apiIsOverriding())
if (configEntry.mcVersionOverridePresent())
{ {
#if MC_VER <= MC_1_12_2
resetButton.enabled = false;
resetButton.displayString = Translatable("distanthorizons.general.unsupportedMcVersion").setStyle(new Style().setColor(TextFormatting.DARK_GRAY)).getFormattedText();
#else
resetButton.active = false;
resetButton.setMessage(Translatable("distanthorizons.general.unsupportedMcVersion").withStyle(ChatFormatting.DARK_GRAY));
#endif
}
else if (configEntry.apiIsOverriding())
{
#if MC_VER <= MC_1_12_2
resetButton.enabled = false;
resetButton.displayString = Translatable("distanthorizons.general.apiOverride").setStyle(new Style().setColor(TextFormatting.DARK_GRAY)).getFormattedText();
#else
resetButton.active = false; resetButton.active = false;
resetButton.setMessage(Translatable("distanthorizons.general.apiOverride").withStyle(ChatFormatting.DARK_GRAY)); resetButton.setMessage(Translatable("distanthorizons.general.apiOverride").withStyle(ChatFormatting.DARK_GRAY));
#endif
} }
else else
{ {
#if MC_VER <= MC_1_12_2
resetButton.enabled = true;
#else
resetButton.active = true; resetButton.active = true;
#endif
} }
//endregion
//==============// //==============//
// option field // // option field //
//==============// //==============//
//region
#if MC_VER <= MC_1_12_2
ITextComponent textComponent = this.GetTranslatableTextComponentForConfig(configEntry);
#else
Component textComponent = this.GetTranslatableTextComponentForConfig(configEntry); Component textComponent = this.GetTranslatableTextComponentForConfig(configEntry);
#endif
int optionFieldPosX = this.width int optionFieldPosX = this.width
- ClassicConfigGUI.ConfigScreenConfigs.SPACE_FROM_RIGHT_SCREEN - ClassicConfigGUI.ConfigScreenConfigs.SPACE_FROM_RIGHT_SCREEN
@@ -506,21 +643,40 @@ class DhConfigScreen extends DhScreen
if (configGuiInfo.buttonOptionMap != null) if (configGuiInfo.buttonOptionMap != null)
{ {
// enum/multi option input button // enum/multi option input button
#if MC_VER <= MC_1_12_2
Map.Entry<OnPressed, Function<Object,ITextComponent>> widget = configGuiInfo.buttonOptionMap;
#else
Map.Entry<Button.OnPress, Function<Object, Component>> widget = configGuiInfo.buttonOptionMap; Map.Entry<Button.OnPress, Function<Object, Component>> widget = configGuiInfo.buttonOptionMap;
#endif
if (configEntry.getType().isEnum()) if (configEntry.getType().isEnum())
{ {
widget.setValue((value) -> Translatable(TRANSLATION_PREFIX + "enum." + configEntry.getType().getSimpleName() + "." + configEntry.get().toString())); widget.setValue((value) -> Translatable(TRANSLATION_PREFIX + "enum." + configEntry.getType().getSimpleName() + "." + configEntry.get().toString()));
} }
#if MC_VER <= MC_1_12_2
GuiButton button = MakeBtn(
#else
Button button = MakeBtn( Button button = MakeBtn(
#endif
widget.getValue().apply(configEntry.get()), widget.getValue().apply(configEntry.get()),
optionFieldPosX, optionFieldPosZ, optionFieldPosX, optionFieldPosZ,
ClassicConfigGUI.ConfigScreenConfigs.OPTION_FIELD_WIDTH, ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT, ClassicConfigGUI.ConfigScreenConfigs.OPTION_FIELD_WIDTH, ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT,
widget.getKey()); widget.getKey());
// deactivate the button if the API is overriding it // deactivate the button if the API is overriding it
button.active = !configEntry.apiIsOverriding(); // or the MC version doesn't support it
if (configEntry.mcVersionOverridePresent()
|| configEntry.apiIsOverriding())
{
#if MC_VER <= MC_1_12_2
button.enabled = false;
#else
button.active = false;
#endif
}
this.configListWidget.addButton(this, configEntry, this.configListWidget.addButton(this, configEntry,
@@ -534,16 +690,25 @@ class DhConfigScreen extends DhScreen
else else
{ {
// text box input // text box input
#if MC_VER <= MC_1_12_2
GuiTextField widget = new GuiTextField(0, this.fontRenderer,
optionFieldPosX, optionFieldPosZ,
ClassicConfigGUI.ConfigScreenConfigs.OPTION_FIELD_WIDTH - 4, ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT);
widget.setMaxStringLength(3_000_000); // hopefully 3 million characters should be enough for any normal use-case, lol
widget.setText(String.valueOf(configEntry.get()));
#else
EditBox widget = new EditBox(this.font, EditBox widget = new EditBox(this.font,
optionFieldPosX, optionFieldPosZ, optionFieldPosX, optionFieldPosZ,
ClassicConfigGUI.ConfigScreenConfigs.OPTION_FIELD_WIDTH - 4, ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT, ClassicConfigGUI.ConfigScreenConfigs.OPTION_FIELD_WIDTH - 4, ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT,
Translatable("")); Translatable(""));
widget.setMaxLength(3_000_000); // hopefully 3 million characters should be enough for any normal use-case, lol widget.setMaxLength(3_000_000); // hopefully 3 million characters should be enough for any normal use-case, lol
widget.insertText(String.valueOf(configEntry.get())); widget.insertText(String.valueOf(configEntry.get()));
#endif
Predicate<String> processor = configGuiInfo.tooltipFunction.apply(widget, this.doneButton); Predicate<String> processor = configGuiInfo.tooltipFunction.apply(widget, this.doneButton);
#if MC_VER <= MC_1_21_11 #if MC_VER <= MC_1_12_2
widget.setValidator(processor::test);
#elif MC_VER <= MC_1_21_11
widget.setFilter(processor); widget.setFilter(processor);
#else #else
widget.setResponder(processor::test); widget.setResponder(processor::test);
@@ -553,6 +718,8 @@ class DhConfigScreen extends DhScreen
return true; return true;
} }
//endregion
} }
return false; return false;
@@ -563,18 +730,31 @@ class DhConfigScreen extends DhScreen
{ {
ConfigCategory configCategory = (ConfigCategory) configType; ConfigCategory configCategory = (ConfigCategory) configType;
#if MC_VER <= MC_1_12_2
ITextComponent textComponent = this.GetTranslatableTextComponentForConfig(configCategory);
#else
Component textComponent = this.GetTranslatableTextComponentForConfig(configCategory); Component textComponent = this.GetTranslatableTextComponentForConfig(configCategory);
#endif
int categoryPosX = this.width - ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_WIDTH - ClassicConfigGUI.ConfigScreenConfigs.SPACE_FROM_RIGHT_SCREEN; int categoryPosX = this.width - ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_WIDTH - ClassicConfigGUI.ConfigScreenConfigs.SPACE_FROM_RIGHT_SCREEN;
int categoryPosZ = this.height - ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT; // Note: the posZ value here seems to be ignored int categoryPosZ = this.height - ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT; // Note: the posZ value here seems to be ignored
Button widget = MakeBtn(textComponent, #if MC_VER <= MC_1_12_2
GuiButton widget = MakeBtn(
#else
Button widget = MakeBtn(
#endif
textComponent,
categoryPosX, categoryPosZ, categoryPosX, categoryPosZ,
ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_WIDTH, ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT, ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_WIDTH, ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT,
((button) -> ((button) ->
{ {
ConfigHandler.INSTANCE.configFileHandler.saveToFile(); ConfigHandler.INSTANCE.configFileHandler.saveToFile();
#if MC_VER <= MC_1_12_2
Objects.requireNonNull(this.mc).displayGuiScreen(ClassicConfigGUI.getScreen(this, configCategory.getDestination()));
#else
Objects.requireNonNull(this.minecraft).setScreen(ClassicConfigGUI.getScreen(this, configCategory.getDestination())); Objects.requireNonNull(this.minecraft).setScreen(ClassicConfigGUI.getScreen(this, configCategory.getDestination()));
#endif
})); }));
this.configListWidget.addButton(this, configType, widget, null, null, null); this.configListWidget.addButton(this, configType, widget, null, null, null);
@@ -589,11 +769,20 @@ class DhConfigScreen extends DhScreen
{ {
ConfigUIButton configUiButton = (ConfigUIButton) configType; ConfigUIButton configUiButton = (ConfigUIButton) configType;
#if MC_VER <= MC_1_12_2
ITextComponent textComponent = this.GetTranslatableTextComponentForConfig(configUiButton);
#else
Component textComponent = this.GetTranslatableTextComponentForConfig(configUiButton); Component textComponent = this.GetTranslatableTextComponentForConfig(configUiButton);
#endif
int buttonPosX = this.width - ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_WIDTH - ClassicConfigGUI.ConfigScreenConfigs.SPACE_FROM_RIGHT_SCREEN; int buttonPosX = this.width - ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_WIDTH - ClassicConfigGUI.ConfigScreenConfigs.SPACE_FROM_RIGHT_SCREEN;
Button widget = MakeBtn(textComponent, #if MC_VER <= MC_1_12_2
GuiButton widget = MakeBtn(
#else
Button widget = MakeBtn(
#endif
textComponent,
buttonPosX, this.height - 28, buttonPosX, this.height - 28,
ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_WIDTH, ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT, ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_WIDTH, ClassicConfigGUI.ConfigScreenConfigs.CATEGORY_BUTTON_HEIGHT,
(button) -> ((ConfigUIButton) configType).runAction()); (button) -> ((ConfigUIButton) configType).runAction());
@@ -610,7 +799,11 @@ class DhConfigScreen extends DhScreen
{ {
ConfigUIComment configUiComment = (ConfigUIComment) configType; ConfigUIComment configUiComment = (ConfigUIComment) configType;
#if MC_VER <= MC_1_12_2
ITextComponent textComponent = this.GetTranslatableTextComponentForConfig(configUiComment);
#else
Component textComponent = this.GetTranslatableTextComponentForConfig(configUiComment); Component textComponent = this.GetTranslatableTextComponentForConfig(configUiComment);
#endif
if (configUiComment.parentConfigPath != null) if (configUiComment.parentConfigPath != null)
{ {
textComponent = Translatable(TRANSLATION_PREFIX + configUiComment.parentConfigPath); textComponent = Translatable(TRANSLATION_PREFIX + configUiComment.parentConfigPath);
@@ -626,8 +819,13 @@ class DhConfigScreen extends DhScreen
private boolean tryCreateSpacer(AbstractConfigBase<?> configType) private boolean tryCreateSpacer(AbstractConfigBase<?> configType)
{ {
if (configType instanceof ConfigUISpacer) if (configType instanceof ConfigUISpacer)
{ {
Button spacerButton = MakeBtn(Translatable("distanthorizons.general.spacer"), #if MC_VER <= MC_1_12_2
GuiButton spacerButton = MakeBtn(
#else
Button spacerButton = MakeBtn(
#endif
Translatable("distanthorizons.general.spacer"),
10, 10, // having too small of a size causes division by 0 errors in older MC versions (IE 1.20.1) 10, 10, // having too small of a size causes division by 0 errors in older MC versions (IE 1.20.1)
1, 1, 1, 1,
(button) -> { }); (button) -> { });
@@ -652,25 +850,36 @@ class DhConfigScreen extends DhScreen
return false; return false;
} }
#if MC_VER <= MC_1_12_2
private ITextComponent GetTranslatableTextComponentForConfig(AbstractConfigBase<?> configType)
#else
private Component GetTranslatableTextComponentForConfig(AbstractConfigBase<?> configType) private Component GetTranslatableTextComponentForConfig(AbstractConfigBase<?> configType)
#endif
{ return Translatable(TRANSLATION_PREFIX + configType.getNameAndCategory()); } { return Translatable(TRANSLATION_PREFIX + configType.getNameAndCategory()); }
//endregion
//===========// //===========//
// rendering // // rendering //
//===========// //===========//
//region
@Override @Override
#if MC_VER < MC_1_20_1 #if MC_VER <= MC_1_12_2
public void drawScreen(int mouseX, int mouseY, float delta)
#elif MC_VER < MC_1_20_1
public void render(PoseStack matrices, int mouseX, int mouseY, float delta) public void render(PoseStack matrices, int mouseX, int mouseY, float delta)
#elif MC_VER <= MC_1_21_11 #elif MC_VER <= MC_1_21_11
public void render(GuiGraphics matrices, int mouseX, int mouseY, float delta) public void render(GuiGraphics matrices, int mouseX, int mouseY, float delta)
#else #else
public void extractRenderState(GuiGraphicsExtractor matrices, int mouseX, int mouseY, float delta) public void extractRenderState(GuiGraphicsExtractor matrices, int mouseX, int mouseY, float delta)
#endif #endif
{ {
#if MC_VER < MC_1_20_2 // 1.20.2 now enables this by default in the `this.list.render` function #if MC_VER <= MC_1_12_2
this.drawDefaultBackground();
#elif MC_VER < MC_1_20_2 // 1.20.2 now enables this by default in the `this.list.render` function
this.renderBackground(matrices); this.renderBackground(matrices);
#elif MC_VER <= MC_1_21_11 #elif MC_VER <= MC_1_21_11
super.render(matrices, mouseX, mouseY, delta); super.render(matrices, mouseX, mouseY, delta);
@@ -679,7 +888,9 @@ class DhConfigScreen extends DhScreen
#endif #endif
// Render buttons // Render buttons
#if MC_VER <= MC_1_21_11 #if MC_VER <= MC_1_12_2
this.configListWidget.drawScreen(mouseX, mouseY, delta);
#elif MC_VER <= MC_1_21_11
this.configListWidget.render(matrices, mouseX, mouseY, delta); this.configListWidget.render(matrices, mouseX, mouseY, delta);
#else #else
this.configListWidget.extractRenderState(matrices, mouseX, mouseY, delta); this.configListWidget.extractRenderState(matrices, mouseX, mouseY, delta);
@@ -687,51 +898,74 @@ class DhConfigScreen extends DhScreen
// Render config title // Render config title
this.DhDrawCenteredString(matrices, this.font, this.title, this.DhDrawCenteredString(
#if MC_VER > MC_1_12_2
matrices, this.font,
#endif
this.title,
this.width / 2, 15, this.width / 2, 15,
#if MC_VER < MC_1_21_6 #if MC_VER < MC_1_21_6
0xFFFFFF // RGB white 0xFFFFFF // RGB white
#else #else
0xFFFFFFFF // ARGB white 0xFFFFFFFF // ARGB white
#endif ); #endif);
// render DH version // render DH version
this.DhDrawString(matrices, this.font, TextOrLiteral(ModInfo.VERSION), 2, this.height - 10, this.DhDrawString(
#if MC_VER < MC_1_21_6 #if MC_VER > MC_1_12_2
matrices, this.font,
#endif
TextOrLiteral(ModInfo.VERSION), 2, this.height - 10,
#if MC_VER < MC_1_21_6
0xAAAAAA // RGB white 0xAAAAAA // RGB white
#else #else
0xFFAAAAAA // ARGB white 0xFFAAAAAA // ARGB white
#endif ); #endif);
// If the update is pending, display this message to inform the user that it will apply when the game restarts // If the update is pending, display this message to inform the user that it will apply when the game restarts
if (SelfUpdater.deleteOldJarOnJvmShutdown) if (SelfUpdater.deleteOldJarOnJvmShutdown)
{ {
this.DhDrawString(matrices, this.font, Translatable(ModInfo.ID + ".updater.waitingForClose"), 4, this.height - 42, this.DhDrawString(
#if MC_VER < MC_1_21_6 #if MC_VER > MC_1_12_2
matrices, this.font,
#endif
Translatable(ModInfo.ID + ".updater.waitingForClose"), 4, this.height - 42,
#if MC_VER < MC_1_21_6
0xFFFFFF // RGB white 0xFFFFFF // RGB white
#else #else
0xFFFFFFFF // ARGB white 0xFFFFFFFF // ARGB white
#endif ); #endif);
} }
#if MC_VER <= MC_1_12_2
this.renderTooltip(mouseX, mouseY, delta);
#else
this.renderTooltip(matrices, mouseX, mouseY, delta); this.renderTooltip(matrices, mouseX, mouseY, delta);
#endif
#if MC_VER < MC_1_20_2 #if MC_VER <= MC_1_12_2
super.drawScreen(mouseX, mouseY, delta);
#elif MC_VER < MC_1_20_2
super.render(matrices, mouseX, mouseY, delta); super.render(matrices, mouseX, mouseY, delta);
#endif #endif
} }
#if MC_VER < MC_1_20_1 #if MC_VER <= MC_1_12_2
private void renderTooltip(int mouseX, int mouseY, float delta)
#elif MC_VER < MC_1_20_1
private void renderTooltip(PoseStack matrices, int mouseX, int mouseY, float delta) private void renderTooltip(PoseStack matrices, int mouseX, int mouseY, float delta)
#elif MC_VER <= MC_1_21_11 #elif MC_VER <= MC_1_21_11
private void renderTooltip(GuiGraphics matrices, int mouseX, int mouseY, float delta) private void renderTooltip(GuiGraphics matrices, int mouseX, int mouseY, float delta)
#else #else
private void renderTooltip(GuiGraphicsExtractor matrices, int mouseX, int mouseY, float delta) private void renderTooltip(GuiGraphicsExtractor matrices, int mouseX, int mouseY, float delta)
#endif #endif
{ {
#if MC_VER <= MC_1_12_2
Gui hoveredWidget = this.configListWidget.getHoveredButton(mouseX, mouseY);
#else
AbstractWidget hoveredWidget = this.configListWidget.getHoveredButton(mouseX, mouseY); AbstractWidget hoveredWidget = this.configListWidget.getHoveredButton(mouseX, mouseY);
#endif
if (hoveredWidget == null) if (hoveredWidget == null)
{ {
return; return;
@@ -747,14 +981,21 @@ class DhConfigScreen extends DhScreen
button.dhConfigType; button.dhConfigType;
boolean apiOverrideActive = false; boolean apiOverrideActive = false;
boolean unsupportedMcVersion = false;
if (configBase instanceof ConfigEntry) if (configBase instanceof ConfigEntry)
{ {
apiOverrideActive = ((ConfigEntry<?>) configBase).apiIsOverriding(); apiOverrideActive = ((ConfigEntry<?>) configBase).apiIsOverriding();
unsupportedMcVersion = ((ConfigEntry<?>) configBase).mcVersionOverridePresent();
} }
String key = TRANSLATION_PREFIX + (configBase.category.isEmpty() ? "" : configBase.category + ".") + configBase.getName() + ".@tooltip"; String key = TRANSLATION_PREFIX + (configBase.category.isEmpty() ? "" : configBase.category + ".") + configBase.getName() + ".@tooltip";
if (apiOverrideActive) if (unsupportedMcVersion)
{
key = "distanthorizons.general.unsupportedMcVersion.@tooltip";
}
else if (apiOverrideActive)
{ {
key = "distanthorizons.general.disabledByApi.@tooltip"; key = "distanthorizons.general.disabledByApi.@tooltip";
} }
@@ -763,37 +1004,116 @@ class DhConfigScreen extends DhScreen
final ConfigGuiInfo configGuiInfo = ((ConfigGuiInfo) configBase.guiValue); final ConfigGuiInfo configGuiInfo = ((ConfigGuiInfo) configBase.guiValue);
if (configGuiInfo.errorMessage != null) if (configGuiInfo.errorMessage != null)
{ {
#if MC_VER <= MC_1_12_2
this.DhRenderTooltip(configGuiInfo.errorMessage, mouseX, mouseY);
#else
this.DhRenderTooltip(matrices, this.font, configGuiInfo.errorMessage, mouseX, mouseY); this.DhRenderTooltip(matrices, this.font, configGuiInfo.errorMessage, mouseX, mouseY);
#endif
} }
// display the tooltip if present // display the tooltip if present
else if (LANG_WRAPPER.langExists(key)) else if (LANG_WRAPPER.langExists(key))
{ {
#if MC_VER <= MC_1_12_2
List<ITextComponent> list = new ArrayList<>();
#else
List<Component> list = new ArrayList<>(); List<Component> list = new ArrayList<>();
#endif
String lang = LANG_WRAPPER.getLang(key); String lang = LANG_WRAPPER.getLang(key);
for (String langLine : lang.split("\n")) for (String langLine : lang.split("\n"))
{ {
list.add(TextOrTranslatable(langLine)); list.add(TextOrTranslatable(langLine));
} }
#if MC_VER <= MC_1_12_2
this.DhRenderComponentTooltip(list, mouseX, mouseY);
#else
this.DhRenderComponentTooltip(matrices, this.font, list, mouseX, mouseY); this.DhRenderComponentTooltip(matrices, this.font, list, mouseX, mouseY);
#endif
} }
} }
#if MC_VER <= MC_1_12_2
@Override
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws java.io.IOException
{
super.mouseClicked(mouseX, mouseY, mouseButton);
if (mouseY >= this.configListWidget.top && mouseY <= this.configListWidget.bottom)
{
for (ClassicConfigGUI.DhButtonEntry entry : this.configListWidget.children)
{
if (entry.button instanceof GuiButton btn && btn.visible)
{
if (btn.mousePressed(this.mc, mouseX, mouseY))
{
btn.playPressSound(this.mc.getSoundHandler());
OnPressed handler = GuiHelper.HANDLER_BY_BUTTON.get(btn);
if (handler != null) handler.pressed(btn);
}
}
else if (entry.button instanceof GuiTextField field && field.getVisible())
{
field.mouseClicked(mouseX, mouseY, mouseButton);
}
if (entry.resetButton instanceof GuiButton reset && reset.visible)
{
if (reset.mousePressed(this.mc, mouseX, mouseY))
{
reset.playPressSound(this.mc.getSoundHandler());
OnPressed handler = GuiHelper.HANDLER_BY_BUTTON.get(reset);
if (handler != null) handler.pressed(reset);
}
}
}
}
}
@Override
protected void keyTyped(char typedChar, int keyCode) throws java.io.IOException
{
super.keyTyped(typedChar, keyCode);
for (ClassicConfigGUI.DhButtonEntry entry : this.configListWidget.children)
{
if (entry.button instanceof GuiTextField field)
{
field.textboxKeyTyped(typedChar, keyCode);
}
}
}
@Override
public void handleMouseInput() throws java.io.IOException
{
super.handleMouseInput();
this.configListWidget.handleMouseInput();
}
#endif
//endregion
//==========// //==========//
// shutdown // // shutdown //
//==========// //==========//
//region
/** When you close it, it goes to the previous screen and saves */ /** When you close it, it goes to the previous screen and saves */
@Override @Override
#if MC_VER <= MC_1_12_2
public void onGuiClosed()
#else
public void onClose() public void onClose()
#endif
{ {
ConfigHandler.INSTANCE.configFileHandler.saveToFile(); ConfigHandler.INSTANCE.configFileHandler.saveToFile();
#if MC_VER > MC_1_12_2
Objects.requireNonNull(this.minecraft).setScreen(this.parent); Objects.requireNonNull(this.minecraft).setScreen(this.parent);
#endif
ClassicConfigGUI.CONFIG_CORE_INTERFACE.onScreenChangeListenerList.forEach((listener) -> listener.run()); ClassicConfigGUI.CONFIG_CORE_INTERFACE.onScreenChangeListenerList.forEach((listener) -> listener.run());
} }
//endregion
} }
@@ -2,9 +2,16 @@ package com.seibel.distanthorizons.common.wrappers.gui.config;
import com.seibel.distanthorizons.core.config.gui.IConfigGuiInfo; import com.seibel.distanthorizons.core.config.gui.IConfigGuiInfo;
import com.seibel.distanthorizons.core.config.types.AbstractConfigBase; import com.seibel.distanthorizons.core.config.types.AbstractConfigBase;
#if MC_VER <= MC_1_12_2
import com.seibel.distanthorizons.common.wrappers.gui.OnPressed;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiTextField;
import net.minecraft.util.text.ITextComponent;
#else
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.components.EditBox;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
#endif
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.AbstractMap; import java.util.AbstractMap;
@@ -23,11 +30,25 @@ public class ConfigGuiInfo implements IConfigGuiInfo
* Used to display validation errors. * Used to display validation errors.
* Null if no error is present. * Null if no error is present.
*/ */
@Nullable @Nullable
#if MC_VER <= MC_1_12_2
public ITextComponent errorMessage;
#else
public Component errorMessage; public Component errorMessage;
#endif
#if MC_VER <= MC_1_12_2
public BiFunction<GuiTextField, GuiButton, Predicate<String>> tooltipFunction;
#else
public BiFunction<EditBox, Button , Predicate<String>> tooltipFunction;
#endif
public BiFunction<EditBox, Button, Predicate<String>> tooltipFunction;
/** determines which options the button will show */ /** determines which options the button will show */
#if MC_VER <= MC_1_12_2
public AbstractMap.SimpleEntry<OnPressed, Function<Object, ITextComponent>> buttonOptionMap;
#else
public AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>> buttonOptionMap; public AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>> buttonOptionMap;
#endif
} }
@@ -1,5 +1,5 @@
package com.seibel.distanthorizons.common.wrappers.gui.updater; package com.seibel.distanthorizons.common.wrappers.gui.updater;
#if MC_VER > MC_1_12_2
import com.seibel.distanthorizons.common.wrappers.gui.DhScreen; import com.seibel.distanthorizons.common.wrappers.gui.DhScreen;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
@@ -296,4 +296,5 @@ public class ChangelogScreen extends DhScreen
} }
} }
#endif
@@ -1,5 +1,5 @@
package com.seibel.distanthorizons.common.wrappers.gui.updater; package com.seibel.distanthorizons.common.wrappers.gui.updater;
#if MC_VER > MC_1_12_2
import com.seibel.distanthorizons.api.enums.config.EDhApiUpdateBranch; import com.seibel.distanthorizons.api.enums.config.EDhApiUpdateBranch;
import com.seibel.distanthorizons.common.wrappers.gui.DhScreen; import com.seibel.distanthorizons.common.wrappers.gui.DhScreen;
import com.seibel.distanthorizons.common.wrappers.gui.TexturedButtonWidget; import com.seibel.distanthorizons.common.wrappers.gui.TexturedButtonWidget;
@@ -221,4 +221,5 @@ public class UpdateModScreen extends DhScreen
Objects.requireNonNull(this.minecraft).setScreen(this.parent); // Go to the parent screen Objects.requireNonNull(this.minecraft).setScreen(this.parent); // Go to the parent screen
} }
} }
#endif
@@ -1,20 +1,43 @@
package com.seibel.distanthorizons.common.wrappers.level; package com.seibel.distanthorizons.common.wrappers.level;
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel; import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel;
import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager; import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
#if MC_VER <= MC_1_12_2
import net.minecraft.client.multiplayer.WorldClient;
#else
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
#endif
import net.minecraft.client.Minecraft;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
public class KeyedClientLevelManager implements IKeyedClientLevelManager public class KeyedClientLevelManager implements IKeyedClientLevelManager
{ {
public static final KeyedClientLevelManager INSTANCE = new KeyedClientLevelManager(); public static final KeyedClientLevelManager INSTANCE = new KeyedClientLevelManager();
/** This is set and managed by the ClientApi for servers with support for DH. */ private static class KeyInfo {
@Nullable public final String serverKey;
private IServerKeyedClientLevel serverKeyedLevel = null; public final String levelKey;
public KeyInfo(String serverKey, String levelKey) {
this.serverKey = serverKey;
this.levelKey = levelKey;
}
}
/** Stores the server-provided keys indexed by dimension name for persistence. */
private final Map<String, KeyInfo> keysByDimensionName = new ConcurrentHashMap<>();
/** Cache for already keyed level wrappers to maintain object identity. */
private final Map<#if MC_VER > MC_1_12_2 ClientLevel #else WorldClient #endif, IServerKeyedClientLevel> keyedLevelsCache = Collections.synchronizedMap(new WeakHashMap<>());
/** Allows to keep level manager enabled between loading different keyed levels */ /** Allows to keep level manager enabled between loading different keyed levels */
private boolean enabled = false; private volatile boolean enabled = false;
@@ -22,34 +45,131 @@ public class KeyedClientLevelManager implements IKeyedClientLevelManager
//=============// //=============//
// constructor // // constructor //
//=============// //=============//
//region
private KeyedClientLevelManager() { } private KeyedClientLevelManager() { }
//endregion
//======================// //======================//
// level override logic // // level override logic //
//======================// //======================//
//region
@Override @Override
@Nullable @Nullable
public IServerKeyedClientLevel getServerKeyedLevel() { return this.serverKeyedLevel; } public IServerKeyedClientLevel getServerKeyedLevel()
{
#if MC_VER > MC_1_12_2
return this.getServerKeyedLevel(Minecraft.getInstance().level);
#else
return this.getServerKeyedLevel(Minecraft.getMinecraft().world);
#endif
}
@Nullable
public IServerKeyedClientLevel getServerKeyedLevel(@Nullable #if MC_VER > MC_1_12_2 ClientLevel #else WorldClient #endif level)
{
if (level == null)
{
return null;
}
// We synchronize on the cache map to ensure atomicity of the lookup-and-populate sequence.
// This prevents multiple threads from creating duplicate wrappers for the same level.
synchronized (this.keyedLevelsCache)
{
// Check the cache first
IServerKeyedClientLevel cached = this.keyedLevelsCache.get(level);
if (cached != null)
{
return cached;
}
// Determine the dimension name for this level
// We use bypassLevelKeyManager=true to avoid recursion back into this manager
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper(level, true);
if (wrappedLevel == null)
{
return null;
}
String dimensionName = wrappedLevel.getDimensionName();
KeyInfo info = this.keysByDimensionName.get(dimensionName);
if (info == null)
{
return null;
}
// Create and cache a new keyed wrapper
IServerKeyedClientLevel keyedLevel = new ServerKeyedClientLevelWrapper(level, info.serverKey, info.levelKey);
this.keyedLevelsCache.put(level, keyedLevel);
return keyedLevel;
}
}
@Override @Override
public IServerKeyedClientLevel setServerKeyedLevel(IClientLevelWrapper clientLevel, String serverKey, String levelKey) public IServerKeyedClientLevel setServerKeyedLevel(IClientLevelWrapper clientLevel, String serverKey, String levelKey)
{ {
IServerKeyedClientLevel keyedLevel = new ServerKeyedClientLevelWrapper((ClientLevel) clientLevel.getWrappedMcObject(), serverKey, levelKey); // 1. Determine the target dimension name
this.serverKeyedLevel = keyedLevel; String targetDimensionName = clientLevel.getDimensionName();
int separatorIndex = levelKey.lastIndexOf("@");
if (separatorIndex != -1)
{
targetDimensionName = levelKey.substring(separatorIndex + 1);
}
final String finalTargetDimensionName = targetDimensionName;
// 2. Store the key for this dimension
this.keysByDimensionName.put(finalTargetDimensionName, new KeyInfo(serverKey, levelKey));
this.enabled = true; this.enabled = true;
return keyedLevel;
// 3. Clear the cache for this dimension to ensure new wrappers are created with the new key
// (though in practice keys shouldn't change mid-session)
//
// We synchronize manually on the map to ensure atomicity of the compound removal operation
// and to prevent race conditions or deadlocks with other threads accessing the map.
// We avoid calling ClientLevelWrapper.getWrapper() inside the lock to prevent circular lock dependencies.
synchronized (this.keyedLevelsCache)
{
this.keyedLevelsCache.keySet().removeIf(level -> {
#if MC_VER <= MC_1_12_2
String levelDim = level.provider.getDimensionType().getName() + ":" + level.provider.getDimension();
#elif MC_VER <= MC_1_21_10
String levelDim = level.dimension().location().toString();
#else
String levelDim = level.dimension().identifier().toString();
#endif
return levelDim.equals(finalTargetDimensionName);
});
}
// 4. Return the keyed wrapper for whatever level the core passed us,
// but only if it matches the dimension we just keyed.
return this.getServerKeyedLevel((#if MC_VER > MC_1_12_2 ClientLevel #else WorldClient #endif) clientLevel.getWrappedMcObject());
} }
@Override @Override
public void clearKeyedLevel() { this.serverKeyedLevel = null; } public void clearKeyedLevel()
{
synchronized (this.keyedLevelsCache)
{
this.keyedLevelsCache.clear();
this.keysByDimensionName.clear();
}
}
@Override @Override
public boolean isEnabled() { return this.enabled; } public boolean isEnabled() { return this.enabled; }
@Override
public void disable() { this.enabled = false; }
@Override
public void disable()
{
this.enabled = false;
this.clearKeyedLevel();
}
} }
@@ -2,7 +2,11 @@ package com.seibel.distanthorizons.common.wrappers.level;
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper; import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel; import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel;
#if MC_VER <= MC_1_12_2
import net.minecraft.client.multiplayer.WorldClient;
#else
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
#endif
public class ServerKeyedClientLevelWrapper extends ClientLevelWrapper implements IServerKeyedClientLevel public class ServerKeyedClientLevelWrapper extends ClientLevelWrapper implements IServerKeyedClientLevel
{ {
@@ -17,21 +21,30 @@ public class ServerKeyedClientLevelWrapper extends ClientLevelWrapper implements
//=============// //=============//
// constructor // // constructor //
//=============// //=============//
//region
#if MC_VER <= MC_1_12_2
public ServerKeyedClientLevelWrapper(WorldClient level, String serverKey, String serverLevelKey)
#else
public ServerKeyedClientLevelWrapper(ClientLevel level, String serverKey, String serverLevelKey) public ServerKeyedClientLevelWrapper(ClientLevel level, String serverKey, String serverLevelKey)
#endif
{ {
super(level); super(level);
this.serverKey = serverKey; this.serverKey = serverKey;
this.serverLevelKey = serverLevelKey; this.serverLevelKey = serverLevelKey;
} }
//endregion
@Override
public String getServerKey() { return this.serverKey; }
//======================// //======================//
// level identification // // level identification //
//======================// //======================//
//region
@Override
public String getServerKey() { return this.serverKey; }
@Override @Override
public String getServerLevelKey() { return this.serverLevelKey; } public String getServerLevelKey() { return this.serverLevelKey; }
@@ -39,6 +52,8 @@ public class ServerKeyedClientLevelWrapper extends ClientLevelWrapper implements
@Override @Override
public String getDhIdentifier() { return this.getServerLevelKey(); } public String getDhIdentifier() { return this.getServerLevelKey(); }
//endregion
} }
@@ -20,13 +20,20 @@
package com.seibel.distanthorizons.common.wrappers.minecraft; package com.seibel.distanthorizons.common.wrappers.minecraft;
import java.io.File; import java.io.File;
import java.util.Arrays;
#if MC_VER > MC_1_12_2
import com.mojang.blaze3d.platform.Window; import com.mojang.blaze3d.platform.Window;
#endif
import com.seibel.distanthorizons.common.wrappers.gui.NativeDialogUtil; import com.seibel.distanthorizons.common.wrappers.gui.NativeDialogUtil;
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper; import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure; import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure;
import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler; import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IImmersivePortalsAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.ModInfo;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
@@ -36,19 +43,35 @@ import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLogger;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ServerData;
#if MC_VER <= MC_1_12_2
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.crash.CrashReport;
import net.minecraft.profiler.Profiler;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.world.DimensionType;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.DimensionManager;
#else
import net.minecraft.CrashReport; import net.minecraft.CrashReport;
import net.minecraft.client.CloudStatus; import net.minecraft.client.CloudStatus;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
#endif
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
#if MC_VER < MC_1_19_2 #if MC_VER < MC_1_19_2 && MC_VER > MC_1_12_2
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
#endif #endif
@@ -57,11 +80,26 @@ import net.minecraft.network.chat.TextComponent;
import net.minecraft.util.profiling.Profiler; import net.minecraft.util.profiling.Profiler;
#endif #endif
#if MC_VER <= MC_1_21_10 #if MC_VER <= MC_1_21_10 && MC_VER > MC_1_12_2
import net.minecraft.client.GraphicsStatus; import net.minecraft.client.GraphicsStatus;
#else #else
#endif #endif
#if MC_VER <= MC_1_12_2
import net.minecraft.util.ResourceLocation;
#elif MC_VER <= MC_1_21_10
import net.minecraft.resources.ResourceLocation;
#else
import net.minecraft.resources.Identifier;
#endif
#if MC_VER > MC_1_19_2
import net.minecraft.core.registries.Registries;
#elif MC_VER > MC_1_12_2
import net.minecraft.core.Registry;
#endif
/** /**
* A singleton that wraps the Minecraft object. * A singleton that wraps the Minecraft object.
* *
@@ -70,13 +108,23 @@ import net.minecraft.client.GraphicsStatus;
public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecraftSharedWrapper public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecraftSharedWrapper
{ {
private static final DhLogger LOGGER = new DhLoggerBuilder().build(); private static final DhLogger LOGGER = new DhLoggerBuilder().build();
#if MC_VER <= MC_1_12_2
private static final Minecraft MINECRAFT = Minecraft.getMinecraft();
#else
private static final Minecraft MINECRAFT = Minecraft.getInstance(); private static final Minecraft MINECRAFT = Minecraft.getInstance();
#endif
public static final MinecraftClientWrapper INSTANCE = new MinecraftClientWrapper(); public static final MinecraftClientWrapper INSTANCE = new MinecraftClientWrapper();
private ProfilerWrapper profilerWrapper; private ProfilerWrapper profilerWrapper;
// Need to classload this field later because otherwise it will be null even when Immersive Portals is present.
public static class Late {
private static final IImmersivePortalsAccessor IMMERSIVE_PORTALS = ModAccessorInjector.INSTANCE.get(IImmersivePortalsAccessor.class);
}
//======================// //======================//
@@ -85,19 +133,36 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
//region //region
@Override @Override
public boolean hasSinglePlayerServer() { return MINECRAFT.hasSingleplayerServer(); } public boolean hasSinglePlayerServer()
@Override {
public boolean clientConnectedToDedicatedServer() #if MC_VER <= MC_1_12_2
{ return MINECRAFT.isSingleplayer();
return MINECRAFT.getCurrentServer() != null #else
&& !this.hasSinglePlayerServer(); return MINECRAFT.hasSingleplayerServer();
#endif
} }
@Override @Override
public boolean connectedToReplay() public boolean clientConnectedToDedicatedServer()
{ {
return MINECRAFT.getCurrentServer() == null return this.hasServerConnection()
&& !this.hasSinglePlayerServer() ; && !this.hasSinglePlayerServer();
} }
@Override
public boolean connectedToReplay()
{
return !this.hasServerConnection()
&& !this.hasSinglePlayerServer() ;
}
private boolean hasServerConnection()
{
#if MC_VER <= MC_1_12_2
return MINECRAFT.getCurrentServerData() != null;
#else
return MINECRAFT.getCurrentServer() != null;
#endif
}
@Override @Override
public String getCurrentServerName() public String getCurrentServerName()
@@ -108,8 +173,13 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
} }
else else
{ {
#if MC_VER <= MC_1_12_2
ServerData server = MINECRAFT.getCurrentServerData();
return (server != null) ? server.serverName : "NULL";
#else
ServerData server = MINECRAFT.getCurrentServer(); ServerData server = MINECRAFT.getCurrentServer();
return (server != null) ? server.name : "NULL"; return (server != null) ? server.name : "NULL";
#endif
} }
} }
@Override @Override
@@ -121,17 +191,46 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
} }
else else
{ {
ServerData server = MINECRAFT.getCurrentServer(); ServerData server = getCurrentServerData();
return (server != null) ? server.ip : "NA"; return getServerIp(server);
} }
} }
@Override @Override
public String getCurrentServerVersion() public String getCurrentServerVersion()
{ {
ServerData server = MINECRAFT.getCurrentServer(); ServerData server = getCurrentServerData();
return (server != null) ? server.version.getString() : "UNKOWN"; return getServerVersion(server);
} }
private ServerData getCurrentServerData()
{
#if MC_VER <= MC_1_12_2
return MINECRAFT.getCurrentServerData();
#else
return MINECRAFT.getCurrentServer();
#endif
}
private String getServerIp(ServerData server)
{
if (server == null) { return "NA"; }
#if MC_VER <= MC_1_12_2
return server.serverIP;
#else
return server.ip;
#endif
}
private String getServerVersion(ServerData server)
{
if (server == null) { return "UNKOWN"; }
#if MC_VER <= MC_1_12_2
return server.gameVersion;
#else
return server.version.getString();
#endif
}
//endregion //endregion
@@ -141,7 +240,11 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
//=================// //=================//
//region //region
#if MC_VER <= MC_1_12_2
public EntityPlayerSP getPlayer() { return MINECRAFT.player; }
#else
public LocalPlayer getPlayer() { return MINECRAFT.player; } public LocalPlayer getPlayer() { return MINECRAFT.player; }
#endif
@Override @Override
public boolean playerExists() { return MINECRAFT.player != null; } public boolean playerExists() { return MINECRAFT.player != null; }
@@ -149,26 +252,52 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
@Override @Override
public DhBlockPos getPlayerBlockPos() public DhBlockPos getPlayerBlockPos()
{ {
#if MC_VER <= MC_1_12_2
EntityPlayerSP player = this.getPlayer();
#else
LocalPlayer player = this.getPlayer(); LocalPlayer player = this.getPlayer();
#endif
if (player == null) if (player == null)
{ {
return new DhBlockPos(0, 0, 0); return new DhBlockPos(0, 0, 0);
} }
if (Late.IMMERSIVE_PORTALS != null)
{
DhBlockPos pos = Late.IMMERSIVE_PORTALS.getOriginalPlayerBlockPos();
if (pos != null) return pos;
}
#if MC_VER <= MC_1_12_2
BlockPos playerPos = player.getPosition();
#else
BlockPos playerPos = player.blockPosition(); BlockPos playerPos = player.blockPosition();
#endif
return new DhBlockPos(playerPos.getX(), playerPos.getY(), playerPos.getZ()); return new DhBlockPos(playerPos.getX(), playerPos.getY(), playerPos.getZ());
} }
@Override @Override
public DhChunkPos getPlayerChunkPos() public DhChunkPos getPlayerChunkPos()
{ {
#if MC_VER <= MC_1_12_2
EntityPlayerSP player = this.getPlayer();
#else
LocalPlayer player = this.getPlayer(); LocalPlayer player = this.getPlayer();
#endif
if (player == null) if (player == null)
{ {
return new DhChunkPos(0, 0); return new DhChunkPos(0, 0);
} }
#if MC_VER < MC_1_17_1 if (Late.IMMERSIVE_PORTALS != null)
{
DhChunkPos pos = Late.IMMERSIVE_PORTALS.getOriginalPlayerChunkPos();
if (pos != null) return pos;
}
#if MC_VER <= MC_1_12_2
ChunkPos playerPos = new ChunkPos(player.getPosition());
#elif MC_VER < MC_1_17_1
ChunkPos playerPos = new ChunkPos(player.blockPosition()); ChunkPos playerPos = new ChunkPos(player.blockPosition());
#else #else
ChunkPos playerPos = player.chunkPosition(); ChunkPos playerPos = player.chunkPosition();
@@ -198,7 +327,16 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
@Nullable @Nullable
public IClientLevelWrapper getWrappedClientLevel(boolean bypassLevelKeyManager) public IClientLevelWrapper getWrappedClientLevel(boolean bypassLevelKeyManager)
{ {
if (!bypassLevelKeyManager && Late.IMMERSIVE_PORTALS != null)
{
IClientLevelWrapper level = Late.IMMERSIVE_PORTALS.getOriginalClientLevelWrapper();
if (level != null) return level;
}
#if MC_VER <= MC_1_12_2
WorldClient level = MINECRAFT.world;
#else
ClientLevel level = MINECRAFT.level; ClientLevel level = MINECRAFT.level;
#endif
if (level == null) if (level == null)
{ {
return null; return null;
@@ -219,13 +357,19 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
@Override @Override
public void sendChatMessage(String string) public void sendChatMessage(String string)
{ {
#if MC_VER <= MC_1_12_2
EntityPlayerSP player = this.getPlayer();
#else
LocalPlayer player = this.getPlayer(); LocalPlayer player = this.getPlayer();
#endif
if (player == null) if (player == null)
{ {
return; return;
} }
#if MC_VER < MC_1_19_2 #if MC_VER <= MC_1_12_2
player.sendMessage(new TextComponentString(string));
#elif MC_VER < MC_1_19_2
player.sendMessage(new TextComponent(string), getPlayer().getUUID()); player.sendMessage(new TextComponent(string), getPlayer().getUUID());
#elif MC_VER < MC_1_21_9 #elif MC_VER < MC_1_21_9
player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/false); player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/false);
@@ -245,13 +389,19 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
@Override @Override
public void sendOverlayMessage(String string) public void sendOverlayMessage(String string)
{ {
#if MC_VER <= MC_1_12_2
EntityPlayerSP player = this.getPlayer();
#else
LocalPlayer player = this.getPlayer(); LocalPlayer player = this.getPlayer();
#endif
if (player == null) if (player == null)
{ {
return; return;
} }
#if MC_VER < MC_1_19_2 #if MC_VER <= MC_1_12_2
MINECRAFT.ingameGUI.setOverlayMessage(string, /*animateColor*/false);
#elif MC_VER < MC_1_19_2
player.displayClientMessage(new TextComponent(string), /*isOverlay*/true); player.displayClientMessage(new TextComponent(string), /*isOverlay*/true);
#elif MC_VER <= MC_1_21_11 #elif MC_VER <= MC_1_21_11
player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/true); player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/true);
@@ -273,7 +423,9 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
{ {
LOGGER.info("Disabling vanilla clouds... This is done to prevent vanilla clouds from rendering on top of Distant Horizons LODs."); LOGGER.info("Disabling vanilla clouds... This is done to prevent vanilla clouds from rendering on top of Distant Horizons LODs.");
#if MC_VER <= MC_1_18_2 #if MC_VER <= MC_1_12_2
MINECRAFT.gameSettings.clouds = 0;
#elif MC_VER <= MC_1_18_2
MINECRAFT.options.renderClouds = CloudStatus.OFF; MINECRAFT.options.renderClouds = CloudStatus.OFF;
#else #else
MINECRAFT.options.cloudStatus().set(CloudStatus.OFF); MINECRAFT.options.cloudStatus().set(CloudStatus.OFF);
@@ -282,11 +434,13 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
public void disableVanillaChunkFadeIn() public void disableVanillaChunkFadeIn()
{ {
LOGGER.info("Disabling vanilla chunk fade in... This is done to prevent vanilla chunks from flashing on the Distant Horizons boarder when moving (which is distracting)."); String message = "Disabling vanilla chunk fade in... This is done to prevent vanilla chunks from flashing on the Distant Horizons boarder when moving (which is distracting).";
#if MC_VER <= MC_1_21_10 #if MC_VER <= MC_1_21_10
// chunk fade in was added MC 1.21.11 // chunk fade in was added MC 1.21.11
#else #else
LOGGER.info(message);
MINECRAFT.options.chunkSectionFadeInTime().set(0.0); MINECRAFT.options.chunkSectionFadeInTime().set(0.0);
#endif #endif
} }
@@ -295,7 +449,9 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
{ {
String reasoning = "This is done to fix vanilla chunks (specifically water blocks) not fading into Distant Horizons LODs when DH's 'Vanilla Fade' option is enabled."; String reasoning = "This is done to fix vanilla chunks (specifically water blocks) not fading into Distant Horizons LODs when DH's 'Vanilla Fade' option is enabled.";
#if MC_VER <= MC_1_18_2 #if MC_VER <= MC_1_12_2
// fabulous graphics was added in MC 1.16
#elif MC_VER <= MC_1_18_2
LOGGER.info("Disabling fabulous graphics... "+reasoning); LOGGER.info("Disabling fabulous graphics... "+reasoning);
GraphicsStatus oldGraphicsStatus = MINECRAFT.options.graphicsMode; GraphicsStatus oldGraphicsStatus = MINECRAFT.options.graphicsMode;
@@ -331,6 +487,7 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
* no override and not included in {@link IMinecraftClientWrapper} * no override and not included in {@link IMinecraftClientWrapper}
* since this would only be used in common/client, not core. * since this would only be used in common/client, not core.
*/ */
#if MC_VER > MC_1_12_2
public public
#if MC_VER < MC_1_21_9 long #if MC_VER < MC_1_21_9 long
#else Window #else Window
@@ -344,12 +501,20 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
return MINECRAFT.getWindow(); return MINECRAFT.getWindow();
#endif #endif
} }
#endif
@Override @Override
public IProfilerWrapper getProfiler() public IProfilerWrapper getProfiler()
{ {
#if MC_VER <= MC_1_12_2
Profiler profiler;
#else
ProfilerFiller profiler; ProfilerFiller profiler;
#if MC_VER < MC_1_21_3 #endif
#if MC_VER <= MC_1_12_2
profiler = MINECRAFT.profiler;
#elif MC_VER < MC_1_21_3
profiler = MINECRAFT.getProfiler(); profiler = MINECRAFT.getProfiler();
#else #else
profiler = Profiler.get(); profiler = Profiler.get();
@@ -378,7 +543,9 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
executeOnRenderThread(() -> executeOnRenderThread(() ->
{ {
CrashReport report = new CrashReport(errorMessage, exception); CrashReport report = new CrashReport(errorMessage, exception);
#if MC_VER < MC_1_20_4 #if MC_VER <= MC_1_12_2
MINECRAFT.crashed(report);
#elif MC_VER < MC_1_20_4
Minecraft.crash(report); Minecraft.crash(report);
#else #else
MINECRAFT.delayCrash(report); MINECRAFT.delayCrash(report);
@@ -387,7 +554,14 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
} }
@Override @Override
public void executeOnRenderThread(Runnable runnable) { MINECRAFT.execute(runnable); } public void executeOnRenderThread(Runnable runnable)
{
#if MC_VER <= MC_1_12_2
MINECRAFT.addScheduledTask(runnable);
#else
MINECRAFT.execute(runnable);
#endif
}
@Override @Override
public void showDialog(String title, String message, String dialogType, String iconType) public void showDialog(String title, String message, String dialogType, String iconType)
@@ -403,7 +577,14 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
//region //region
@Override @Override
public Object getOptionsObject() { return MINECRAFT.options; } public Object getOptionsObject()
{
#if MC_VER <= MC_1_12_2
return MINECRAFT.gameSettings;
#else
return MINECRAFT.options;
#endif
}
//endregion //endregion
@@ -418,22 +599,75 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
public boolean isDedicatedServer() { return false; } public boolean isDedicatedServer() { return false; }
@Override @Override
public File getInstallationDirectory() { return MINECRAFT.gameDirectory; } public File getInstallationDirectory()
{
#if MC_VER <= MC_1_12_2
return MINECRAFT.gameDir;
#else
return MINECRAFT.gameDirectory;
#endif
}
@Override @Override
public int getPlayerCount() public int getPlayerCount()
{ {
// can be null if the server hasn't finished booting up yet // can be null if the server hasn't finished booting up yet
#if MC_VER <= MC_1_12_2
if (MINECRAFT.getIntegratedServer() == null)
#else
if (MINECRAFT.getSingleplayerServer() == null) if (MINECRAFT.getSingleplayerServer() == null)
#endif
{ {
return 1; return 1;
} }
else else
{ {
#if MC_VER <= MC_1_12_2
return MINECRAFT.getIntegratedServer().getCurrentPlayerCount();
#else
return MINECRAFT.getSingleplayerServer().getPlayerCount(); return MINECRAFT.getSingleplayerServer().getPlayerCount();
#endif
} }
} }
@Override
public IServerLevelWrapper getWrappedServerLevel(String levelKey)
{
if (!hasSinglePlayerServer()) return null;
#if MC_VER <= MC_1_12_2
int dimensionID;
try
{
dimensionID = Integer.parseInt(levelKey.substring(levelKey.indexOf(":")+1));
}
catch (NumberFormatException ignored)
{
return null;
}
#else
#if MC_VER <= MC_1_21_10
ResourceLocation levelID = ResourceLocation.tryParse(levelKey);
#else
Identifier levelID = Identifier.tryParse(levelKey);
#endif
if (levelID == null) return null;
#if MC_VER > MC_1_19_2
ResourceKey<Level> resourceKey = ResourceKey.create(Registries.DIMENSION, levelID);
#else
ResourceKey<Level> resourceKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, levelID);
#endif
#endif
#if MC_VER <= MC_1_12_2
WorldServer level = MINECRAFT.getIntegratedServer().getWorld(dimensionID);
#else
ServerLevel level = MINECRAFT.getSingleplayerServer().getLevel(resourceKey);
#endif
return ServerLevelWrapper.getWrapper(level);
}
//endregion //endregion
@@ -19,7 +19,9 @@
package com.seibel.distanthorizons.common.wrappers.minecraft; package com.seibel.distanthorizons.common.wrappers.minecraft;
#if MC_VER < MC_1_21_5 #if MC_VER <= MC_1_12_2
import net.minecraft.client.renderer.GlStateManager;
#elif MC_VER < MC_1_21_5
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager;
#else #else
import com.mojang.blaze3d.opengl.GlStateManager; import com.mojang.blaze3d.opengl.GlStateManager;
@@ -36,7 +38,7 @@ import org.lwjgl.opengl.GL32;
* <b>Why does DH often call GL methods twice? </b><br> * <b>Why does DH often call GL methods twice? </b><br>
* Once using the base {@link GL32} function and a second time using * Once using the base {@link GL32} function and a second time using
* Minecraft's {@link GlStateManager}?<br><br> * Minecraft's {@link GlStateManager}?<br><br>
* *
* <b>Answer: </b><br> * <b>Answer: </b><br>
* Compatibility and robustness<br> * Compatibility and robustness<br>
* In general all MC rendering should go through MC's {@link GlStateManager}, * In general all MC rendering should go through MC's {@link GlStateManager},
@@ -66,16 +68,20 @@ public class MinecraftGLWrapper
// scissor // // scissor //
/** @see GL32#GL_SCISSOR_TEST */ /** @see GL32#GL_SCISSOR_TEST */
public void enableScissorTest() public void enableScissorTest()
{ {
GL32.glEnable(GL32.GL_SCISSOR_TEST); GL32.glEnable(GL32.GL_SCISSOR_TEST);
#if MC_VER > MC_1_12_2
GlStateManager._enableScissorTest(); GlStateManager._enableScissorTest();
#endif
} }
/** @see GL32#GL_SCISSOR_TEST */ /** @see GL32#GL_SCISSOR_TEST */
public void disableScissorTest() public void disableScissorTest()
{ {
GL32.glDisable(GL32.GL_SCISSOR_TEST); GL32.glDisable(GL32.GL_SCISSOR_TEST);
GlStateManager._disableScissorTest(); #if MC_VER > MC_1_12_2
GlStateManager._disableScissorTest();
#endif
} }
@@ -90,78 +96,113 @@ public class MinecraftGLWrapper
// depth // // depth //
/** @see GL32#GL_DEPTH_TEST */ /** @see GL32#GL_DEPTH_TEST */
public void enableDepthTest() public void enableDepthTest()
{ {
GL32.glEnable(GL32.GL_DEPTH_TEST); GL32.glEnable(GL32.GL_DEPTH_TEST);
#if MC_VER <= MC_1_12_2
GlStateManager.enableDepth();
#else
GlStateManager._enableDepthTest(); GlStateManager._enableDepthTest();
#endif
} }
/** @see GL32#GL_DEPTH_TEST */ /** @see GL32#GL_DEPTH_TEST */
public void disableDepthTest() public void disableDepthTest()
{ {
GL32.glDisable(GL32.GL_DEPTH_TEST); GL32.glDisable(GL32.GL_DEPTH_TEST);
#if MC_VER <= MC_1_12_2
GlStateManager.disableDepth();
#else
GlStateManager._disableDepthTest(); GlStateManager._disableDepthTest();
#endif
} }
/** @see GL32#glDepthFunc(int) */ /** @see GL32#glDepthFunc(int) */
public void glDepthFunc(int func) public void glDepthFunc(int func)
{ {
GL32.glDepthFunc(func); GL32.glDepthFunc(func);
#if MC_VER <= MC_1_12_2
GlStateManager.depthFunc(func);
#else
GlStateManager._depthFunc(func); GlStateManager._depthFunc(func);
#endif
} }
/** @see GL32#glDepthMask(boolean) */ /** @see GL32#glDepthMask(boolean) */
public void enableDepthMask() public void enableDepthMask()
{ {
GL32.glDepthMask(true); GL32.glDepthMask(true);
GlStateManager._depthMask(true); #if MC_VER <= MC_1_12_2
GlStateManager.depthMask(true);
#else
GlStateManager._depthMask(true);
#endif
} }
/** @see GL32#glDepthMask(boolean) */ /** @see GL32#glDepthMask(boolean) */
public void disableDepthMask() public void disableDepthMask()
{ {
GL32.glDepthMask(false); GL32.glDepthMask(false);
#if MC_VER <= MC_1_12_2
GlStateManager.depthMask(false);
#else
GlStateManager._depthMask(false); GlStateManager._depthMask(false);
#endif
} }
// blending // // blending //
/** @see GL32#GL_BLEND */ /** @see GL32#GL_BLEND */
public void enableBlend() public void enableBlend()
{ {
GL32.glEnable(GL32.GL_BLEND); GL32.glEnable(GL32.GL_BLEND);
#if MC_VER <= MC_1_12_2
GlStateManager.enableBlend();
#else
GlStateManager._enableBlend(); GlStateManager._enableBlend();
#endif
} }
/** @see GL32#GL_BLEND */ /** @see GL32#GL_BLEND */
public void disableBlend() public void disableBlend()
{ {
GL32.glDisable(GL32.GL_BLEND); GL32.glDisable(GL32.GL_BLEND);
#if MC_VER <= MC_1_12_2
GlStateManager.disableBlend();
#else
GlStateManager._disableBlend(); GlStateManager._disableBlend();
#endif
} }
/** @see GL32#glBlendFunc */ /** @see GL32#glBlendFunc */
public void glBlendFunc(int sfactor, int dfactor) public void glBlendFunc(int sfactor, int dfactor)
{ {
GL32.glBlendFunc(sfactor, dfactor); GL32.glBlendFunc(sfactor, dfactor);
#if MC_VER <= MC_1_12_2
#if MC_VER < MC_1_21_5 GlStateManager.blendFunc(sfactor, dfactor);
#elif MC_VER < MC_1_21_5
GlStateManager._blendFunc(sfactor, dfactor); GlStateManager._blendFunc(sfactor, dfactor);
#endif #endif
} }
/** @see GL32#glBlendFuncSeparate */ /** @see GL32#glBlendFuncSeparate */
public void glBlendFuncSeparate(int sfactorRGB, int dfactorRGB, int sfactorAlpha, int dfactorAlpha) public void glBlendFuncSeparate(int sfactorRGB, int dfactorRGB, int sfactorAlpha, int dfactorAlpha)
{ {
GL32.glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); GL32.glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
GlStateManager._blendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); #if MC_VER <= MC_1_12_2
GlStateManager.tryBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
#else
GlStateManager._blendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
#endif
} }
// frame buffers // // frame buffers //
/** @see GL32#glBindFramebuffer */ /** @see GL32#glBindFramebuffer */
public void glBindFramebuffer(int target, int framebuffer) public void glBindFramebuffer(int target, int framebuffer)
{ {
GL32.glBindFramebuffer(target, framebuffer); GL32.glBindFramebuffer(target, framebuffer);
GlStateManager._glBindFramebuffer(target, framebuffer); #if MC_VER > MC_1_12_2
GlStateManager._glBindFramebuffer(target, framebuffer);
#endif
} }
@@ -187,31 +228,57 @@ public class MinecraftGLWrapper
// culling // // culling //
/** @see GL32#GL_CULL_FACE */ /** @see GL32#GL_CULL_FACE */
public void enableFaceCulling() public void enableFaceCulling()
{ {
GL32.glEnable(GL32.GL_CULL_FACE); GL32.glEnable(GL32.GL_CULL_FACE);
GlStateManager._enableCull(); #if MC_VER <= MC_1_12_2
GlStateManager.enableCull();
#else
GlStateManager._enableCull();
#endif
} }
/** @see GL32#GL_CULL_FACE */ /** @see GL32#GL_CULL_FACE */
public void disableFaceCulling() public void disableFaceCulling()
{ {
GL32.glDisable(GL32.GL_CULL_FACE); GL32.glDisable(GL32.GL_CULL_FACE);
GlStateManager._disableCull(); #if MC_VER <= MC_1_12_2
GlStateManager.disableCull();
#else
GlStateManager._disableCull();
#endif
} }
// textures // // textures //
/** @see GL32#glGenTextures() */ /** @see GL32#glGenTextures() */
public int glGenTextures() { return GlStateManager._genTexture(); } public int glGenTextures()
{
#if MC_VER <= MC_1_12_2
return GlStateManager.generateTexture();
#else
return GlStateManager._genTexture();
#endif
}
/** @see GL32#glDeleteTextures(int) */ /** @see GL32#glDeleteTextures(int) */
public void glDeleteTextures(int texture) { GlStateManager._deleteTexture(texture); } public void glDeleteTextures(int texture)
{
#if MC_VER <= MC_1_12_2
GlStateManager.deleteTexture(texture);
#else
GlStateManager._deleteTexture(texture);
#endif
}
/** @see GL32#glActiveTexture(int) */ /** @see GL32#glActiveTexture(int) */
public void glActiveTexture(int textureId) public void glActiveTexture(int textureId)
{ {
GL32.glActiveTexture(textureId); GL32.glActiveTexture(textureId);
#if MC_VER <= MC_1_12_2
GlStateManager.setActiveTexture(textureId);
#else
GlStateManager._activeTexture(textureId); GlStateManager._activeTexture(textureId);
#endif
} }
public int getActiveTexture() { return GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D); } public int getActiveTexture() { return GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D); }
@@ -219,10 +286,14 @@ public class MinecraftGLWrapper
* Always binds to {@link GL32#GL_TEXTURE_2D} * Always binds to {@link GL32#GL_TEXTURE_2D}
* @see GL32#glBindTexture(int, int) * @see GL32#glBindTexture(int, int)
*/ */
public void glBindTexture(int texture) public void glBindTexture(int texture)
{ {
GL32.glBindTexture(GL32.GL_TEXTURE_2D, texture); GL32.glBindTexture(GL32.GL_TEXTURE_2D, texture);
#if MC_VER <= MC_1_12_2
GlStateManager.bindTexture(texture);
#else
GlStateManager._bindTexture(texture); GlStateManager._bindTexture(texture);
#endif
} }
@@ -20,27 +20,34 @@
package com.seibel.distanthorizons.common.wrappers.minecraft; package com.seibel.distanthorizons.common.wrappers.minecraft;
import java.awt.Color; import java.awt.Color;
import java.lang.invoke.MethodHandles;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
#if MC_VER > MC_1_12_2
import com.mojang.blaze3d.pipeline.RenderTarget; import com.mojang.blaze3d.pipeline.RenderTarget;
import com.mojang.blaze3d.platform.NativeImage; import com.mojang.blaze3d.platform.NativeImage;
#endif
import com.seibel.distanthorizons.api.enums.config.EDhApiLodShading; import com.seibel.distanthorizons.api.enums.config.EDhApiLodShading;
import com.seibel.distanthorizons.common.wrappers.McObjectConverter; import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
import com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper; import com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper;
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector; import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.enums.EDhDirection;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.coreapi.util.ColorUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
#if MC_VER < MC_1_17_1 #if MC_VER < MC_1_17_1
#elif MC_VER < MC_1_21_6 #elif MC_VER < MC_1_21_3
import net.minecraft.client.renderer.FogRenderer; import net.minecraft.client.renderer.FogRenderer;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
#elif MC_VER < MC_1_21_6
import com.seibel.distanthorizons.coreapi.util.ColorUtil;
import net.minecraft.client.renderer.FogRenderer;
#else #else
import com.seibel.distanthorizons.coreapi.util.ColorUtil;
import net.minecraft.client.renderer.fog.FogData; import net.minecraft.client.renderer.fog.FogData;
import net.minecraft.client.renderer.fog.FogRenderer; import net.minecraft.client.renderer.fog.FogRenderer;
#endif #endif
@@ -51,27 +58,38 @@ import org.joml.Vector3f;
#else #else
#endif #endif
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOptifineAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import com.seibel.distanthorizons.core.util.math.Vec3d; import com.seibel.distanthorizons.core.util.math.Vec3d;
import com.seibel.distanthorizons.core.util.math.Vec3f; import com.seibel.distanthorizons.core.util.math.Vec3f;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IImmersivePortalsAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
#if MC_VER <= MC_1_12_2
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.fluids.IFluidBlock;
import net.minecraft.init.MobEffects;
import net.minecraft.client.renderer.entity.RenderManager;
#else
import net.minecraft.client.Camera; import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.world.effect.MobEffects; import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
#endif
import net.minecraft.client.Minecraft;
import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLogger;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joml.Vector4f; import org.joml.Vector4f;
#if MC_VER < MC_1_17_1 #if MC_VER <= MC_1_12_2
import org.lwjgl.opengl.GL15;
#elif MC_VER < MC_1_17_1
import net.minecraft.tags.FluidTags; import net.minecraft.tags.FluidTags;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.FluidState;
@@ -100,9 +118,20 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
public static final MinecraftRenderWrapper INSTANCE = new MinecraftRenderWrapper(); public static final MinecraftRenderWrapper INSTANCE = new MinecraftRenderWrapper();
private static final IOptifineAccessor OPTIFINE_ACCESSOR = ModAccessorInjector.INSTANCE.get(IOptifineAccessor.class); private static final IOptifineAccessor OPTIFINE_ACCESSOR = ModAccessorInjector.INSTANCE.get(IOptifineAccessor.class);
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private static final DhLogger LOGGER = new DhLoggerBuilder().build(); private static final DhLogger LOGGER = new DhLoggerBuilder().build();
#if MC_VER <= MC_1_12_2
private static final Minecraft MC = Minecraft.getMinecraft();
#else
private static final Minecraft MC = Minecraft.getInstance(); private static final Minecraft MC = Minecraft.getInstance();
#endif
// Need to classload this field later because otherwise it will be null even when Immersive Portals is present.
public static class Late {
private static final IImmersivePortalsAccessor IMMERSIVE_PORTALS = ModAccessorInjector.INSTANCE.get(IImmersivePortalsAccessor.class);
}
/** /**
* In the case of immersive portals multiple levels may be active at once, causing conflicting lightmaps. <br> * In the case of immersive portals multiple levels may be active at once, causing conflicting lightmaps. <br>
@@ -133,7 +162,10 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
@Override @Override
public Vec3f getLookAtVector() public Vec3f getLookAtVector()
{ {
#if MC_VER <= MC_1_21_10 #if MC_VER <= MC_1_12_2
net.minecraft.util.math.Vec3d lookVector = (MC.getRenderViewEntity().getLook(MC.getRenderPartialTicks()));
return new Vec3f((float) lookVector.x, (float) lookVector.y, (float) lookVector.z);
#elif MC_VER <= MC_1_21_10
Camera camera = MC.gameRenderer.getMainCamera(); Camera camera = MC.gameRenderer.getMainCamera();
return new Vec3f(camera.getLookVector().x(), camera.getLookVector().y(), camera.getLookVector().z()); return new Vec3f(camera.getLookVector().x(), camera.getLookVector().y(), camera.getLookVector().z());
#else #else
@@ -153,37 +185,57 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
{ {
return false; return false;
} }
else if (MC.player.getActiveEffectsMap() == null)
#if MC_VER <= MC_1_12_2
if (MC.player.getActivePotionMap() == null)
{ {
return false; return false;
} }
else
return MC.player.getActivePotionEffect(MobEffects.BLINDNESS) != null;
#else
if (MC.player.getActiveEffectsMap() == null)
{ {
return MC.player.getActiveEffectsMap().get(MobEffects.BLINDNESS) != null return false;
#if MC_VER >= MC_1_19_2
|| MC.player.getActiveEffectsMap().get(MobEffects.DARKNESS) != null // Deep dark effect
#endif
;
} }
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
#endif
;
#endif
} }
@Override @Override
public Vec3d getCameraExactPosition() public Vec3d getCameraExactPosition()
{ {
if (Late.IMMERSIVE_PORTALS != null)
{
Vec3d cameraPos = Late.IMMERSIVE_PORTALS.getOriginalCameraPos();
if (cameraPos != null) return cameraPos;
}
#if MC_VER <= MC_1_12_2
RenderManager rm = MC.getRenderManager();
return new Vec3d(rm.viewerPosX, rm.viewerPosY, rm.viewerPosZ);
#else
Camera camera = MC.gameRenderer.getMainCamera(); Camera camera = MC.gameRenderer.getMainCamera();
#if MC_VER <= MC_1_21_10 #if MC_VER <= MC_1_21_10
Vec3 projectedView = camera.getPosition(); Vec3 projectedView = camera.getPosition();
#else #else
Vec3 projectedView = camera.position(); Vec3 projectedView = camera.position();
#endif #endif
return new Vec3d(projectedView.x, projectedView.y, projectedView.z); return new Vec3d(projectedView.x, projectedView.y, projectedView.z);
#endif
} }
@Override @Override
public float getPartialTickTime() public float getPartialTickTime()
{ {
#if MC_VER < MC_1_21_1 #if MC_VER <= MC_1_12_2
return MC.getRenderPartialTicks();
#elif MC_VER < MC_1_21_1
return MC.getFrameTime(); return MC.getFrameTime();
#elif MC_VER < MC_1_21_3 #elif MC_VER < MC_1_21_3
return MC.getTimer().getRealtimeDeltaTicks(); return MC.getTimer().getRealtimeDeltaTicks();
@@ -296,9 +348,17 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
@Override @Override
public Color getSkyColor() public Color getSkyColor()
{ {
#if MC_VER <= MC_1_12_2
if (MC.world.provider.hasSkyLight())
#else
if (MC.level.dimensionType().hasSkyLight()) if (MC.level.dimensionType().hasSkyLight())
#endif
{ {
#if MC_VER < MC_1_17_1 #if MC_VER <= MC_1_12_2
float frameTime = this.getPartialTickTime();
net.minecraft.util.math.Vec3d colorValues = MC.world.getSkyColor(MC.getRenderViewEntity(), frameTime);
return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z);
#elif MC_VER < MC_1_17_1
float frameTime = this.getPartialTickTime(); float frameTime = this.getPartialTickTime();
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getBlockPosition(), frameTime); Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getBlockPosition(), frameTime);
return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z); return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z);
@@ -325,7 +385,9 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
@Override @Override
public int getRenderDistance() public int getRenderDistance()
{ {
#if MC_VER <= MC_1_17_1 #if MC_VER <= MC_1_12_2
return MC.gameSettings.renderDistanceChunks;
#elif MC_VER <= MC_1_17_1
return MC.options.renderDistance; return MC.options.renderDistance;
#else #else
return MC.options.getEffectiveRenderDistance(); return MC.options.getEffectiveRenderDistance();
@@ -335,14 +397,18 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
@Override @Override
public int getFrameLimit() public int getFrameLimit()
{ {
#if MC_VER <= MC_1_18_2 #if MC_VER <= MC_1_12_2
return MC.gameSettings.limitFramerate;
#elif MC_VER <= MC_1_18_2
return MC.options.framerateLimit; return MC.options.framerateLimit;
#else #else
return MC.options.framerateLimit().get(); return MC.options.framerateLimit().get();
#endif #endif
} }
#if MC_VER > MC_1_12_2
protected RenderTarget getRenderTarget() { return MC.getMainRenderTarget(); } protected RenderTarget getRenderTarget() { return MC.getMainRenderTarget(); }
#endif
@Override @Override
public boolean mcRendersToFrameBuffer() public boolean mcRendersToFrameBuffer()
@@ -373,7 +439,9 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
return this.finalLevelFrameBufferId; return this.finalLevelFrameBufferId;
} }
#if MC_VER < MC_1_21_5 #if MC_VER <= MC_1_12_2
return MC.getFramebuffer().framebufferObject;
#elif MC_VER < MC_1_21_5
return this.getRenderTarget().frameBufferId; return this.getRenderTarget().frameBufferId;
#else #else
// MC renders to a texture and then directly to the default FBO now // MC renders to a texture and then directly to the default FBO now
@@ -388,7 +456,10 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
@Override @Override
public int getDepthTextureId() public int getDepthTextureId()
{ {
#if MC_VER < MC_1_21_5 #if MC_VER <= MC_1_12_2
//1.12.2 is using renderbuffer instead of framebuffer for depth texture
return -1;
#elif MC_VER < MC_1_21_5
return this.getRenderTarget().getDepthTextureId(); return this.getRenderTarget().getDepthTextureId();
#else #else
try try
@@ -418,7 +489,9 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
@Override @Override
public int getColorTextureId() public int getColorTextureId()
{ {
#if MC_VER < MC_1_21_5 #if MC_VER <= MC_1_12_2
return MC.getFramebuffer().framebufferTexture;
#elif MC_VER < MC_1_21_5
return this.getRenderTarget().getColorTextureId(); return this.getRenderTarget().getColorTextureId();
#else #else
try try
@@ -448,7 +521,9 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
@Override @Override
public int getTargetFramebufferViewportWidth() public int getTargetFramebufferViewportWidth()
{ {
#if MC_VER < MC_1_21_9 #if MC_VER <= MC_1_12_2
return MC.getFramebuffer().framebufferWidth;
#elif MC_VER < MC_1_21_9
return this.getRenderTarget().viewWidth; return this.getRenderTarget().viewWidth;
#else #else
return this.getRenderTarget().width; return this.getRenderTarget().width;
@@ -458,20 +533,23 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
@Override @Override
public int getTargetFramebufferViewportHeight() public int getTargetFramebufferViewportHeight()
{ {
#if MC_VER < MC_1_21_9 #if MC_VER <= MC_1_12_2
return MC.getFramebuffer().framebufferHeight;
#elif MC_VER < MC_1_21_9
return this.getRenderTarget().viewHeight; return this.getRenderTarget().viewHeight;
#else #else
return this.getRenderTarget().height; return this.getRenderTarget().height;
#endif #endif
} }
@Override
public ILightMapWrapper getLightmapWrapper(@NotNull ILevelWrapper level) { return this.lightmapByDimensionType.get(level.getDimensionType()); }
@Override @Override
public boolean isFogStateSpecial() public boolean isFogStateSpecial()
{ {
#if MC_VER < MC_1_17_1 #if MC_VER <= MC_1_12_2
BlockPos blockPos = new BlockPos(MC.getRenderViewEntity().getPositionEyes(MC.getRenderPartialTicks()));
IBlockState fluidState = MC.getRenderViewEntity().world.getBlockState(blockPos);
return this.playerHasBlindingEffect() || fluidState.getMaterial().isLiquid() || fluidState.getBlock() instanceof IFluidBlock;
#elif MC_VER < MC_1_17_1
Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera(); Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera();
FluidState fluidState = camera.getFluidInCamera(); FluidState fluidState = camera.getFluidInCamera();
Entity entity = camera.getEntity(); Entity entity = camera.getEntity();
@@ -485,88 +563,89 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
#endif #endif
} }
//==========//
// lightmap //
//==========//
//region
@Override
public ILightMapWrapper getLightmapWrapper(@NotNull ILevelWrapper level) { return this.lightmapByDimensionType.get(level.getDimensionType()); }
/** /**
* It's better to use {@link MinecraftRenderWrapper#setLightmapId(int, IClientLevelWrapper)} if possible, * It's better to use {@link MinecraftRenderWrapper#setLightmapId(int)} if possible,
* however old MC versions don't support it. * however old MC versions don't support it.
*/ */
public void updateLightmap(NativeImage lightPixels, IClientLevelWrapper level) #if MC_VER > MC_1_12_2
public void updateLightmap(NativeImage lightPixels)
{ {
IClientLevelWrapper clientLevel = getLightmapClientLevelWrapper();
if (clientLevel == null)
{
return;
}
// Using ClientLevelWrapper as the key would be better, but we don't have a consistent way to create the same // Using ClientLevelWrapper as the key would be better, but we don't have a consistent way to create the same
// object for the same MC level and/or the same hash, // object for the same MC level and/or the same hash,
// so this will have to do for now // so this will have to do for now
IDimensionTypeWrapper dimensionType = level.getDimensionType(); IDimensionTypeWrapper dimensionType = clientLevel.getDimensionType();
LightMapWrapper wrapper = this.lightmapByDimensionType.computeIfAbsent(dimensionType, (dimType) -> new LightMapWrapper()); LightMapWrapper wrapper = this.lightmapByDimensionType.computeIfAbsent(dimensionType, (dimType) -> new LightMapWrapper());
wrapper.uploadLightmap(lightPixels); wrapper.uploadLightmap(lightPixels);
} }
public void setLightmapId(int tetxureId, IClientLevelWrapper level) #endif
public void setLightmapId(int textureId)
{ {
IClientLevelWrapper clientLevel = getLightmapClientLevelWrapper();
if (clientLevel == null)
{
return;
}
// Using ClientLevelWrapper as the key would be better, but we don't have a consistent way to create the same // Using ClientLevelWrapper as the key would be better, but we don't have a consistent way to create the same
// object for the same MC level and/or the same hash, // object for the same MC level and/or the same hash,
// so this will have to do for now // so this will have to do for now
IDimensionTypeWrapper dimensionType = level.getDimensionType(); IDimensionTypeWrapper dimensionType = clientLevel.getDimensionType();
LightMapWrapper wrapper = this.lightmapByDimensionType.computeIfAbsent(dimensionType, (dimType) -> new LightMapWrapper()); LightMapWrapper wrapper = this.lightmapByDimensionType.computeIfAbsent(dimensionType, (dimType) -> new LightMapWrapper());
wrapper.setLightmapId(tetxureId); wrapper.setLightmapId(textureId);
} }
#if MC_VER <= MC_1_21_10 #if MC_VER <= MC_1_21_10
#else #else
public void setLightmapGpuTexture(GpuTexture gpuTexture, IClientLevelWrapper level) public void setLightmapGpuTexture(GpuTexture gpuTexture)
{ {
IClientLevelWrapper clientLevel = getLightmapClientLevelWrapper();
if (clientLevel == null)
{
return;
}
// Using ClientLevelWrapper as the key would be better, but we don't have a consistent way to create the same // Using ClientLevelWrapper as the key would be better, but we don't have a consistent way to create the same
// object for the same MC level and/or the same hash, // object for the same MC level and/or the same hash,
// so this will have to do for now // so this will have to do for now
IDimensionTypeWrapper dimensionType = level.getDimensionType(); IDimensionTypeWrapper dimensionType = clientLevel.getDimensionType();
LightMapWrapper wrapper = this.lightmapByDimensionType.computeIfAbsent(dimensionType, (dimType) -> new LightMapWrapper()); LightMapWrapper wrapper = this.lightmapByDimensionType.computeIfAbsent(dimensionType, (dimType) -> new LightMapWrapper());
wrapper.setLightmapGpuTexture(gpuTexture); wrapper.setLightmapGpuTexture(gpuTexture);
} }
#endif #endif
@Override private static @Nullable IClientLevelWrapper getLightmapClientLevelWrapper()
public float getShade(EDhDirection lodDirection)
{ {
EDhApiLodShading lodShading = Config.Client.Advanced.Graphics.Quality.lodShading.get(); IClientLevelWrapper clientLevel = ClientApi.RENDER_STATE.clientLevelWrapper;
switch (lodShading) if (clientLevel == null)
{ {
default: clientLevel = MC_CLIENT.getWrappedClientLevel();
case AUTO:
if (MC.level != null)
{
Direction mcDir = McObjectConverter.Convert(lodDirection);
#if MC_VER <= MC_1_21_11
return MC.level.getShade(mcDir, true);
#else
return MC.level.cardinalLighting().byFace(mcDir);
#endif
}
else
{
return 0.0f;
}
case ENABLED:
switch (lodDirection)
{
case DOWN:
return 0.5F;
default:
case UP:
return 1.0F;
case NORTH:
case SOUTH:
return 0.8F;
case WEST:
case EAST:
return 0.6F;
}
case DISABLED:
return 1.0F;
} }
return clientLevel;
} }
//endregion
} }
@@ -1,9 +1,32 @@
package com.seibel.distanthorizons.common.wrappers.minecraft; package com.seibel.distanthorizons.common.wrappers.minecraft;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.dedicated.DedicatedServer;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
#if MC_VER > MC_1_12_2
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
#else
import net.minecraft.world.WorldServer;
#endif
#if MC_VER <= MC_1_12_2
#elif MC_VER <= MC_1_21_10
import net.minecraft.resources.ResourceLocation;
#else
import net.minecraft.resources.Identifier;
#endif
#if MC_VER > MC_1_19_2
import net.minecraft.core.registries.Registries;
#elif MC_VER > MC_1_12_2
import net.minecraft.core.Registry;
#endif
import java.io.File; import java.io.File;
public class MinecraftServerWrapper implements IMinecraftSharedWrapper public class MinecraftServerWrapper implements IMinecraftSharedWrapper
@@ -39,7 +62,9 @@ public class MinecraftServerWrapper implements IMinecraftSharedWrapper
throw new IllegalStateException("Trying to get Installation Direction before dedicated server completed initialization!"); throw new IllegalStateException("Trying to get Installation Direction before dedicated server completed initialization!");
} }
#if MC_VER < MC_1_21_1 #if MC_VER <= MC_1_12_2
return this.dedicatedServer.getDataDirectory();
#elif MC_VER < MC_1_21_1
return this.dedicatedServer.getServerDirectory(); return this.dedicatedServer.getServerDirectory();
#else #else
return this.dedicatedServer.getServerDirectory().toFile(); return this.dedicatedServer.getServerDirectory().toFile();
@@ -54,9 +79,49 @@ public class MinecraftServerWrapper implements IMinecraftSharedWrapper
throw new IllegalStateException("Trying to get player count before dedicated server completed initialization!"); throw new IllegalStateException("Trying to get player count before dedicated server completed initialization!");
} }
return this.dedicatedServer.getPlayerCount(); #if MC_VER <= MC_1_12_2
return this.dedicatedServer.getCurrentPlayerCount();
#else
return this.dedicatedServer.getPlayerCount();
#endif
} }
@Override
public IServerLevelWrapper getWrappedServerLevel(String levelKey)
{
#if MC_VER <= MC_1_12_2
int dimensionID;
try
{
dimensionID = Integer.parseInt(levelKey.substring(levelKey.indexOf(":")+1));
}
catch (NumberFormatException ignored)
{
return null;
}
#else
#if MC_VER <= MC_1_21_10
ResourceLocation levelID = ResourceLocation.tryParse(levelKey);
#else
Identifier levelID = Identifier.tryParse(levelKey);
#endif
if (levelID == null) return null;
#if MC_VER > MC_1_19_2
ResourceKey<Level> resourceKey = ResourceKey.create(Registries.DIMENSION, levelID);
#else
ResourceKey<Level> resourceKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, levelID);
#endif
#endif
#if MC_VER > MC_1_12_2
ServerLevel level = dedicatedServer.getLevel(resourceKey);
#else
WorldServer level = dedicatedServer.getWorld(dimensionID);
#endif
return ServerLevelWrapper.getWrapper(level);
}
} }
@@ -21,25 +21,50 @@ package com.seibel.distanthorizons.common.wrappers.minecraft;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
#if MC_VER <= MC_1_12_2
import net.minecraft.profiler.Profiler;
#else
import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.util.profiling.ProfilerFiller;
#endif
public class ProfilerWrapper implements IProfilerWrapper public class ProfilerWrapper implements IProfilerWrapper
{ {
#if MC_VER <= MC_1_12_2
public Profiler profiler;
#else
public ProfilerFiller profiler; public ProfilerFiller profiler;
#endif
#if MC_VER <= MC_1_12_2
public ProfilerWrapper(Profiler newProfiler)
#else
public ProfilerWrapper(ProfilerFiller newProfiler)
#endif
{ this.profiler = newProfiler; }
public ProfilerWrapper(ProfilerFiller newProfiler) { this.profiler = newProfiler; }
@Override @Override
public IProfileBlock push(String newSection) public IProfileBlock push(String newSection)
{ {
this.profiler.push(newSection); #if MC_VER <= MC_1_12_2
this.profiler.startSection(newSection);
#else
this.profiler.push(newSection);
#endif
return new ProfileBlock(this.profiler); return new ProfileBlock(this.profiler);
} }
@Override @Override
public void popPush(String newSection) public void popPush(String newSection)
{ {
this.profiler.popPush(newSection); #if MC_VER <= MC_1_12_2
this.profiler.endStartSection(newSection);
#else
this.profiler.popPush(newSection) ;
#endif
} }
@@ -51,14 +76,27 @@ public class ProfilerWrapper implements IProfilerWrapper
public static class ProfileBlock implements IProfileBlock public static class ProfileBlock implements IProfileBlock
{ {
private final ProfilerFiller profiler; #if MC_VER <= MC_1_12_2
public ProfileBlock(ProfilerFiller newProfiler) { this.profiler = newProfiler; } public Profiler profiler;
#else
public ProfilerFiller profiler;
#endif
#if MC_VER <= MC_1_12_2
public ProfileBlock(Profiler newProfiler)
#else
public ProfileBlock(ProfilerFiller newProfiler)
#endif
{ this.profiler = newProfiler; }
@Override @Override
public void close() public void close()
{ {
#if MC_VER <= MC_1_12_2
this.profiler.endSection();
#else
this.profiler.pop(); this.profiler.pop();
#endif
} }
} }
@@ -1,12 +1,21 @@
package com.seibel.distanthorizons.common.wrappers.misc; package com.seibel.distanthorizons.common.wrappers.misc;
#if MC_VER <= MC_1_12_2
import net.minecraft.world.WorldServer;
#else
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
#endif
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public interface IMixinServerPlayer public interface IMixinServerPlayer
{ {
@Nullable @Nullable
#if MC_VER <= MC_1_12_2
WorldServer distantHorizons$getDimensionChangeDestination();
#else
ServerLevel distantHorizons$getDimensionChangeDestination(); ServerLevel distantHorizons$getDimensionChangeDestination();
#endif
#if MC_VER == MC_1_16_5 #if MC_VER == MC_1_16_5
void distantHorizons$setDimensionChangeDestination(ServerLevel dimensionChangeDestination); void distantHorizons$setDimensionChangeDestination(ServerLevel dimensionChangeDestination);
@@ -19,9 +19,13 @@
package com.seibel.distanthorizons.common.wrappers.misc; package com.seibel.distanthorizons.common.wrappers.misc;
#if MC_VER > MC_1_12_2
import com.mojang.blaze3d.platform.NativeImage; import com.mojang.blaze3d.platform.NativeImage;
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureViewWrapper; import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureViewWrapper;
#endif
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureViewWrapper;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper; import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLogger;
@@ -58,7 +62,6 @@ public class LightMapWrapper implements ILightMapWrapper
private final BlazeTextureViewWrapper lightmapTextureWrapper = new BlazeTextureViewWrapper(); private final BlazeTextureViewWrapper lightmapTextureWrapper = new BlazeTextureViewWrapper();
//==============// //==============//
// constructors // // constructors //
//==============// //==============//
@@ -75,6 +78,7 @@ public class LightMapWrapper implements ILightMapWrapper
//==================// //==================//
//region //region
#if MC_VER > MC_1_12_2
public void uploadLightmap(NativeImage image) public void uploadLightmap(NativeImage image)
{ {
#if MC_VER < MC_1_21_3 #if MC_VER < MC_1_21_3
@@ -110,6 +114,7 @@ public class LightMapWrapper implements ILightMapWrapper
throw new UnsupportedOperationException("setLightmapId should be used for MC versions after 1.21.3"); throw new UnsupportedOperationException("setLightmapId should be used for MC versions after 1.21.3");
#endif #endif
} }
#endif
public void setLightmapId(int minecraftLightmapTextureId) public void setLightmapId(int minecraftLightmapTextureId)
{ {
@@ -126,6 +131,7 @@ public class LightMapWrapper implements ILightMapWrapper
} }
#endif #endif
//endregion //endregion
@@ -1,7 +1,11 @@
package com.seibel.distanthorizons.common.wrappers.misc; package com.seibel.distanthorizons.common.wrappers.misc;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IMutableBlockPosWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IMutableBlockPosWrapper;
#if MC_VER <= MC_1_12_2
import net.minecraft.util.math.BlockPos;
#else
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
#endif
public class MutableBlockPosWrapper implements IMutableBlockPosWrapper public class MutableBlockPosWrapper implements IMutableBlockPosWrapper
{ {
@@ -12,19 +16,27 @@ public class MutableBlockPosWrapper implements IMutableBlockPosWrapper
//=============// //=============//
// constructor // // constructor //
//=============// //=============//
//region
public MutableBlockPosWrapper() public MutableBlockPosWrapper()
{ {
this.pos = new BlockPos.MutableBlockPos(); this.pos = new BlockPos.MutableBlockPos();
} }
//endregion
//===========// //===========//
// overrides // // overrides //
//===========// //===========//
//region
@Override @Override
public Object getWrappedMcObject() { return this.pos; } public Object getWrappedMcObject() { return this.pos; }
//endregion
} }
@@ -6,53 +6,114 @@ import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
import com.seibel.distanthorizons.core.util.math.Vec3d; import com.seibel.distanthorizons.core.util.math.Vec3d;
#if MC_VER <= MC_1_12_2
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.WorldServer;
#else
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.server.network.ServerGamePacketListenerImpl;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
#endif
import java.net.SocketAddress; import java.net.SocketAddress;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
#if MC_VER <= MC_1_12_2
/**
* This wrapper transparently ensures that the underlying {@link EntityPlayerMP} is always valid,
* unless the player has disconnected.
*/
#else
/** /**
* This wrapper transparently ensures that the underlying {@link ServerPlayer} is always valid, * This wrapper transparently ensures that the underlying {@link ServerPlayer} is always valid,
* unless the player has disconnected. * unless the player has disconnected.
*/ */
#endif
public class ServerPlayerWrapper implements IServerPlayerWrapper public class ServerPlayerWrapper implements IServerPlayerWrapper
{ {
#if MC_VER <= MC_1_12_2
private static final ConcurrentMap<NetHandlerPlayServer, ServerPlayerWrapper> serverPlayerWrapperMap = new MapMaker().weakKeys().weakValues().makeMap();
#else
private static final ConcurrentMap<ServerGamePacketListenerImpl, ServerPlayerWrapper> serverPlayerWrapperMap = new MapMaker().weakKeys().weakValues().makeMap(); private static final ConcurrentMap<ServerGamePacketListenerImpl, ServerPlayerWrapper> serverPlayerWrapperMap = new MapMaker().weakKeys().weakValues().makeMap();
#endif
#if MC_VER <= MC_1_12_2
private final NetHandlerPlayServer connection;
#else
private final ServerGamePacketListenerImpl connection; private final ServerGamePacketListenerImpl connection;
#endif
//=============// //=============//
// constructor // // constructor //
//=============// //=============//
//region
public static ServerPlayerWrapper getWrapper(ServerPlayer serverPlayer) #if MC_VER <= MC_1_12_2
public static ServerPlayerWrapper getWrapper(EntityPlayerMP serverPlayer)
#else
public static ServerPlayerWrapper getWrapper(ServerPlayer serverPlayer)
#endif
{ return serverPlayerWrapperMap.computeIfAbsent(serverPlayer.connection, ignored -> new ServerPlayerWrapper(serverPlayer.connection)); } { return serverPlayerWrapperMap.computeIfAbsent(serverPlayer.connection, ignored -> new ServerPlayerWrapper(serverPlayer.connection)); }
private ServerPlayerWrapper(ServerGamePacketListenerImpl connection) { this.connection = connection; } #if MC_VER <= MC_1_12_2
private ServerPlayerWrapper(NetHandlerPlayServer connection)
#else
private ServerPlayerWrapper(ServerGamePacketListenerImpl connection)
#endif
{ this.connection = connection; }
//endregion
//=========// //=========//
// getters // // getters //
//=========// //=========//
//region
private ServerPlayer getServerPlayer() { return this.connection.player; } #if MC_VER <= MC_1_12_2
private EntityPlayerMP getServerPlayer()
#else
private ServerPlayer getServerPlayer()
#endif
{ return this.connection.player; }
@Override @Override
public String getName() { return this.getServerPlayer().getName().getString(); } public String getName()
{
#if MC_VER <= MC_1_12_2
return this.getServerPlayer().getName();
#else
return this.getServerPlayer().getName().getString();
#endif
}
@Override @Override
public IServerLevelWrapper getLevel() public IServerLevelWrapper getLevel()
{ {
ServerLevel level = ((IMixinServerPlayer) this.getServerPlayer()).distantHorizons$getDimensionChangeDestination(); #if MC_VER <= MC_1_12_2
WorldServer level = null;
if (this.getServerPlayer() instanceof IMixinServerPlayer mixinPlayer)
{
level = mixinPlayer.distantHorizons$getDimensionChangeDestination();
}
#else
ServerLevel level = ((IMixinServerPlayer) this.getServerPlayer()).distantHorizons$getDimensionChangeDestination();
#endif
if (level == null) if (level == null)
{ {
#if MC_VER < MC_1_20_1 #if MC_VER <= MC_1_12_2
MinecraftServer server = this.getServerPlayer().getServer();
level = (server != null) ? server.getWorld(this.getServerPlayer().dimension) : this.getServerPlayer().getServerWorld();
#elif MC_VER < MC_1_20_1
level = this.getServerPlayer().getLevel(); level = this.getServerPlayer().getLevel();
#elif MC_VER < MC_1_21_6 #elif MC_VER < MC_1_21_6
level = this.getServerPlayer().serverLevel(); level = this.getServerPlayer().serverLevel();
@@ -67,15 +128,23 @@ public class ServerPlayerWrapper implements IServerPlayerWrapper
@Override @Override
public Vec3d getPosition() public Vec3d getPosition()
{ {
#if MC_VER <= MC_1_12_2
BlockPos position = this.getServerPlayer().getPosition();
return new Vec3d(position.getX(), position.getY(), position.getZ());
#else
Vec3 position = this.getServerPlayer().position(); Vec3 position = this.getServerPlayer().position();
return new Vec3d(position.x, position.y, position.z); return new Vec3d(position.x, position.y, position.z);
#endif
} }
//endregion
//================// //================//
// base overrides // // base overrides //
//================// //================//
//region
@Override @Override
public Object getWrappedMcObject() { return this.getServerPlayer(); } public Object getWrappedMcObject() { return this.getServerPlayer(); }
@@ -101,4 +170,8 @@ public class ServerPlayerWrapper implements IServerPlayerWrapper
@Override @Override
public int hashCode() { return Objects.hashCode(this.connection); } public int hashCode() { return Objects.hashCode(this.connection); }
//endregion
} }
@@ -0,0 +1,144 @@
/*
* 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.modAccessor;
#if MC_VER > MC_1_12_2
import com.google.common.base.Suppliers;
import com.mojang.blaze3d.systems.RenderSystem;
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
import com.seibel.distanthorizons.core.util.math.Vec3d;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ImmersivePortalsAbstractAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.culling.Frustum;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
#if MC_VER > MC_1_19_2
import org.joml.Matrix4f;
#else
import com.mojang.math.Matrix4f;
import com.seibel.distanthorizons.core.util.math.Mat4f;
#endif
#if MC_VER < MC_1_17_1
import java.lang.reflect.Field;
#endif
import java.util.function.Supplier;
public abstract class ImmersivePortalsAccessorCommon extends ImmersivePortalsAbstractAccessor
{
// We don't use the fields in RenderStates because they are not volatile.
@Nullable
public static volatile ClientLevel originalLevel;
@Nullable
public static volatile DhBlockPos originalBlockPos;
@Nullable
public static volatile DhChunkPos originalChunkPos;
@Nullable
public static volatile Vec3d originalCameraPos;
@Override
protected Object getClientLevel() { return Minecraft.getInstance().level; }
@Override
protected Class<?> getLevelClass() { return Level.class; }
@Override
protected Iterable<?> getEntitiesForRendering() { return Minecraft.getInstance().level.entitiesForRendering(); }
#if MC_VER < MC_1_21_6
private static Matrix4f getProjectionMatrix()
{
#if MC_VER > MC_1_16_5
return RenderSystem.getProjectionMatrix();
#else
try
{
Class<?> renderStates = Class.forName("com.qouteall.immersive_portals.render.context_management.RenderStates");
Field projectionMatrix = renderStates.getField("projectionMatrix");
return (Matrix4f) projectionMatrix.get(null);
}
catch (Throwable e)
{
throw new RuntimeException(e);
}
#endif
}
#endif
#if MC_VER <= MC_1_19_2
protected abstract Matrix4f convert(Mat4f matrix);
#endif
@Override
protected Supplier<?> getFrustumSupplier()
{
#if MC_VER < MC_1_21_6 // TODO Fix this for 1.21.6+ when a more modern version of Immersive Portals is available.
return Suppliers.memoize(() -> {
Frustum frustum = new Frustum(
#if MC_VER > MC_1_19_2
ClientApi.RENDER_STATE.mcModelViewMatrix.createJomlMatrix(),
#else
convert(ClientApi.RENDER_STATE.mcModelViewMatrix),
#endif
getProjectionMatrix()
);
Vec3 cameraPos = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition();
frustum.prepare(cameraPos.x, cameraPos.y, cameraPos.z);
return frustum;
});
#else
return null;
#endif
}
@Override
@Nullable
public DhBlockPos getOriginalPlayerBlockPos() {
return originalBlockPos;
}
@Override
@Nullable
public DhChunkPos getOriginalPlayerChunkPos() {
return originalChunkPos;
}
@Override
@Nullable
public IClientLevelWrapper getOriginalClientLevelWrapper() {
return ClientLevelWrapper.getWrapper(originalLevel, false);
}
@Override
@Nullable
public Vec3d getOriginalCameraPos() {
return originalCameraPos;
}
}
#endif
@@ -1,31 +1,48 @@
package com.seibel.distanthorizons.common.wrappers.world; package com.seibel.distanthorizons.common.wrappers.world;
import com.seibel.distanthorizons.api.enums.config.EDhApiLodShading;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper; import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper;
import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper; import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper;
import com.seibel.distanthorizons.common.wrappers.block.ClientBlockStateColorCache; import com.seibel.distanthorizons.common.wrappers.block.ClientBlockStateColorCache;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
import com.seibel.distanthorizons.common.wrappers.level.KeyedClientLevelManager;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftClientWrapper;
import com.seibel.distanthorizons.core.api.internal.SharedApi;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.enums.EDhDirection;
import com.seibel.distanthorizons.core.level.*; import com.seibel.distanthorizons.core.level.*;
import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel; import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos; import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.util.TimerUtil;
import com.seibel.distanthorizons.core.world.AbstractDhWorld;
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
#if MC_VER <= MC_1_12_2
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.WorldServer;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.block.state.IBlockState;
#else
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
#endif
import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLogger;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -33,19 +50,20 @@ import java.awt.*;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.Collections; import java.util.*;
import java.util.Map; import java.util.List;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function; import java.util.function.Function;
#if MC_VER <= MC_1_20_4 #if MC_VER <= MC_1_12_2
#elif MC_VER <= MC_1_20_4
import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.ChunkStatus;
#else #else
import net.minecraft.world.level.chunk.status.ChunkStatus; import net.minecraft.world.level.chunk.status.ChunkStatus;
#endif #endif
#if MC_VER < MC_1_21_3 #if MC_VER <= MC_1_12_2
#elif MC_VER < MC_1_21_3
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
#else #else
import com.seibel.distanthorizons.coreapi.util.ColorUtil; import com.seibel.distanthorizons.coreapi.util.ColorUtil;
@@ -65,22 +83,42 @@ public class ClientLevelWrapper implements IClientLevelWrapper
* where, upon world closure, some levels aren't shutdown/removed properly * where, upon world closure, some levels aren't shutdown/removed properly
* and/or for servers were the level object isn't consistent * 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 Map<
#if MC_VER <= MC_1_12_2 WorldClient #else ClientLevel #endif,
WeakReference<ClientLevelWrapper>> LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL = Collections.synchronizedMap(new WeakHashMap<>());
private static final IKeyedClientLevelManager KEYED_CLIENT_LEVEL_MANAGER = SingletonInjector.INSTANCE.get(IKeyedClientLevelManager.class); private static final IKeyedClientLevelManager KEYED_CLIENT_LEVEL_MANAGER = SingletonInjector.INSTANCE.get(IKeyedClientLevelManager.class);
#if MC_VER <= MC_1_12_2
private static final Minecraft MINECRAFT = Minecraft.getMinecraft();
#else
private static final Minecraft MINECRAFT = Minecraft.getInstance(); private static final Minecraft MINECRAFT = Minecraft.getInstance();
#endif
private static final Timer CLIENT_CLEANUP_TIMER = TimerUtil.CreateTimer("ClientLevelTickCleanup");
private static final TimerTask CLIENT_CLEANUP_TASK = TimerUtil.createTimerTask(ClientLevelWrapper::tickCleanup);
#if MC_VER <= MC_1_12_2
private final WorldClient level;
private final ConcurrentHashMap<IBlockState, ClientBlockStateColorCache> blockColorCacheByBlockState = new ConcurrentHashMap<>();
#else
private final ClientLevel level; private final ClientLevel level;
private final ConcurrentHashMap<BlockState, ClientBlockStateColorCache> blockColorCacheByBlockState = new ConcurrentHashMap<>(); private final ConcurrentHashMap<BlockState, ClientBlockStateColorCache> blockColorCacheByBlockState = new ConcurrentHashMap<>();
#endif
/** cached method reference to reduce GC overhead */ /** cached method reference to reduce GC overhead */
private final Function<BlockState, ClientBlockStateColorCache> createCachedBlockColorCacheFunc = (blockState) -> new ClientBlockStateColorCache(blockState, this); private final Function<
#if MC_VER <= MC_1_12_2 IBlockState #else BlockState #endif,
ClientBlockStateColorCache> createCachedBlockColorCacheFunc
= (blockState) -> new ClientBlockStateColorCache(blockState, this);
private boolean cloudColorFailLogged = false; private boolean cloudColorFailLogged = false;
private BlockStateWrapper dirtBlockWrapper; private volatile BlockStateWrapper dirtBlockWrapper;
private IDhLevel dhLevel; private volatile IDhLevel dhLevel;
private volatile long lastAccessTime = System.currentTimeMillis();
@@ -89,7 +127,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper
//=============// //=============//
//region //region
protected ClientLevelWrapper(ClientLevel level) { this.level = level; } protected ClientLevelWrapper(#if MC_VER <= MC_1_12_2 WorldClient #else ClientLevel #endif level) { this.level = level; }
//endregion //endregion
@@ -100,16 +138,102 @@ public class ClientLevelWrapper implements IClientLevelWrapper
//==================// //==================//
//region //region
@Override
public synchronized void markAccessed() { this.lastAccessTime = System.currentTimeMillis(); }
public synchronized long getLastAccessTime() { return this.lastAccessTime; }
static
{
// 20 ticks per second (50ms interval)
CLIENT_CLEANUP_TIMER.scheduleAtFixedRate(CLIENT_CLEANUP_TASK, 0, 1000 / 20);
}
private void unload()
{
AbstractDhWorld world = SharedApi.getAbstractDhWorld();
if (world == null || !world.unloadLevel(this))
{
this.onUnload();
}
}
private static #if MC_VER > MC_1_12_2 ClientLevel #else WorldClient #endif clientLevel() {
return #if MC_VER > MC_1_12_2 MINECRAFT.level #else MINECRAFT.world #endif;
}
public static void tickCleanup()
{
if (clientLevel() == null)
{
return;
}
long currentTime = System.currentTimeMillis();
long timeout = 30 * 1000;
ArrayList<ClientLevelWrapper> toUnload = new ArrayList<>();
synchronized(LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL)
{
for (WeakReference<ClientLevelWrapper> ref : LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL.values())
{
ClientLevelWrapper wrapper = ref.get();
if (wrapper != null
&& wrapper.level != clientLevel())
{
// We use the synchronized getter to prevent race conditions with markAccessed()
if (currentTime - wrapper.getLastAccessTime() > timeout)
{
toUnload.add(wrapper);
}
}
}
}
for (ClientLevelWrapper wrapper : toUnload)
{
// Re-verify all conditions inside a synchronized block on the wrapper
// to ensure atomicity with respect to markAccessed()
synchronized(wrapper)
{
if (wrapper.level != clientLevel()
&& currentTime - wrapper.getLastAccessTime() > timeout)
{
LOGGER.debug("Unloading level [" + wrapper.getDhIdentifier() + "] due to inactivity");
wrapper.unload();
}
}
}
}
/** /**
* can be used when speed is important and the same level is likely to be passed in, * can be used when speed is important and the same level is likely to be passed in,
* IE rendering. * IE rendering.
*/ */
@Nullable @Nullable
public static IClientLevelWrapper getWrapperIfDifferent(@Nullable IClientLevelWrapper levelWrapper, @NotNull ClientLevel level) public static IClientLevelWrapper getWrapperIfDifferent(
@Nullable IClientLevelWrapper levelWrapper,
@NotNull #if MC_VER <= MC_1_12_2 WorldClient #else ClientLevel #endif level)
{ {
if (KEYED_CLIENT_LEVEL_MANAGER.isEnabled() && KEYED_CLIENT_LEVEL_MANAGER.getServerKeyedLevel() != levelWrapper) if (KEYED_CLIENT_LEVEL_MANAGER.isEnabled())
{ {
return getWrapper(level); IServerKeyedClientLevel keyedLevel = null;
if (KEYED_CLIENT_LEVEL_MANAGER instanceof KeyedClientLevelManager)
{
keyedLevel = ((KeyedClientLevelManager) KEYED_CLIENT_LEVEL_MANAGER).getServerKeyedLevel(level);
}
else
{
// FIXME: If the implementation is not KeyedClientLevelManager,
// this fallback may return the key for the wrong dimension in multiverse scenarios.
keyedLevel = KEYED_CLIENT_LEVEL_MANAGER.getServerKeyedLevel();
}
if (keyedLevel != levelWrapper)
{
return getWrapper(level);
}
} }
ClientLevelWrapper clientLevelWrapper = (ClientLevelWrapper)levelWrapper; ClientLevelWrapper clientLevelWrapper = (ClientLevelWrapper)levelWrapper;
@@ -123,10 +247,13 @@ public class ClientLevelWrapper implements IClientLevelWrapper
} }
@Nullable @Nullable
public static IClientLevelWrapper getWrapper(@NotNull ClientLevel level) { return getWrapper(level, false); } public static IClientLevelWrapper getWrapper(
@NotNull #if MC_VER <= MC_1_12_2 WorldClient #else ClientLevel #endif level)
{ return getWrapper(level, false); }
@Nullable @Nullable
public static IClientLevelWrapper getWrapper(@Nullable ClientLevel level, boolean bypassLevelKeyManager) public static IClientLevelWrapper getWrapper(
@Nullable #if MC_VER <= MC_1_12_2 WorldClient #else ClientLevel #endif level, boolean bypassLevelKeyManager)
{ {
if (!bypassLevelKeyManager) if (!bypassLevelKeyManager)
{ {
@@ -136,9 +263,31 @@ public class ClientLevelWrapper implements IClientLevelWrapper
} }
// used if the client is connected to a server that defines the currently loaded level // used if the client is connected to a server that defines the currently loaded level
IServerKeyedClientLevel overrideLevel = KEYED_CLIENT_LEVEL_MANAGER.getServerKeyedLevel(); IServerKeyedClientLevel overrideLevel = null;
if (KEYED_CLIENT_LEVEL_MANAGER instanceof KeyedClientLevelManager)
{
overrideLevel = ((KeyedClientLevelManager) KEYED_CLIENT_LEVEL_MANAGER).getServerKeyedLevel(level);
}
else
{
// FIXME: If the implementation is not KeyedClientLevelManager,
// this fallback may return the key for the wrong dimension in multiverse scenarios.
overrideLevel = KEYED_CLIENT_LEVEL_MANAGER.getServerKeyedLevel();
}
if (overrideLevel != null) if (overrideLevel != null)
{ {
WeakReference<ClientLevelWrapper> levelRef = LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL.get(level);
if (levelRef != null && levelRef.get() != overrideLevel)
{
ClientLevelWrapper l = levelRef.get();
if (l != null) l.unload();
levelRef = null;
}
if (levelRef == null && overrideLevel instanceof ClientLevelWrapper)
{
LEVEL_WRAPPER_REF_BY_CLIENT_LEVEL.put(level, new WeakReference<>((ClientLevelWrapper) overrideLevel));
}
return overrideLevel; return overrideLevel;
} }
} }
@@ -177,19 +326,27 @@ public class ClientLevelWrapper implements IClientLevelWrapper
try try
{ {
// this method only makes sense if we are running a single-player server // this method only makes sense if we are running a single-player server
if (MINECRAFT.getSingleplayerServer() == null) if (MINECRAFT.#if MC_VER <= MC_1_12_2 getIntegratedServer() #else getSingleplayerServer() #endif == null)
{ {
return null; return null;
} }
#if MC_VER <= MC_1_12_2
WorldServer[] serverLevels = MINECRAFT.getIntegratedServer().worlds;
#else
Iterable<ServerLevel> serverLevels = MINECRAFT.getSingleplayerServer().getAllLevels(); Iterable<ServerLevel> serverLevels = MINECRAFT.getSingleplayerServer().getAllLevels();
#endif
// attempt to find the server level with the same dimension type // attempt to find the server level with the same dimension type
// Note: this assumes only one level per dimension type, multiverse servers may not behave correctly // Note: this assumes only one level per dimension type, multiverse servers may not behave correctly
ServerLevelWrapper foundLevelWrapper = null; ServerLevelWrapper foundLevelWrapper = null;
for (ServerLevel serverLevel : serverLevels) for (#if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif serverLevel : serverLevels)
{ {
#if MC_VER <= MC_1_12_2
if (serverLevel.provider.getDimension() == this.level.provider.getDimension())
#else
if (serverLevel.dimension() == this.level.dimension()) if (serverLevel.dimension() == this.level.dimension())
#endif
{ {
foundLevelWrapper = ServerLevelWrapper.getWrapper(serverLevel); foundLevelWrapper = ServerLevelWrapper.getWrapper(serverLevel);
break; break;
@@ -262,7 +419,9 @@ public class ClientLevelWrapper implements IClientLevelWrapper
return this.dimensionTypeWrapper; return this.dimensionTypeWrapper;
} }
#if MC_VER <= MC_1_21_10 #if MC_VER <= MC_1_12_2
this.dimensionTypeWrapper = DimensionTypeWrapper.getDimensionTypeWrapper(this.level.provider.getDimensionType());
#elif MC_VER <= MC_1_21_10
this.dimensionTypeWrapper = DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType()); this.dimensionTypeWrapper = DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType());
#else #else
this.dimensionTypeWrapper = DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType(), this.getDimensionName()); this.dimensionTypeWrapper = DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType(), this.getDimensionName());
@@ -281,8 +440,9 @@ public class ClientLevelWrapper implements IClientLevelWrapper
return this.dimensionName; return this.dimensionName;
} }
#if MC_VER <= MC_1_12_2
#if MC_VER <= MC_1_21_10 this.dimensionName = this.level.provider.getDimensionType().getName() + ":" + this.level.provider.getDimension();
#elif MC_VER <= MC_1_21_10
this.dimensionName = this.level.dimension().location().toString(); this.dimensionName = this.level.dimension().location().toString();
#else #else
this.dimensionName = this.level.dimension().identifier().toString(); this.dimensionName = this.level.dimension().identifier().toString();
@@ -291,7 +451,14 @@ public class ClientLevelWrapper implements IClientLevelWrapper
} }
@Override @Override
public long getHashedSeed() { return this.level.getBiomeManager().biomeZoomSeed; } public long getHashedSeed()
{
#if MC_VER <= MC_1_12_2
return this.level.getSeed();
#else
return this.level.getBiomeManager().biomeZoomSeed;
#endif
}
@Override @Override
public String getDhIdentifier() { return this.getHashedSeedEncoded() + "@" + this.getDimensionName(); } public String getDhIdentifier() { return this.getHashedSeedEncoded() + "@" + this.getDimensionName(); }
@@ -299,7 +466,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper
@Override @Override
public EDhApiLevelType getLevelType() { return EDhApiLevelType.CLIENT_LEVEL; } public EDhApiLevelType getLevelType() { return EDhApiLevelType.CLIENT_LEVEL; }
public ClientLevel getLevel() { return this.level; } public #if MC_VER <= MC_1_12_2 WorldClient #else ClientLevel #endif getLevel() { return this.level; }
private Boolean dimHasCeiling = null; private Boolean dimHasCeiling = null;
@Override @Override
@@ -312,8 +479,12 @@ public class ClientLevelWrapper implements IClientLevelWrapper
return this.dimHasCeiling; return this.dimHasCeiling;
} }
#if MC_VER <= MC_1_12_2
// 1.12.2 has no hasCeiling() - only the nether has a ceiling in vanilla
this.dimHasCeiling = this.level.provider.isNether();
#else
this.dimHasCeiling = this.level.dimensionType().hasCeiling(); this.dimHasCeiling = this.level.dimensionType().hasCeiling();
#endif
return this.dimHasCeiling; return this.dimHasCeiling;
} }
@@ -328,7 +499,11 @@ public class ClientLevelWrapper implements IClientLevelWrapper
return this.dimHasSkyLight; return this.dimHasSkyLight;
} }
#if MC_VER <= MC_1_12_2
this.dimHasSkyLight = this.level.provider.hasSkyLight();
#else
this.dimHasSkyLight = this.level.dimensionType().hasSkyLight(); this.dimHasSkyLight = this.level.dimensionType().hasSkyLight();
#endif
return this.dimHasSkyLight; return this.dimHasSkyLight;
} }
@@ -370,7 +545,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper
} }
@Override @Override
public ClientLevel getWrappedMcObject() { return this.level; } public #if MC_VER <= MC_1_12_2 WorldClient #else ClientLevel #endif getWrappedMcObject() { return this.level; }
@Override @Override
public void onUnload() public void onUnload()
@@ -419,10 +594,20 @@ public class ClientLevelWrapper implements IClientLevelWrapper
public Color getCloudColor(float tickDelta) public Color getCloudColor(float tickDelta)
{ {
#if MC_VER < MC_1_21_3 #if MC_VER < MC_1_21_3
#if MC_VER <= MC_1_12_2
Vec3d colorVec3 = null;
#else
Vec3 colorVec3 = null; Vec3 colorVec3 = null;
#endif
try try
{ {
#if MC_VER <= MC_1_12_2
colorVec3 = this.level.getCloudColour(tickDelta);
#else
colorVec3 = this.level.getCloudColor(tickDelta); colorVec3 = this.level.getCloudColor(tickDelta);
#endif
return new Color((float)colorVec3.x, (float)colorVec3.y, (float)colorVec3.z); return new Color((float)colorVec3.x, (float)colorVec3.y, (float)colorVec3.z);
} }
catch (Exception e) catch (Exception e)
@@ -484,6 +669,45 @@ public class ClientLevelWrapper implements IClientLevelWrapper
#endif #endif
} }
@Override
public float getShade(EDhDirection lodDirection)
{
EDhApiLodShading lodShading = Config.Client.Advanced.Graphics.Quality.lodShading.get();
switch (lodShading)
{
default:
case AUTO:
#if MC_VER <= MC_1_12_2
// 1.12.2 level doesn't have a getShade method, fall through to ENABLED
#else
Direction mcDir = McObjectConverter.Convert(lodDirection);
#if MC_VER <= MC_1_21_11
return this.level.getShade(mcDir, true);
#else
return this.level.cardinalLighting().byFace(mcDir);
#endif
#endif
case ENABLED:
switch (lodDirection)
{
case DOWN:
return 0.5F;
default:
case UP:
return 1.0F;
case NORTH:
case SOUTH:
return 0.8F;
case WEST:
case EAST:
return 0.6F;
}
case DISABLED:
return 1.0F;
}
}
//endregion //endregion
@@ -24,7 +24,11 @@ import java.util.concurrent.ConcurrentMap;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWrapper;
#if MC_VER <= MC_1_12_2
import net.minecraft.world.DimensionType;
#else
import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.DimensionType;
#endif
public class DimensionTypeWrapper implements IDimensionTypeWrapper public class DimensionTypeWrapper implements IDimensionTypeWrapper
{ {
@@ -86,7 +90,9 @@ public class DimensionTypeWrapper implements IDimensionTypeWrapper
} }
private static String determineName(DimensionType dimensionType) private static String determineName(DimensionType dimensionType)
{ {
#if MC_VER <= MC_1_16_5 #if MC_VER <= MC_1_12_2
return dimensionType.getName();
#elif MC_VER <= MC_1_16_5
// effectsLocation() is marked as client only, so using the backing field directly // effectsLocation() is marked as client only, so using the backing field directly
return dimensionType.effectsLocation.getPath(); return dimensionType.effectsLocation.getPath();
#elif MC_VER <= MC_1_21_10 #elif MC_VER <= MC_1_21_10
@@ -108,10 +114,26 @@ public class DimensionTypeWrapper implements IDimensionTypeWrapper
public String getName() { return this.name; } public String getName() { return this.name; }
@Override @Override
public boolean hasCeiling() { return this.dimensionType.hasCeiling(); } public boolean hasCeiling()
{
#if MC_VER <= MC_1_12_2
// 1.12.2 has no hasCeiling() - only the nether has a ceiling in vanilla
return this.dimensionType.getId() == -1;
#else
return this.dimensionType.hasCeiling();
#endif
}
@Override @Override
public boolean hasSkyLight() { return this.dimensionType.hasSkyLight(); } public boolean hasSkyLight()
{
#if MC_VER <= MC_1_12_2
// 1.12.2 DimensionType doesn't store hasSkyLight, it's in the WorldProvider instead
return this.dimensionType != DimensionType.NETHER;
#else
return this.dimensionType.hasSkyLight();
#endif
}
@Override @Override
public Object getWrappedMcObject() { return this.dimensionType; } public Object getWrappedMcObject() { return this.dimensionType; }
@@ -120,7 +142,15 @@ public class DimensionTypeWrapper implements IDimensionTypeWrapper
public boolean isTheEnd() { return this.getName().equalsIgnoreCase("the_end"); } public boolean isTheEnd() { return this.getName().equalsIgnoreCase("the_end"); }
@Override @Override
public double getCoordinateScale() { return this.dimensionType.coordinateScale(); } public double getCoordinateScale()
{
#if MC_VER <= MC_1_12_2
// 1.12.2 DimensionType doesn't store coordinate scale, it's in the WorldProvider instead
return this.dimensionType == net.minecraft.world.DimensionType.NETHER ? 8.0 : 1.0;
#else
return this.dimensionType.coordinateScale();
#endif
}
@@ -38,12 +38,17 @@ import com.seibel.distanthorizons.core.world.EWorldEnvironment;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
#if MC_VER <= MC_1_12_2
import net.minecraft.world.WorldServer;
#else
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkSource; import net.minecraft.world.level.chunk.ChunkSource;
#endif
#if MC_VER <= MC_1_20_4 #if MC_VER <= MC_1_12_2
#elif MC_VER <= MC_1_20_4
import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.ChunkStatus;
#else #else
import net.minecraft.world.level.chunk.status.ChunkStatus; import net.minecraft.world.level.chunk.status.ChunkStatus;
@@ -59,9 +64,9 @@ public class ServerLevelWrapper implements IServerLevelWrapper
* weak references are to prevent rare issues * weak references are to prevent rare issues
* where, upon world closure, some levels aren't shutdown/removed properly * 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 static final Map<#if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif, WeakReference<ServerLevelWrapper>> LEVEL_WRAPPER_REF_BY_SERVER_LEVEL = Collections.synchronizedMap(new WeakHashMap<>());
private final ServerLevel level; private final #if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif level;
private IDhLevel dhLevel; private IDhLevel dhLevel;
/** /**
@@ -76,7 +81,7 @@ public class ServerLevelWrapper implements IServerLevelWrapper
// constructors // // constructors //
//==============// //==============//
public static ServerLevelWrapper getWrapper(ServerLevel level) public static ServerLevelWrapper getWrapper(#if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif level)
{ {
return LEVEL_WRAPPER_REF_BY_SERVER_LEVEL.compute(level, (newLevel, levelRef) -> return LEVEL_WRAPPER_REF_BY_SERVER_LEVEL.compute(level, (newLevel, levelRef) ->
{ {
@@ -93,7 +98,7 @@ public class ServerLevelWrapper implements IServerLevelWrapper
}).get(); }).get();
} }
public ServerLevelWrapper(ServerLevel level) public ServerLevelWrapper(#if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif level)
{ {
this.level = level; this.level = level;
this.KeyedLevelDimensionName = this.createKeyedLevelDimensionName(); this.KeyedLevelDimensionName = this.createKeyedLevelDimensionName();
@@ -108,7 +113,9 @@ public class ServerLevelWrapper implements IServerLevelWrapper
@Override @Override
public File getMcSaveFolder() public File getMcSaveFolder()
{ {
#if MC_VER < MC_1_21_3 #if MC_VER <= MC_1_12_2
return new File(this.level.getChunkSaveLocation(), "data");
#elif MC_VER < MC_1_21_3
return this.level.getChunkSource().getDataStorage().dataFolder; return this.level.getChunkSource().getDataStorage().dataFolder;
#else #else
return this.level.getChunkSource().getDataStorage().dataFolder.toFile(); return this.level.getChunkSource().getDataStorage().dataFolder.toFile();
@@ -157,7 +164,9 @@ public class ServerLevelWrapper implements IServerLevelWrapper
{ {
// We use the overworld since it's the only dimension that is stored in the server root folder // We use the overworld since it's the only dimension that is stored in the server root folder
#if MC_VER >= MC_1_21_3 #if MC_VER <= MC_1_12_2
return this.level.getMinecraftServer().getWorld(0).getSaveHandler().getWorldDirectory().getParentFile().getName();
#elif MC_VER >= MC_1_21_3
return this.level.getServer().getLevel(Level.OVERWORLD).getChunkSource().getDataStorage().dataFolder.getParent().getFileName().toString(); return this.level.getServer().getLevel(Level.OVERWORLD).getChunkSource().getDataStorage().dataFolder.getParent().getFileName().toString();
#else // <= 1.21.3 #else // <= 1.21.3
return this.level.getServer().getLevel(Level.OVERWORLD).getChunkSource().getDataStorage().dataFolder.getParentFile().getName(); return this.level.getServer().getLevel(Level.OVERWORLD).getChunkSource().getDataStorage().dataFolder.getParentFile().getName();
@@ -174,7 +183,9 @@ public class ServerLevelWrapper implements IServerLevelWrapper
@Override @Override
public DimensionTypeWrapper getDimensionType() public DimensionTypeWrapper getDimensionType()
{ {
#if MC_VER <= MC_1_21_10 #if MC_VER <= MC_1_12_2
return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.provider.getDimensionType());
#elif MC_VER <= MC_1_21_10
return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType()); return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType());
#else #else
return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType(), this.getDimensionName()); return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType(), this.getDimensionName());
@@ -184,7 +195,9 @@ public class ServerLevelWrapper implements IServerLevelWrapper
@Override @Override
public String getDimensionName() public String getDimensionName()
{ {
#if MC_VER <= MC_1_21_10 #if MC_VER <= MC_1_12_2
return this.level.provider.getDimensionType().getName() + ":" + this.level.provider.getDimension();
#elif MC_VER <= MC_1_21_10
return this.level.dimension().location().toString(); return this.level.dimension().location().toString();
#else #else
return this.level.dimension().identifier().toString(); return this.level.dimension().identifier().toString();
@@ -192,7 +205,14 @@ public class ServerLevelWrapper implements IServerLevelWrapper
} }
@Override @Override
public long getHashedSeed() { return this.level.getBiomeManager().biomeZoomSeed; } public long getHashedSeed()
{
#if MC_VER <= MC_1_12_2
return this.level.getSeed();
#else
return this.level.getBiomeManager().biomeZoomSeed;
#endif
}
@Override @Override
public String getDhIdentifier() { return this.getDimensionName(); } public String getDhIdentifier() { return this.getDimensionName(); }
@@ -200,13 +220,28 @@ public class ServerLevelWrapper implements IServerLevelWrapper
@Override @Override
public EDhApiLevelType getLevelType() { return EDhApiLevelType.SERVER_LEVEL; } public EDhApiLevelType getLevelType() { return EDhApiLevelType.SERVER_LEVEL; }
public ServerLevel getLevel() { return this.level; } public #if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif getLevel() { return this.level; }
@Override @Override
public boolean hasCeiling() { return this.level.dimensionType().hasCeiling(); } public boolean hasCeiling()
{
#if MC_VER <= MC_1_12_2
// 1.12.2 has no hasCeiling() - only the nether has a ceiling in vanilla
return this.level.provider.isNether();
#else
return this.level.dimensionType().hasCeiling();
#endif
}
@Override @Override
public boolean hasSkyLight() { return this.level.dimensionType().hasSkyLight(); } public boolean hasSkyLight()
{
#if MC_VER <= MC_1_12_2
return this.level.provider.hasSkyLight();
#else
return this.level.dimensionType().hasSkyLight();
#endif
}
@Override @Override
public int getMaxHeight() { return this.level.getHeight(); } public int getMaxHeight() { return this.level.getHeight(); }
@@ -224,7 +259,7 @@ public class ServerLevelWrapper implements IServerLevelWrapper
} }
@Override @Override
public ServerLevel getWrappedMcObject() { return this.level; } public #if MC_VER <= MC_1_12_2 WorldServer #else ServerLevel #endif getWrappedMcObject() { return this.level; }
@Override @Override
public void onUnload() { LEVEL_WRAPPER_REF_BY_SERVER_LEVEL.remove(this.level); } public void onUnload() { LEVEL_WRAPPER_REF_BY_SERVER_LEVEL.remove(this.level); }
@@ -26,8 +26,10 @@ import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGenerat
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep;
import com.seibel.distanthorizons.common.wrappers.McObjectConverter; import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
#if MC_VER > MC_1_12_2
import com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling.ChunkFileReader; import com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling.ChunkFileReader;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.*; import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.*;
#endif
import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.GlobalWorldGenParams; import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.GlobalWorldGenParams;
import com.seibel.distanthorizons.core.api.internal.SharedApi; import com.seibel.distanthorizons.core.api.internal.SharedApi;
import com.seibel.distanthorizons.core.api.internal.chunkUpdating.ChunkUpdateQueueManager; import com.seibel.distanthorizons.core.api.internal.chunkUpdating.ChunkUpdateQueueManager;
@@ -57,18 +59,26 @@ import com.seibel.distanthorizons.coreapi.ModInfo;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
#if MC_VER > MC_1_12_2
import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepBiomes; import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepBiomes;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepFeatures; import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepFeatures;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepNoise; import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepNoise;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepStructureReference; import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepStructureReference;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepStructureStart; import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepStructureStart;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepSurface; import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepSurface;
#endif
#if MC_VER <= MC_1_12_2
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.ForgeChunkManager;
#else
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.*; import net.minecraft.world.level.chunk.*;
import net.minecraft.world.level.levelgen.DebugLevelSource; import net.minecraft.world.level.levelgen.DebugLevelSource;
import net.minecraft.world.level.levelgen.FlatLevelSource; import net.minecraft.world.level.levelgen.FlatLevelSource;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
#endif
#if MC_VER <= MC_1_17_1 #if MC_VER <= MC_1_17_1
#elif MC_VER <= MC_1_19_2 #elif MC_VER <= MC_1_19_2
@@ -80,12 +90,14 @@ import net.minecraft.core.registries.Registries;
#else #else
#endif #endif
#if MC_VER <= MC_1_12_2
#if MC_VER <= MC_1_20_4 #elif MC_VER <= MC_1_20_4
import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.ChunkStatus;
#else #else
import net.minecraft.world.level.chunk.status.ChunkStatus; import net.minecraft.world.level.chunk.status.ChunkStatus;
#endif #endif
import org.jetbrains.annotations.Nullable;
public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironmentWrapper public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironmentWrapper
{ {
@@ -122,7 +134,10 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
private final ChunkUpdateQueueManager updateManager; private final ChunkUpdateQueueManager updateManager;
public final InternalServerGenerator internalServerGenerator; public final InternalServerGenerator internalServerGenerator;
#if MC_VER > MC_1_12_2
public final ChunkFileReader chunkFileReader; public final ChunkFileReader chunkFileReader;
#endif
private final Timer chunkSaveIgnoreTimer = TimerUtil.CreateTimer("ChunkSaveIgnoreTimer"); private final Timer chunkSaveIgnoreTimer = TimerUtil.CreateTimer("ChunkSaveIgnoreTimer");
@@ -131,12 +146,14 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
public final LinkedBlockingQueue<GenerationEvent> generationEventQueue = new LinkedBlockingQueue<>(); public final LinkedBlockingQueue<GenerationEvent> generationEventQueue = new LinkedBlockingQueue<>();
public final GlobalWorldGenParams globalParams; public final GlobalWorldGenParams globalParams;
#if MC_VER > MC_1_12_2
public final StepStructureStart stepStructureStart = new StepStructureStart(this); public final StepStructureStart stepStructureStart = new StepStructureStart(this);
public final StepStructureReference stepStructureReference = new StepStructureReference(this); public final StepStructureReference stepStructureReference = new StepStructureReference(this);
public final StepBiomes stepBiomes = new StepBiomes(this); public final StepBiomes stepBiomes = new StepBiomes(this);
public final StepNoise stepNoise = new StepNoise(this); public final StepNoise stepNoise = new StepNoise(this);
public final StepSurface stepSurface = new StepSurface(this); public final StepSurface stepSurface = new StepSurface(this);
public final StepFeatures stepFeatures = new StepFeatures(this); public final StepFeatures stepFeatures = new StepFeatures(this);
#endif
public boolean unsafeThreadingRecorded = false; public boolean unsafeThreadingRecorded = false;
public boolean generatedChunkWithoutBiomeWarningLogged = false; public boolean generatedChunkWithoutBiomeWarningLogged = false;
@@ -181,6 +198,8 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
this.updateManager = WorldChunkUpdateManager.INSTANCE.getByLevelWrapper(this.dhServerLevel.getServerLevelWrapper()); this.updateManager = WorldChunkUpdateManager.INSTANCE.getByLevelWrapper(this.dhServerLevel.getServerLevelWrapper());
this.globalParams = new GlobalWorldGenParams(dhServerLevel); this.globalParams = new GlobalWorldGenParams(dhServerLevel);
this.internalServerGenerator = new InternalServerGenerator(this.globalParams, this.dhServerLevel); this.internalServerGenerator = new InternalServerGenerator(this.globalParams, this.dhServerLevel);
#if MC_VER > MC_1_12_2
this.chunkFileReader = new ChunkFileReader(this.globalParams); this.chunkFileReader = new ChunkFileReader(this.globalParams);
ChunkGenerator generator = ((ServerLevelWrapper) (dhServerLevel.getServerLevelWrapper())).getLevel().getChunkSource().getGenerator(); ChunkGenerator generator = ((ServerLevelWrapper) (dhServerLevel.getServerLevelWrapper())).getLevel().getChunkSource().getGenerator();
@@ -201,6 +220,7 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
LOGGER.warn("If it does crash, disable Distant Generation or set the Generation Mode to [" + EDhApiDistantGeneratorMode.PRE_EXISTING_ONLY + "]."); LOGGER.warn("If it does crash, disable Distant Generation or set the Generation Mode to [" + EDhApiDistantGeneratorMode.PRE_EXISTING_ONLY + "].");
} }
} }
#endif
} }
@@ -309,6 +329,11 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
// variable setup // // variable setup //
//================// //================//
#if MC_VER <= MC_1_12_2
// MC 1.12 can only run world gen on the main thread
this.internalServerGenerator.generateChunksViaInternalServer(genEvent);
#else
int borderSize = MAX_WORLD_GEN_CHUNK_BORDER_NEEDED; int borderSize = MAX_WORLD_GEN_CHUNK_BORDER_NEEDED;
// genEvent.size - 1 converts the even width size to an odd number for MC compatability // genEvent.size - 1 converts the even width size to an odd number for MC compatability
int refSize = (genEvent.widthInChunks - 1) + (borderSize * 2); int refSize = (genEvent.widthInChunks - 1) + (borderSize * 2);
@@ -558,12 +583,14 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
{ {
LOGGER.error("Unexpected error during world gen for min chunk pos ["+genEvent.minPos+"], error: ["+e.getMessage()+"].", e); LOGGER.error("Unexpected error during world gen for min chunk pos ["+genEvent.minPos+"], error: ["+e.getMessage()+"].", e);
} }
#endif
} }
// direct generation // // direct generation //
#if MC_VER > MC_1_12_2
public void generateDirect( public void generateDirect(
GenerationEvent genEvent, ArrayGridList<ChunkWrapper> chunkWrappersToGenerate, GenerationEvent genEvent, ArrayGridList<ChunkWrapper> chunkWrappersToGenerate,
DhLitWorldGenRegion region) throws InterruptedException DhLitWorldGenRegion region) throws InterruptedException
@@ -728,7 +755,7 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
} }
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, int border) { return new ArrayGridList<>(total, border, total.gridSize - border); }
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, WORLD_GEN_CHUNK_BORDER_NEEDED_BY_GEN_STEP.get(step)); }
#endif
// queue task // // queue task //
@@ -769,8 +796,9 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
} }
#if MC_VER > MC_1_12_2
this.chunkFileReader.close(); this.chunkFileReader.close();
#endif
} }
@@ -798,12 +826,12 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
// helper classes // // helper classes //
//================// //================//
#if MC_VER > MC_1_12_2
@FunctionalInterface @FunctionalInterface
public interface IEmptyChunkRetrievalFunc public interface IEmptyChunkRetrievalFunc
{ {
ChunkAccess getChunk(int chunkPosX, int chunkPosZ); ChunkAccess getChunk(int chunkPosX, int chunkPosZ);
} }
#endif
}
}
@@ -1,6 +1,10 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration; package com.seibel.distanthorizons.common.wrappers.worldGeneration;
#if MC_VER <= MC_1_12_2
import net.minecraft.util.math.ChunkPos;
#else
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
#endif
import java.util.Iterator; import java.util.Iterator;
import java.util.Spliterator; import java.util.Spliterator;
@@ -25,7 +25,9 @@ import java.util.function.Consumer;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep;
#if MC_VER > MC_1_12_2
import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.ThreadWorldGenParams; import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.ThreadWorldGenParams;
#endif
import com.seibel.distanthorizons.core.util.ExceptionUtil; import com.seibel.distanthorizons.core.util.ExceptionUtil;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhChunkPos;
@@ -43,7 +45,9 @@ public final class GenerationEvent
/** can be used for troubleshooting */ /** can be used for troubleshooting */
public final int id; public final int id;
#if MC_VER > MC_1_12_2
public final ThreadWorldGenParams threadedParam; public final ThreadWorldGenParams threadedParam;
#endif
public final DhChunkPos minPos; public final DhChunkPos minPos;
public final int widthInChunks; public final int widthInChunks;
public final EDhApiWorldGenerationStep targetGenerationStep; public final EDhApiWorldGenerationStep targetGenerationStep;
@@ -67,7 +71,9 @@ public final class GenerationEvent
this.widthInChunks = widthInChunks; this.widthInChunks = widthInChunks;
this.targetGenerationStep = targetGenerationStep; this.targetGenerationStep = targetGenerationStep;
this.generatorMode = generatorMode; this.generatorMode = generatorMode;
#if MC_VER > MC_1_12_2
this.threadedParam = ThreadWorldGenParams.getOrMake(generationGroup.globalParams); this.threadedParam = ThreadWorldGenParams.getOrMake(generationGroup.globalParams);
#endif
this.future = new CompletableFuture<>(); this.future = new CompletableFuture<>();
this.resultConsumer = resultConsumer; this.resultConsumer = resultConsumer;
} }
@@ -168,4 +174,4 @@ public final class GenerationEvent
} }
@@ -15,6 +15,7 @@ import com.seibel.distanthorizons.core.generation.DhLightingEngine;
import com.seibel.distanthorizons.core.level.IDhServerLevel; import com.seibel.distanthorizons.core.level.IDhServerLevel;
import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.util.ExceptionUtil; import com.seibel.distanthorizons.core.util.ExceptionUtil;
import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.TimerUtil; import com.seibel.distanthorizons.core.util.TimerUtil;
@@ -23,14 +24,23 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IC2meAccess
import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.ModInfo;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
#if MC_VER <= MC_1_12_2
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.gen.ChunkProviderServer;
import net.minecraftforge.common.ForgeChunkManager;
#else
import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.TicketType; import net.minecraft.server.level.TicketType;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
#endif
#if MC_VER <= MC_1_20_4 #if MC_VER <= MC_1_12_2
#elif MC_VER <= MC_1_20_4
import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.ChunkStatus;
#else #else
import net.minecraft.world.level.chunk.status.ChunkStatus; import net.minecraft.world.level.chunk.status.ChunkStatus;
@@ -64,7 +74,8 @@ public class InternalServerGenerator
*/ */
private static final int MS_TO_IGNORE_CHUNK_AFTER_COMPLETION = 5_000; private static final int MS_TO_IGNORE_CHUNK_AFTER_COMPLETION = 5_000;
#if MC_VER < MC_1_21_5 #if MC_VER <= MC_1_12_2
#elif MC_VER < MC_1_21_5
private static final TicketType<ChunkPos> DH_SERVER_GEN_TICKET = TicketType.create("dh_server_gen_ticket", Comparator.comparingLong(ChunkPos::toLong)); private static final TicketType<ChunkPos> DH_SERVER_GEN_TICKET = TicketType.create("dh_server_gen_ticket", Comparator.comparingLong(ChunkPos::toLong));
#elif MC_VER < MC_1_21_9 #elif MC_VER < MC_1_21_9
private static final TicketType DH_SERVER_GEN_TICKET = new TicketType(/* timeout, 0 = disabled*/0L, /* persist */ false, TicketType.TicketUse.LOADING); private static final TicketType DH_SERVER_GEN_TICKET = new TicketType(/* timeout, 0 = disabled*/0L, /* persist */ false, TicketType.TicketUse.LOADING);
@@ -110,14 +121,25 @@ public class InternalServerGenerator
// create gen requests // // create gen requests //
//=====================// //=====================//
#if MC_VER <= MC_1_12_2
ArrayList<CompletableFuture<Chunk>> getChunkFutureList = new ArrayList<>();
#else
ArrayList<CompletableFuture<ChunkAccess>> getChunkFutureList = new ArrayList<>(); ArrayList<CompletableFuture<ChunkAccess>> getChunkFutureList = new ArrayList<>();
#endif
{ {
Iterator<ChunkPos> chunkPosIterator = ChunkPosGenStream.getIterator(genEvent.minPos.getX(), genEvent.minPos.getZ(), genEvent.widthInChunks, 0); Iterator<ChunkPos> chunkPosIterator = ChunkPosGenStream.getIterator(genEvent.minPos.getX(), genEvent.minPos.getZ(), genEvent.widthInChunks, 0);
while (chunkPosIterator.hasNext()) while (chunkPosIterator.hasNext())
{ {
ChunkPos chunkPos = chunkPosIterator.next(); ChunkPos chunkPos = chunkPosIterator.next();
CompletableFuture<ChunkAccess> requestChunkFuture = #if MC_VER <= MC_1_12_2
CompletableFuture<Chunk> requestChunkFuture;
#else
CompletableFuture<ChunkAccess> requestChunkFuture;
#endif
requestChunkFuture =
this.requestChunkFromServerAsync(chunkPos) this.requestChunkFromServerAsync(chunkPos)
// log errors if necessary // log errors if necessary
.whenCompleteAsync( .whenCompleteAsync(
@@ -160,8 +182,16 @@ public class InternalServerGenerator
ArrayList<IChunkWrapper> chunkWrappers = new ArrayList<>(); ArrayList<IChunkWrapper> chunkWrappers = new ArrayList<>();
for (int i = 0; i < getChunkFutureList.size(); i++) for (int i = 0; i < getChunkFutureList.size(); i++)
{ {
CompletableFuture<ChunkAccess> getChunkFuture = getChunkFutureList.get(i); #if MC_VER <= MC_1_12_2
ChunkAccess chunk = getChunkFuture.join(); CompletableFuture<Chunk> getChunkFuture;
Chunk chunk;
#else
CompletableFuture<ChunkAccess> getChunkFuture;
ChunkAccess chunk;
#endif
getChunkFuture = getChunkFutureList.get(i);
chunk = getChunkFuture.join();
if (chunk != null) if (chunk != null)
{ {
ChunkWrapper chunkWrapper = new ChunkWrapper(chunk, this.dhServerLevel.getLevelWrapper()); ChunkWrapper chunkWrapper = new ChunkWrapper(chunk, this.dhServerLevel.getLevelWrapper());
@@ -245,8 +275,47 @@ public class InternalServerGenerator
LOGGER.warn(c2meWarning); LOGGER.warn(c2meWarning);
} }
} }
#if MC_VER <= MC_1_12_2
private CompletableFuture<Chunk> requestChunkFromServerAsync(ChunkPos chunkPos)
#else
private CompletableFuture<ChunkAccess> requestChunkFromServerAsync(ChunkPos chunkPos) private CompletableFuture<ChunkAccess> requestChunkFromServerAsync(ChunkPos chunkPos)
#endif
{ {
#if MC_VER <= MC_1_12_2
WorldServer level = this.params.mcServerLevel;
// ignore chunk update events for this position
if (this.updateManager != null)
{
this.updateManager.addPosToIgnore(McObjectConverter.Convert(chunkPos));
}
CompletableFuture<Chunk> future = new CompletableFuture<>();
level.getMinecraftServer().addScheduledTask(() ->
{
ChunkProviderServer provider = level.getChunkProvider();
// load neighbors first so the target chunk can fully populate
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
if (i != 0 || j != 0)
{
if (this.updateManager != null)
{
this.updateManager.addPosToIgnore(new DhChunkPos(chunkPos.x + i, chunkPos.z + j));
}
provider.provideChunk(chunkPos.x + i, chunkPos.z + j);
}
}
}
Chunk chunk = provider.provideChunk(chunkPos.x, chunkPos.z);
future.complete(chunk);
});
return future;
#else
return CompletableFuture.supplyAsync(() -> return CompletableFuture.supplyAsync(() ->
{ {
ServerLevel level = this.params.mcServerLevel; ServerLevel level = this.params.mcServerLevel;
@@ -289,27 +358,65 @@ public class InternalServerGenerator
}, this.params.mcServerLevel.getChunkSource().chunkMap.mainThreadExecutor) }, this.params.mcServerLevel.getChunkSource().chunkMap.mainThreadExecutor)
.thenCompose(Function.identity()); .thenCompose(Function.identity());
#endif
} }
/** /**
* mitigates out of memory issues in the vanilla chunk system. <br> * mitigates out of memory issues in the vanilla chunk system. <br>
* See: https://github.com/pop4959/Chunky/pull/383 * See: https://github.com/pop4959/Chunky/pull/383
*/ */
#if MC_VER <= MC_1_12_2
private CompletableFuture<Void> releaseChunkFromServerAsync(WorldServer level, ChunkPos chunkPos)
#else
private CompletableFuture<Void> releaseChunkFromServerAsync(ServerLevel level, ChunkPos chunkPos) private CompletableFuture<Void> releaseChunkFromServerAsync(ServerLevel level, ChunkPos chunkPos)
#endif
{ {
CompletableFuture<Void> removeTicketFuture = new CompletableFuture<>(); CompletableFuture<Void> removeTicketFuture = new CompletableFuture<>();
#if MC_VER <= MC_1_12_2
level.getMinecraftServer().addScheduledTask(() ->
#else
level.getChunkSource().chunkMap.mainThreadExecutor.execute(() -> level.getChunkSource().chunkMap.mainThreadExecutor.execute(() ->
#endif
{ {
try try
{ {
#if MC_VER < MC_1_21_5 #if MC_VER <= MC_1_12_2
for (int difX = -1; difX <= 1; difX++)
{
for (int difZ = -1; difZ <= 1; difZ++)
{
if (difX != 0 || difZ != 0)
{
final int finalDifX = difX;
final int finalDifZ = difZ;
this.chunkSaveIgnoreTimer.schedule(new TimerTask()
{
@Override
public void run()
{
if (InternalServerGenerator.this.updateManager != null)
{
InternalServerGenerator.this.updateManager.removePosToIgnore(
new DhChunkPos(
chunkPos.x + finalDifX,
chunkPos.z + finalDifZ
)
);
}
}
}, MS_TO_IGNORE_CHUNK_AFTER_COMPLETION);
}
}
}
#elif MC_VER < MC_1_21_5
int chunkLevel = 33; // 33 is equivalent to FULL Chunk int chunkLevel = 33; // 33 is equivalent to FULL Chunk
level.getChunkSource().distanceManager.removeTicket(DH_SERVER_GEN_TICKET, chunkPos, chunkLevel, chunkPos); level.getChunkSource().distanceManager.removeTicket(DH_SERVER_GEN_TICKET, chunkPos, chunkLevel, chunkPos);
#else #else
level.getChunkSource().removeTicketWithRadius(DH_SERVER_GEN_TICKET, chunkPos, 0); level.getChunkSource().removeTicketWithRadius(DH_SERVER_GEN_TICKET, chunkPos, 0);
#endif #endif
#if MC_VER > MC_1_12_2
level.getChunkSource().chunkMap.tick(() -> false); level.getChunkSource().chunkMap.tick(() -> false);
#endif
#if MC_VER > MC_1_16_5 #if MC_VER > MC_1_16_5
level.entityManager.tick(); level.entityManager.tick();
@@ -340,7 +447,6 @@ public class InternalServerGenerator
removeTicketFuture.complete(null); removeTicketFuture.complete(null);
} }
}); });
return removeTicketFuture; return removeTicketFuture;
} }
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling; package com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling;
#if MC_VER > MC_1_12_2
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.seibel.distanthorizons.common.wrappers.McObjectConverter; import com.seibel.distanthorizons.common.wrappers.McObjectConverter;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
@@ -749,3 +750,4 @@ public class ChunkCompoundTagParser
} }
#endif
@@ -1,5 +1,6 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling; package com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling;
#if MC_VER > MC_1_12_2
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.GlobalWorldGenParams; import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.GlobalWorldGenParams;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.RegionFileStorageExternalCache; import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.RegionFileStorageExternalCache;
@@ -341,3 +342,4 @@ public class ChunkFileReader implements AutoCloseable
} }
#endif
@@ -1,5 +1,6 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling; package com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling;
#if MC_VER > MC_1_12_2
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -146,3 +147,4 @@ public class CompoundTagUtil
} }
#endif
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject; package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
#if MC_VER > MC_1_12_2
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.util.List; import java.util.List;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@@ -488,4 +489,5 @@ public class DhLitWorldGenRegion extends WorldGenRegion
return (k / j & 0xFF) << 16 | (l / j & 0xFF) << 8 | m / j & 0xFF; return (k / j & 0xFF) << 16 | (l / j & 0xFF) << 8 | m / j & 0xFF;
} }
} }
#endif
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject; package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
#if MC_VER > MC_1_12_2
import net.minecraft.world.level.lighting.*; import net.minecraft.world.level.lighting.*;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -96,4 +97,5 @@ public class DummyLightEngine extends LevelLightEngine
public int getMaxLightSection() { throw new UnsupportedOperationException("This should never be used!"); } public int getMaxLightSection() { throw new UnsupportedOperationException("This should never be used!"); }
#endif #endif
} }
#endif
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject; package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
#if MC_VER > MC_1_12_2
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector; import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IStarlightAccessor; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IStarlightAccessor;
@@ -79,4 +80,5 @@ public class LightGetterAdaptor implements LightChunkGetter
return heightGetter; return heightGetter;
} }
#endif #endif
} }
#endif
@@ -1,5 +1,6 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject; package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
#if MC_VER > MC_1_12_2
import com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling.ChunkFileReader; import com.seibel.distanthorizons.common.wrappers.worldGeneration.chunkFileHandling.ChunkFileReader;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
@@ -250,3 +251,4 @@ public class RegionFileStorageExternalCache implements AutoCloseable
} }
} }
#endif
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject; package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
#if MC_VER > MC_1_12_2
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -277,3 +278,4 @@ public class WorldGenStructFeatManager extends #if MC_VER < MC_1_19_2 StructureF
#endif #endif
#endif #endif
} }
#endif
@@ -19,10 +19,20 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.params; package com.seibel.distanthorizons.common.wrappers.worldGeneration.params;
import com.mojang.datafixers.DataFixer;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper; import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.core.level.IDhServerLevel; import com.seibel.distanthorizons.core.level.IDhServerLevel;
#if MC_VER <= MC_1_12_2
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.WorldServer;
import net.minecraft.world.gen.IChunkGenerator;
import java.util.concurrent.CompletableFuture;
#else
import com.mojang.datafixers.DataFixer;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess; import net.minecraft.core.RegistryAccess;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
@@ -56,30 +66,46 @@ import net.minecraft.world.level.levelgen.WorldGenSettings;
#else #else
import net.minecraft.world.level.levelgen.WorldOptions; import net.minecraft.world.level.levelgen.WorldOptions;
#endif #endif
#endif
#if MC_VER > MC_1_12_2
/** /**
* Handles parameters that are relevant for the entire MC world. * Handles parameters that are relevant for the entire MC world.
* *
* @see ThreadWorldGenParams * @see ThreadWorldGenParams
*/ */
#endif
public final class GlobalWorldGenParams public final class GlobalWorldGenParams
{ {
public final ChunkGenerator generator;
public final IDhServerLevel dhServerLevel; public final IDhServerLevel dhServerLevel;
#if MC_VER <= MC_1_12_2
public final IChunkGenerator generator;
public final WorldServer mcServerLevel;
#else
public final ChunkGenerator generator;
public final ServerLevel mcServerLevel; public final ServerLevel mcServerLevel;
#endif
#if MC_VER > MC_1_12_2
public final Registry<Biome> biomes; public final Registry<Biome> biomes;
public final RegistryAccess registry; public final RegistryAccess registry;
#endif
public final long worldSeed; public final long worldSeed;
public final DataFixer dataFixer; public final DataFixer dataFixer;
#if MC_VER < MC_1_19_2 #if MC_VER <= MC_1_12_2
#elif MC_VER < MC_1_19_2
public final StructureManager structures; public final StructureManager structures;
#else #else
public final StructureTemplateManager structures; public final StructureTemplateManager structures;
public final RandomState randomState; public final RandomState randomState;
#endif #endif
#if MC_VER < MC_1_19_4 #if MC_VER <= MC_1_12_2
#elif MC_VER < MC_1_19_4
public final WorldGenSettings worldGenSettings; public final WorldGenSettings worldGenSettings;
#else #else
public final WorldOptions worldOptions; public final WorldOptions worldOptions;
@@ -99,13 +125,22 @@ public final class GlobalWorldGenParams
public GlobalWorldGenParams(IDhServerLevel dhServerLevel) public GlobalWorldGenParams(IDhServerLevel dhServerLevel)
{ {
this.dhServerLevel = dhServerLevel; this.dhServerLevel = dhServerLevel;
this.mcServerLevel = ((ServerLevelWrapper) dhServerLevel.getServerLevelWrapper()).getWrappedMcObject(); this.mcServerLevel = ((ServerLevelWrapper) dhServerLevel.getServerLevelWrapper()).getWrappedMcObject();
#if MC_VER <= MC_1_12_2
MinecraftServer server = this.mcServerLevel.getMinecraftServer();
#else
MinecraftServer server = this.mcServerLevel.getServer(); MinecraftServer server = this.mcServerLevel.getServer();
#endif
#if MC_VER > MC_1_12_2
WorldData worldData = server.getWorldData(); WorldData worldData = server.getWorldData();
this.registry = server.registryAccess(); this.registry = server.registryAccess();
#endif
#if MC_VER < MC_1_19_4 #if MC_VER <= MC_1_12_2
this.worldSeed = mcServerLevel.getSeed();
#elif MC_VER < MC_1_19_4
this.worldGenSettings = worldData.worldGenSettings(); this.worldGenSettings = worldData.worldGenSettings();
this.biomes = registry.registryOrThrow(Registry.BIOME_REGISTRY); this.biomes = registry.registryOrThrow(Registry.BIOME_REGISTRY);
this.worldSeed = worldGenSettings.seed(); this.worldSeed = worldGenSettings.seed();
@@ -123,15 +158,24 @@ public final class GlobalWorldGenParams
this.worldSeed = this.worldOptions.seed(); this.worldSeed = this.worldOptions.seed();
#endif #endif
#if MC_VER >= MC_1_18_2 #if MC_VER >= MC_1_18_2
this.biomeManager = new BiomeManager(this.mcServerLevel, BiomeManager.obfuscateSeed(this.worldSeed)); this.biomeManager = new BiomeManager(this.mcServerLevel, BiomeManager.obfuscateSeed(this.worldSeed));
this.chunkScanner = this.mcServerLevel.getChunkSource().chunkScanner(); this.chunkScanner = this.mcServerLevel.getChunkSource().chunkScanner();
#endif #endif
#if MC_VER <= MC_1_12_2
this.generator = this.mcServerLevel.getChunkProvider().chunkGenerator;
#else
this.structures = server.getStructureManager(); this.structures = server.getStructureManager();
this.generator = this.mcServerLevel.getChunkSource().getGenerator(); this.generator = this.mcServerLevel.getChunkSource().getGenerator();
this.dataFixer = server.getFixerUpper(); #endif
#if MC_VER <= MC_1_12_2
this.dataFixer = server != null ? server.getDataFixer() : null;
#else
this.dataFixer = server.getFixerUpper();
#endif
#if MC_VER >= MC_1_19_2 #if MC_VER >= MC_1_19_2
this.randomState = this.mcServerLevel.getChunkSource().randomState(); this.randomState = this.mcServerLevel.getChunkSource().randomState();
#endif #endif
@@ -20,6 +20,7 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.params; package com.seibel.distanthorizons.common.wrappers.worldGeneration.params;
#if MC_VER > MC_1_12_2
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.WorldGenStructFeatManager; import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.WorldGenStructFeatManager;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
@@ -118,4 +119,5 @@ public final class ThreadWorldGenParams
} }
#endif
@@ -1,5 +1,6 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step; package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
#if MC_VER > MC_1_12_2
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.ThreadWorldGenParams; import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.ThreadWorldGenParams;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion; import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
@@ -52,3 +53,4 @@ public abstract class AbstractWorldGenStep
} }
#endif
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step; package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
#if MC_VER > MC_1_12_2
import java.util.ArrayList; import java.util.ArrayList;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
@@ -114,4 +115,5 @@ public final class StepBiomes extends AbstractWorldGenStep
} }
} }
} }
#endif
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step; package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
#if MC_VER > MC_1_12_2
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment; import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.ThreadWorldGenParams; import com.seibel.distanthorizons.common.wrappers.worldGeneration.params.ThreadWorldGenParams;
@@ -118,4 +119,5 @@ public final class StepFeatures extends AbstractWorldGenStep
} }
} }
} }
#endif
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step; package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
#if MC_VER > MC_1_12_2
import java.util.ArrayList; import java.util.ArrayList;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
@@ -106,4 +107,5 @@ public final class StepNoise extends AbstractWorldGenStep
} }
} }
} }
#endif
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step; package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
#if MC_VER > MC_1_12_2
import java.util.ArrayList; import java.util.ArrayList;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
@@ -72,4 +73,5 @@ public final class StepStructureReference extends AbstractWorldGenStep
} }
} }
} }
#endif
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step; package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
#if MC_VER > MC_1_12_2
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@@ -142,4 +143,5 @@ public final class StepStructureStart extends AbstractWorldGenStep
} }
} }
} }
#endif
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.step; package com.seibel.distanthorizons.common.wrappers.worldGeneration.step;
#if MC_VER > MC_1_12_2
import java.util.ArrayList; import java.util.ArrayList;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper; import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
@@ -81,4 +82,5 @@ public final class StepSurface extends AbstractWorldGenStep
} }
#endif
@@ -0,0 +1,3 @@
public net.minecraft.client.renderer.EntityRenderer getFOVModifier(FZ)F
public net.minecraft.client.renderer.ActiveRenderInfo MODELVIEW
public net.minecraft.client.renderer.ActiveRenderInfo PROJECTION
+1 -22
View File
@@ -43,28 +43,7 @@ dependencies {
addMod("com.github.quiqueck:BCLib:${rootProject.bclib_version}", rootProject.enable_bclib) addMod("com.github.quiqueck:BCLib:${rootProject.bclib_version}", rootProject.enable_bclib)
// Canvas // Canvas
addMod("io.vram:canvas-fabric-${rootProject.canvas_version}", rootProject.enable_canvas) addMod("io.vram:canvas-fabric-${project.canvas_version}", rootProject.enable_canvas)
// Immersive Portals
if (rootProject.enable_immersive_portals == "1") {
modCompileOnly("com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:${rootProject.immersive_portals_version}")
}
else if (rootProject.enable_immersive_portals == "2") {
modImplementation ("com.github.iPortalTeam.ImmersivePortalsMod:imm_ptl_core:${rootProject.immersive_portals_version}") {
exclude(group: "net.fabricmc.fabric-api")
transitive(false)
}
modImplementation("com.github.iPortalTeam.ImmersivePortalsMod:q_misc_util:${rootProject.immersive_portals_version}") {
exclude(group: "net.fabricmc.fabric-api")
transitive(false)
}
modImplementation("com.github.iPortalTeam.ImmersivePortalsMod:build:${rootProject.immersive_portals_version}") {
exclude(group: "net.fabricmc.fabric-api")
transitive(false)
}
api("com.github.LlamaLad7:MixinExtras:0.2.0-beta.4")
annotationProcessor("com.github.LlamaLad7:MixinExtras:0.2.0-beta.4")
}
} }
@@ -116,6 +116,7 @@ public class FabricMain extends AbstractModInitializer implements ClientModIniti
this.tryCreateModCompatAccessor("optifine", IOptifineAccessor.class, OptifineAccessor::new); this.tryCreateModCompatAccessor("optifine", IOptifineAccessor.class, OptifineAccessor::new);
this.tryCreateModCompatAccessor("bclib", IBCLibAccessor.class, BCLibAccessor::new); this.tryCreateModCompatAccessor("bclib", IBCLibAccessor.class, BCLibAccessor::new);
this.tryCreateModCompatAccessor("c2me", IC2meAccessor.class, C2meAccessor::new); this.tryCreateModCompatAccessor("c2me", IC2meAccessor.class, C2meAccessor::new);
this.tryCreateModCompatAccessor("imm_ptl_core", IImmersivePortalsAccessor.class, ImmersivePortalsAccessorFabric::new);
#if MC_VER >= MC_1_19_4 #if MC_VER >= MC_1_19_4
// 1.19.4 is the lowest version Iris supports DH // 1.19.4 is the lowest version Iris supports DH
this.tryCreateModCompatAccessor("iris", IIrisAccessor.class, IrisAccessor::new); this.tryCreateModCompatAccessor("iris", IIrisAccessor.class, IrisAccessor::new);
@@ -0,0 +1,76 @@
/*
* 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_19_2
import com.mojang.math.Matrix4f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(Matrix4f.class)
public interface AccessorMatrix4f
{
@Accessor("m00")
void setM00(float v);
@Accessor("m01")
void setM01(float v);
@Accessor("m02")
void setM02(float v);
@Accessor("m03")
void setM03(float v);
@Accessor("m10")
void setM10(float v);
@Accessor("m11")
void setM11(float v);
@Accessor("m12")
void setM12(float v);
@Accessor("m13")
void setM13(float v);
@Accessor("m20")
void setM20(float v);
@Accessor("m21")
void setM21(float v);
@Accessor("m22")
void setM22(float v);
@Accessor("m23")
void setM23(float v);
@Accessor("m30")
void setM30(float v);
@Accessor("m31")
void setM31(float v);
@Accessor("m32")
void setM32(float v);
@Accessor("m33")
void setM33(float v);
}
#else
import net.minecraft.world.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(Entity.class)
public interface AccessorMatrix4f
{ /* not present in newer MC versions */ }
#endif

Some files were not shown because too many files have changed in this diff Show More