diff --git a/.github/workflows/build-commit.yml b/.github/workflows/build-commit.yml index 80f3152c9d..7ac5e33f8a 100644 --- a/.github/workflows/build-commit.yml +++ b/.github/workflows/build-commit.yml @@ -35,7 +35,9 @@ jobs: run: ./gradlew build - name: Upload artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: sodium-artifacts-${{ steps.ref.outputs.branch }} - path: build/libs/*.jar \ No newline at end of file + path: | + neoforge/build/libs/*.jar + fabric/build/libs/*.jar diff --git a/.gitignore b/.gitignore index 01ca5bc812..69cd50978c 100644 --- a/.gitignore +++ b/.gitignore @@ -23,7 +23,7 @@ bin/ # fabric run/ - +neoforge/runs # macOS .DS_Store diff --git a/README.md b/README.md index ee4676b337..4d5c52fb8a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ - + -# Sodium (for Fabric) +# Sodium Sodium is a powerful rendering engine and optimization mod for the Minecraft client which improves frame rates and reduces micro-stutter, while fixing many graphical issues in Minecraft. diff --git a/build.gradle.kts b/build.gradle.kts index 6c4f79e62d..0fe9eeaf56 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,145 +1,75 @@ -object Constants { - // https://fabricmc.net/develop/ - const val MINECRAFT_VERSION: String = "1.21" - const val FABRIC_LOADER_VERSION: String = "0.16.0" - const val FABRIC_API_VERSION: String = "0.100.7+1.21" - - // https://semver.org/ - const val MOD_VERSION: String = "0.6.0" -} - plugins { - // Unlike most projects, we choose to pin the specific version of Loom. - // This prevents a lot of issues where the build script can fail randomly because the Fabric Maven server - // is not reachable for some reason, and it makes builds much more reproducible. Observation also shows that it - // really helps to improve startup times on slow connections. - id("fabric-loom") version "1.7.2" + id("java") + id("fabric-loom") version ("1.7.3") apply (false) } -base { - archivesName = "sodium-fabric" +val MINECRAFT_VERSION by extra { "1.21" } +val NEOFORGE_VERSION by extra { "21.0.147" } +val FABRIC_LOADER_VERSION by extra { "0.16.0" } +val FABRIC_API_VERSION by extra { "0.100.4+1.21" } - group = "net.caffeinemc.mods" - version = createVersionString() -} +// This value can be set to null to disable Parchment. +val PARCHMENT_VERSION by extra { "2024.07.28" } -loom { - mixin { - defaultRefmapName = "sodium.refmap.json" - } +// https://semver.org/ +val MOD_VERSION by extra { "0.6.0" } - accessWidenerPath = file("src/main/resources/sodium.accesswidener") +allprojects { + apply(plugin = "java") + apply(plugin = "maven-publish") } -java { - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 +tasks.withType { + options.encoding = "UTF-8" } -sourceSets { - val main = getByName("main") - val api = create("api") - val desktop = create("desktop") +subprojects { + apply(plugin = "maven-publish") - api.apply { - java { - compileClasspath += main.compileClasspath - } - } + java.toolchain.languageVersion = JavaLanguageVersion.of(21) - desktop.apply { - java { - srcDir("src/desktop/java") - } - } - main.apply { - java { - compileClasspath += api.output - runtimeClasspath += api.output - } - } -} + fun createVersionString(): String { + val builder = StringBuilder() -dependencies { - minecraft(group = "com.mojang", name = "minecraft", version = Constants.MINECRAFT_VERSION) - mappings(loom.officialMojangMappings()) - modImplementation(group = "net.fabricmc", name = "fabric-loader", version = Constants.FABRIC_LOADER_VERSION) - include(implementation(group = "com.lodborg", name = "interval-tree", version = "1.0.0")) - - fun addEmbeddedFabricModule(name: String) { - val module = fabricApi.module(name, Constants.FABRIC_API_VERSION) - modImplementation(module) - include(module) - } - - // Fabric API modules - addEmbeddedFabricModule("fabric-api-base") - addEmbeddedFabricModule("fabric-block-view-api-v2") - addEmbeddedFabricModule("fabric-renderer-api-v1") - addEmbeddedFabricModule("fabric-rendering-data-attachment-v1") - addEmbeddedFabricModule("fabric-rendering-fluids-v1") - addEmbeddedFabricModule("fabric-resource-loader-v0") -} + val isReleaseBuild = project.hasProperty("build.release") + val buildId = System.getenv("GITHUB_RUN_NUMBER") -tasks { - getByName("compileDesktopJava") { - sourceCompatibility = JavaVersion.VERSION_1_8.toString() - targetCompatibility = JavaVersion.VERSION_1_8.toString() - } - - jar { - from("${rootProject.projectDir}/LICENSE.md") + if (isReleaseBuild) { + builder.append(MOD_VERSION) + } else { + builder.append(MOD_VERSION.substringBefore('-')) + builder.append("-snapshot") + } - val api = sourceSets.getByName("api") - from(api.output.classesDirs) - from(api.output.resourcesDir) + builder.append("+mc").append(MINECRAFT_VERSION) - val desktop = sourceSets.getByName("desktop") - from(desktop.output.classesDirs) - from(desktop.output.resourcesDir) + if (!isReleaseBuild) { + if (buildId != null) { + builder.append("-build.${buildId}") + } else { + builder.append("-local") + } + } - manifest.attributes["Main-Class"] = "net.caffeinemc.mods.sodium.desktop.LaunchWarn" + return builder.toString() } - processResources { - inputs.property("version", project.version) - - filesMatching("fabric.mod.json") { - expand(mapOf("version" to project.version)) + tasks.processResources { + filesMatching("META-INF/neoforge.mods.toml") { + expand(mapOf("version" to createVersionString())) } } -} - -// ensure that the encoding is set to UTF-8, no matter what the system default is -// this fixes some edge cases with special characters not displaying correctly -// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html -tasks.withType { - options.encoding = "UTF-8" -} - -fun createVersionString(): String { - val builder = StringBuilder() - val isReleaseBuild = project.hasProperty("build.release") - val buildId = System.getenv("GITHUB_RUN_NUMBER") + version = createVersionString() + group = "net.caffeinemc.mods" - if (isReleaseBuild) { - builder.append(Constants.MOD_VERSION) - } else { - builder.append(Constants.MOD_VERSION.substringBefore('-')) - builder.append("-snapshot") + tasks.withType { + options.encoding = "UTF-8" + options.release.set(21) } - builder.append("+mc").append(Constants.MINECRAFT_VERSION) - - if (!isReleaseBuild) { - if (buildId != null) { - builder.append("-build.${buildId}") - } else { - builder.append("-local") - } + tasks.withType().configureEach { + enabled = false } - - return builder.toString() } diff --git a/common/build.gradle.kts b/common/build.gradle.kts new file mode 100644 index 0000000000..f840ba1291 --- /dev/null +++ b/common/build.gradle.kts @@ -0,0 +1,119 @@ +plugins { + id("java") + id("idea") + id("fabric-loom") version ("1.7.3") +} + +repositories { + maven("https://maven.parchmentmc.org/") +} + +val MINECRAFT_VERSION: String by rootProject.extra +val PARCHMENT_VERSION: String? by rootProject.extra +val FABRIC_LOADER_VERSION: String by rootProject.extra +val FABRIC_API_VERSION: String by rootProject.extra + +dependencies { + minecraft(group = "com.mojang", name = "minecraft", version = MINECRAFT_VERSION) + mappings(loom.layered() { + officialMojangMappings() + if (PARCHMENT_VERSION != null) { + parchment("org.parchmentmc.data:parchment-${MINECRAFT_VERSION}:${PARCHMENT_VERSION}@zip") + } + }) + compileOnly("io.github.llamalad7:mixinextras-common:0.3.5") + annotationProcessor("io.github.llamalad7:mixinextras-common:0.3.5") + compileOnly("net.fabricmc:sponge-mixin:0.13.2+mixin.0.8.5") + + fun addDependentFabricModule(name: String) { + val module = fabricApi.module(name, FABRIC_API_VERSION) + modCompileOnly(module) + } + + addDependentFabricModule("fabric-api-base") + addDependentFabricModule("fabric-block-view-api-v2") + addDependentFabricModule("fabric-renderer-api-v1") + addDependentFabricModule("fabric-rendering-data-attachment-v1") + + modCompileOnly("net.fabricmc.fabric-api:fabric-renderer-api-v1:3.2.9+1172e897d7") + implementation(group = "com.lodborg", name = "interval-tree", version = "1.0.0") +} + +sourceSets { + val main = getByName("main") + val api = create("api") + val workarounds = create("workarounds") + val desktop = create("desktop") + + api.apply { + java { + compileClasspath += main.compileClasspath + } + } + + workarounds.apply { + java { + compileClasspath += main.compileClasspath + } + } + + desktop.apply { + java { + srcDir("src/desktop/java") + } + } + + main.apply { + java { + compileClasspath += api.output + compileClasspath += workarounds.output + runtimeClasspath += api.output + } + } +} + +loom { + mixin { + defaultRefmapName = "sodium.refmap.json" + } + + accessWidenerPath = file("src/main/resources/sodium.accesswidener") + + mods { + val main by creating { // to match the default mod generated for Forge + sourceSet("api") + sourceSet("desktop") + sourceSet("main") + } + } +} + +tasks { + getByName("compileDesktopJava") { + sourceCompatibility = JavaVersion.VERSION_1_8.toString() + targetCompatibility = JavaVersion.VERSION_1_8.toString() + } + + jar { + from(rootDir.resolve("LICENSE.md")) + + val api = sourceSets.getByName("api") + from(api.output.classesDirs) + from(api.output.resourcesDir) + + val workarounds = sourceSets.getByName("workarounds") + from(workarounds.output.classesDirs) + from(workarounds.output.resourcesDir) + + val desktop = sourceSets.getByName("desktop") + from(desktop.output.classesDirs) + from(desktop.output.resourcesDir) + + manifest.attributes["Main-Class"] = "net.caffeinemc.mods.sodium.desktop.LaunchWarn" + } +} + +// This trick hides common tasks in the IDEA list. +tasks.configureEach { + group = null +} \ No newline at end of file diff --git a/src/.gitignore b/common/src/.gitignore similarity index 100% rename from src/.gitignore rename to common/src/.gitignore diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/internal/DependencyInjection.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/internal/DependencyInjection.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/internal/DependencyInjection.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/internal/DependencyInjection.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/internal/package-info.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/internal/package-info.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/internal/package-info.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/internal/package-info.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/math/MatrixHelper.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/math/MatrixHelper.java similarity index 87% rename from src/api/java/net/caffeinemc/mods/sodium/api/math/MatrixHelper.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/math/MatrixHelper.java index 29dbb8afdc..12df8a23b8 100644 --- a/src/api/java/net/caffeinemc/mods/sodium/api/math/MatrixHelper.java +++ b/common/src/api/java/net/caffeinemc/mods/sodium/api/math/MatrixHelper.java @@ -17,17 +17,26 @@ public class MatrixHelper { /** * @param mat The transformation matrix to apply to the normal + * @param skipNormalization Whether normalizing the vector is unnecessary * @param x The X-coordinate of the normal vector * @param y The Y-coordinate of the normal vector * @param z The Z-coordinate of the normal vector * @return The transformed normal vector (in packed format) */ - public static int transformNormal(Matrix3f mat, float x, float y, float z) { + public static int transformNormal(Matrix3f mat, boolean skipNormalization, float x, float y, float z) { // The transformed normal vector float nxt = transformNormalX(mat, x, y, z); float nyt = transformNormalY(mat, x, y, z); float nzt = transformNormalZ(mat, x, y, z); + if (!skipNormalization) { + float scalar = Math.invsqrt(Math.fma(nxt, nxt, Math.fma(nyt, nyt, nzt * nzt))); + + nxt *= scalar; + nyt *= scalar; + nzt *= scalar; + } + return NormI8.pack(nxt, nyt, nzt); } @@ -36,13 +45,13 @@ public static int transformNormal(Matrix3f mat, float x, float y, float z) { * @param norm The normal vector to transform (in packed format) * @return The transformed normal vector (in packed format) */ - public static int transformNormal(Matrix3f mat, int norm) { + public static int transformNormal(Matrix3f mat, boolean skipNormalization, int norm) { // The unpacked normal vector float x = NormI8.unpackX(norm); float y = NormI8.unpackY(norm); float z = NormI8.unpackZ(norm); - return transformNormal(mat, x, y, z); + return transformNormal(mat, skipNormalization, x, y, z); } /** @@ -129,6 +138,15 @@ public static void rotateZYX(PoseStack.Pose matrices, float angleZ, float angleY .rotateZYX(angleZ, angleY, angleX); } + /** + * Returns the transformed normal vector for a given unit vector (direction). This is significantly faster + * than transforming the vector directly (i.e. with {@link Matrix3f#transform(Vector3f)}), as it can simply + * extract the values from the provided matrix (rather than transforming the vertices.) + * + * @param matrix The transformation matrix + * @param direction The unit vector (direction) to use + * @return A transformed normal in packed format + */ /** * Returns the transformed normal vector for a given unit vector (direction). This is significantly faster * than transforming the vector directly (i.e. with {@link Matrix3f#transform(Vector3f)}), as it can simply diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/memory/MemoryIntrinsics.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/memory/MemoryIntrinsics.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/memory/MemoryIntrinsics.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/memory/MemoryIntrinsics.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/util/ColorABGR.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/util/ColorABGR.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/util/ColorABGR.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/util/ColorABGR.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/util/ColorARGB.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/util/ColorARGB.java similarity index 93% rename from src/api/java/net/caffeinemc/mods/sodium/api/util/ColorARGB.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/util/ColorARGB.java index d4a48cac2a..f93880555e 100644 --- a/src/api/java/net/caffeinemc/mods/sodium/api/util/ColorARGB.java +++ b/common/src/api/java/net/caffeinemc/mods/sodium/api/util/ColorARGB.java @@ -72,6 +72,13 @@ public static int unpackBlue(int color) { return color >> BLUE_COMPONENT_OFFSET & COMPONENT_MASK; } + /** + * Re-packs the ARGB color into an ABGR color with the specified alpha component. + */ + public static int toABGR(int color, float alpha) { + return Integer.reverseBytes(color << 8 | ColorU8.normalizedFloatToByte(alpha)); + } + /** * Re-packs the ARGB color into a aBGR color with the specified alpha component. */ diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/util/ColorMixer.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/util/ColorMixer.java similarity index 83% rename from src/api/java/net/caffeinemc/mods/sodium/api/util/ColorMixer.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/util/ColorMixer.java index a81f00ccc6..a2cd74e5de 100644 --- a/src/api/java/net/caffeinemc/mods/sodium/api/util/ColorMixer.java +++ b/common/src/api/java/net/caffeinemc/mods/sodium/api/util/ColorMixer.java @@ -59,4 +59,19 @@ public static int mul(int a, int b) { // Pack the components return (c0 << 0) | (c1 << 8) | (c2 << 16) | (c3 << 24); } + + /** + * Multiplies the 32-bit colors with one component + */ + public static int mulSingle(int a, byte b) { + // Take each 8-bit component pair, multiply them together to create intermediate 16-bit integers, + // and then shift the high half of each 16-bit integer into 8-bit integers. + int c0 = (((a) & 0xFF) * b) >> 8; + int c1 = (((a >> 8) & 0xFF) * b) >> 8; + int c2 = (((a >> 16) & 0xFF) * b) >> 8; + int c3 = (((a >> 24) & 0xFF) * b) >> 8; + + // Pack the components + return (c0 << 0) | (c1 << 8) | (c2 << 16) | (c3 << 24); + } } diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/util/ColorU8.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/util/ColorU8.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/util/ColorU8.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/util/ColorU8.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/util/NormI8.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/util/NormI8.java similarity index 96% rename from src/api/java/net/caffeinemc/mods/sodium/api/util/NormI8.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/util/NormI8.java index 7dc0b68c34..a84597d247 100644 --- a/src/api/java/net/caffeinemc/mods/sodium/api/util/NormI8.java +++ b/common/src/api/java/net/caffeinemc/mods/sodium/api/util/NormI8.java @@ -1,6 +1,7 @@ package net.caffeinemc.mods.sodium.api.util; import net.minecraft.util.Mth; +import org.joml.Vector3f; import org.joml.Vector3fc; /** @@ -114,4 +115,8 @@ public static boolean isOpposite(int normA, int normB) { return normAX == -normBX && normAY == -normBY && normAZ == -normBZ; } + + public static Vector3f unpack(int i, Vector3f output) { + return output.set(unpackX(i), unpackY(i), unpackZ(i)); + } } diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/CommonVertexAttribute.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/CommonVertexAttribute.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/CommonVertexAttribute.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/CommonVertexAttribute.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/ColorAttribute.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/ColorAttribute.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/ColorAttribute.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/ColorAttribute.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/LightAttribute.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/LightAttribute.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/LightAttribute.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/LightAttribute.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/NormalAttribute.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/NormalAttribute.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/NormalAttribute.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/NormalAttribute.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/OverlayAttribute.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/OverlayAttribute.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/OverlayAttribute.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/OverlayAttribute.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/PositionAttribute.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/PositionAttribute.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/PositionAttribute.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/PositionAttribute.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/TextureAttribute.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/TextureAttribute.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/TextureAttribute.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/attributes/common/TextureAttribute.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/buffer/VertexBufferWriter.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/buffer/VertexBufferWriter.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/vertex/buffer/VertexBufferWriter.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/buffer/VertexBufferWriter.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/VertexFormatDescription.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/VertexFormatDescription.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/VertexFormatDescription.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/VertexFormatDescription.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/VertexFormatRegistry.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/VertexFormatRegistry.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/VertexFormatRegistry.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/VertexFormatRegistry.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/ColorVertex.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/ColorVertex.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/ColorVertex.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/ColorVertex.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/GlyphVertex.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/GlyphVertex.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/GlyphVertex.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/GlyphVertex.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/LineVertex.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/LineVertex.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/LineVertex.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/LineVertex.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/ModelVertex.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/ModelVertex.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/ModelVertex.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/ModelVertex.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/ParticleVertex.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/ParticleVertex.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/ParticleVertex.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/format/common/ParticleVertex.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/serializer/VertexSerializer.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/serializer/VertexSerializer.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/vertex/serializer/VertexSerializer.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/serializer/VertexSerializer.java diff --git a/src/api/java/net/caffeinemc/mods/sodium/api/vertex/serializer/VertexSerializerRegistry.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/serializer/VertexSerializerRegistry.java similarity index 100% rename from src/api/java/net/caffeinemc/mods/sodium/api/vertex/serializer/VertexSerializerRegistry.java rename to common/src/api/java/net/caffeinemc/mods/sodium/api/vertex/serializer/VertexSerializerRegistry.java diff --git a/src/desktop/java/net/caffeinemc/mods/sodium/desktop/LaunchWarn.java b/common/src/desktop/java/net/caffeinemc/mods/sodium/desktop/LaunchWarn.java similarity index 100% rename from src/desktop/java/net/caffeinemc/mods/sodium/desktop/LaunchWarn.java rename to common/src/desktop/java/net/caffeinemc/mods/sodium/desktop/LaunchWarn.java diff --git a/src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/BrowseUrlHandler.java b/common/src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/BrowseUrlHandler.java similarity index 100% rename from src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/BrowseUrlHandler.java rename to common/src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/BrowseUrlHandler.java diff --git a/src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/CrossPlatformImpl.java b/common/src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/CrossPlatformImpl.java similarity index 100% rename from src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/CrossPlatformImpl.java rename to common/src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/CrossPlatformImpl.java diff --git a/src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/GNOMEImpl.java b/common/src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/GNOMEImpl.java similarity index 100% rename from src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/GNOMEImpl.java rename to common/src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/GNOMEImpl.java diff --git a/src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/KDEImpl.java b/common/src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/KDEImpl.java similarity index 100% rename from src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/KDEImpl.java rename to common/src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/KDEImpl.java diff --git a/src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/XDGImpl.java b/common/src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/XDGImpl.java similarity index 100% rename from src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/XDGImpl.java rename to common/src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/XDGImpl.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/SodiumClientMod.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/SodiumClientMod.java similarity index 68% rename from src/main/java/net/caffeinemc/mods/sodium/client/SodiumClientMod.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/SodiumClientMod.java index 54f735464d..9dba7b3641 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/SodiumClientMod.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/SodiumClientMod.java @@ -3,44 +3,25 @@ import net.caffeinemc.mods.sodium.client.data.fingerprint.FingerprintMeasure; import net.caffeinemc.mods.sodium.client.data.fingerprint.HashedFingerprint; import net.caffeinemc.mods.sodium.client.gui.SodiumGameOptions; -import net.caffeinemc.mods.sodium.client.gui.console.Console; -import net.caffeinemc.mods.sodium.client.gui.console.message.MessageLevel; -import net.caffeinemc.mods.sodium.client.render.frapi.SpriteFinderCache; -import net.caffeinemc.mods.sodium.client.util.FlawlessFrames; -import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.fabric.api.resource.ResourceManagerHelper; -import net.fabricmc.loader.api.FabricLoader; -import net.fabricmc.loader.api.ModContainer; +import net.caffeinemc.mods.sodium.client.console.Console; +import net.caffeinemc.mods.sodium.client.console.message.MessageLevel; import net.minecraft.network.chat.Component; -import net.minecraft.server.packs.PackType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; -public class SodiumClientMod implements ClientModInitializer { +public class SodiumClientMod { private static SodiumGameOptions CONFIG; - private static Logger LOGGER; + private static final Logger LOGGER = LoggerFactory.getLogger("Sodium"); private static String MOD_VERSION; - @Override - public void onInitializeClient() { - ModContainer mod = FabricLoader.getInstance() - .getModContainer("sodium") - .orElseThrow(NullPointerException::new); + public static void onInitialization(String version) { + MOD_VERSION = version; - MOD_VERSION = mod.getMetadata() - .getVersion() - .getFriendlyString(); - - LOGGER = LoggerFactory.getLogger("Sodium"); CONFIG = loadConfig(); - FlawlessFrames.onClientInitialization(); - - ResourceManagerHelper.get(PackType.CLIENT_RESOURCES).registerReloadListener(SpriteFinderCache.ReloadListener.INSTANCE); - try { updateFingerprint(); } catch (Throwable t) { @@ -71,7 +52,7 @@ private static SodiumGameOptions loadConfig() { LOGGER.error("Failed to load configuration file", e); LOGGER.error("Using default configuration file in read-only mode"); - Console.instance().logMessage(MessageLevel.SEVERE, Component.translatable("sodium.console.config_not_loaded"), 12.5); + Console.instance().logMessage(MessageLevel.SEVERE, "sodium.console.config_not_loaded", true, 12.5); var config = SodiumGameOptions.defaults(); config.setReadOnly(); diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/checks/ResourcePackScanner.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/checks/ResourcePackScanner.java similarity index 89% rename from src/main/java/net/caffeinemc/mods/sodium/client/compatibility/checks/ResourcePackScanner.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/checks/ResourcePackScanner.java index 9ac0265407..56e0512812 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/checks/ResourcePackScanner.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/checks/ResourcePackScanner.java @@ -1,7 +1,7 @@ -package net.caffeinemc.mods.sodium.client.compatibility.checks; +package net.caffeinemc.mods.sodium.client.checks; -import net.caffeinemc.mods.sodium.client.gui.console.Console; -import net.caffeinemc.mods.sodium.client.gui.console.message.MessageLevel; +import net.caffeinemc.mods.sodium.client.console.Console; +import net.caffeinemc.mods.sodium.client.console.message.MessageLevel; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; @@ -76,27 +76,27 @@ private static void printToasts(Collection resourcePacks) { boolean shown = false; if (!incompatibleResourcePacks.isEmpty()) { - showConsoleMessage(Component.translatable("sodium.console.core_shaders_error"), MessageLevel.SEVERE); + showConsoleMessage("sodium.console.core_shaders_error", true, MessageLevel.SEVERE); for (var entry : incompatibleResourcePacks) { - showConsoleMessage(Component.literal(getResourcePackName(entry.resourcePack)), MessageLevel.SEVERE); + showConsoleMessage(getResourcePackName(entry.resourcePack), false, MessageLevel.SEVERE); } shown = true; } if (!likelyIncompatibleResourcePacks.isEmpty()) { - showConsoleMessage(Component.translatable("sodium.console.core_shaders_warn"), MessageLevel.WARN); + showConsoleMessage("sodium.console.core_shaders_warn", true, MessageLevel.WARN); for (var entry : likelyIncompatibleResourcePacks) { - showConsoleMessage(Component.literal(getResourcePackName(entry.resourcePack)), MessageLevel.WARN); + showConsoleMessage(getResourcePackName(entry.resourcePack), false, MessageLevel.WARN); } shown = true; } if (shown) { - showConsoleMessage(Component.translatable("sodium.console.core_shaders_info"), MessageLevel.INFO); + showConsoleMessage("sodium.console.core_shaders_info", true, MessageLevel.INFO); } } @@ -209,8 +209,8 @@ private static List determineIgnoredShaders(PackResources resourcePack) return ignoredShaders; } - private static void showConsoleMessage(MutableComponent message, MessageLevel messageLevel) { - Console.instance().logMessage(messageLevel, message, 12.5); + private static void showConsoleMessage(String message, boolean translatable, MessageLevel messageLevel) { + Console.instance().logMessage(messageLevel, message, translatable, 12.5); } private record ScannedResourcePack(PackResources resourcePack, diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/checks/SodiumResourcePackMetadata.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/checks/SodiumResourcePackMetadata.java similarity index 94% rename from src/main/java/net/caffeinemc/mods/sodium/client/compatibility/checks/SodiumResourcePackMetadata.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/checks/SodiumResourcePackMetadata.java index 213b93e7ac..44898479b0 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/checks/SodiumResourcePackMetadata.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/checks/SodiumResourcePackMetadata.java @@ -1,4 +1,4 @@ -package net.caffeinemc.mods.sodium.client.compatibility.checks; +package net.caffeinemc.mods.sodium.client.checks; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/data/config/MixinConfig.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/data/config/MixinConfig.java similarity index 83% rename from src/main/java/net/caffeinemc/mods/sodium/client/data/config/MixinConfig.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/data/config/MixinConfig.java index 09c945a453..8c72dad127 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/data/config/MixinConfig.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/data/config/MixinConfig.java @@ -1,10 +1,7 @@ package net.caffeinemc.mods.sodium.client.data.config; +import net.caffeinemc.mods.sodium.client.services.Services; import net.caffeinemc.mods.sodium.mixin.MixinOption; -import net.fabricmc.loader.api.FabricLoader; -import net.fabricmc.loader.api.ModContainer; -import net.fabricmc.loader.api.metadata.CustomValue; -import net.fabricmc.loader.api.metadata.ModMetadata; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -17,14 +14,14 @@ * Documentation of these options... */ @SuppressWarnings("CanBeFinal") -public class MixinConfig { - private static final Logger LOGGER = LogManager.getLogger("SodiumConfig"); +public abstract class MixinConfig { + protected static final Logger LOGGER = LogManager.getLogger("SodiumConfig"); - private static final String JSON_KEY_SODIUM_OPTIONS = "sodium:options"; + protected static final String JSON_KEY_SODIUM_OPTIONS = "sodium:options"; private final Map options = new HashMap<>(); - private MixinConfig() { + protected MixinConfig() { // Defines the default rules which can be configured by the user or other mods. // You must manually add a rule for any new mixins not covered by an existing package rule. this.addMixinRule("core", true); // TODO: Don't actually allow the user to disable this @@ -55,6 +52,8 @@ private MixinConfig() { this.addMixinRule("features.render.entity.cull", true); this.addMixinRule("features.render.entity.shadow", true); + this.addMixinRule("features.render.frapi", true); + this.addMixinRule("features.render.gui", true); this.addMixinRule("features.render.gui.font", true); this.addMixinRule("features.render.gui.outlines", true); @@ -129,47 +128,23 @@ private void readProperties(Properties props) { } } - private void applyModOverrides() { - for (ModContainer container : FabricLoader.getInstance().getAllMods()) { - ModMetadata meta = container.getMetadata(); - - if (meta.containsCustomValue(JSON_KEY_SODIUM_OPTIONS)) { - CustomValue overrides = meta.getCustomValue(JSON_KEY_SODIUM_OPTIONS); - - if (overrides.getType() != CustomValue.CvType.OBJECT) { - LOGGER.warn("Mod '{}' contains invalid Sodium option overrides, ignoring", meta.getId()); - continue; - } + public abstract void applyModOverrides(); - for (Map.Entry entry : overrides.getAsObject()) { - this.applyModOverride(meta, entry.getKey(), entry.getValue()); - } - } - } - } - - private void applyModOverride(ModMetadata meta, String name, CustomValue value) { + protected void applyModOverride(String modId, String name, boolean enabled) { MixinOption option = this.options.get(name); if (option == null) { - LOGGER.warn("Mod '{}' attempted to override option '{}', which doesn't exist, ignoring", meta.getId(), name); - return; - } - - if (value.getType() != CustomValue.CvType.BOOLEAN) { - LOGGER.warn("Mod '{}' attempted to override option '{}' with an invalid value, ignoring", meta.getId(), name); + LOGGER.warn("Mod '{}' attempted to override option '{}', which doesn't exist, ignoring", modId, name); return; } - boolean enabled = value.getAsBoolean(); - // disabling the option takes precedence over enabling if (!enabled && option.isEnabled()) { option.clearModsDefiningValue(); } if (!enabled || option.isEnabled() || option.getDefiningMods().isEmpty()) { - option.addModOverride(enabled, meta.getId()); + option.addModOverride(enabled, modId); } } @@ -218,7 +193,7 @@ public static MixinConfig load(File file) { LOGGER.warn("Could not write default configuration file", e); } - MixinConfig config = new MixinConfig(); + MixinConfig config = MixinConfig.create(); config.applyModOverrides(); return config; @@ -232,13 +207,17 @@ public static MixinConfig load(File file) { throw new RuntimeException("Could not load config file", e); } - MixinConfig config = new MixinConfig(); + MixinConfig config = MixinConfig.create(); config.readProperties(props); config.applyModOverrides(); return config; } + private static MixinConfig create() { + return Services.load(MixinConfig.class); + } + private static void writeDefaultConfig(File file) throws IOException { File dir = file.getParentFile(); diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/data/fingerprint/FingerprintMeasure.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/data/fingerprint/FingerprintMeasure.java similarity index 93% rename from src/main/java/net/caffeinemc/mods/sodium/client/data/fingerprint/FingerprintMeasure.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/data/fingerprint/FingerprintMeasure.java index 97650eb2ea..f1e06db7ab 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/data/fingerprint/FingerprintMeasure.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/data/fingerprint/FingerprintMeasure.java @@ -1,6 +1,6 @@ package net.caffeinemc.mods.sodium.client.data.fingerprint; -import net.fabricmc.loader.api.FabricLoader; +import net.caffeinemc.mods.sodium.client.services.PlatformInfoAccess; import net.minecraft.client.Minecraft; import org.apache.commons.codec.binary.Hex; import org.jetbrains.annotations.NotNull; @@ -17,7 +17,7 @@ public record FingerprintMeasure(@NotNull String uuid, @NotNull String path) { public static @Nullable FingerprintMeasure create() { var uuid = Minecraft.getInstance().getUser().getProfileId(); - var path = FabricLoader.getInstance().getGameDir(); + var path = PlatformInfoAccess.getInstance().getGameDirectory(); if (uuid == null || path == null) { return null; diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/data/fingerprint/HashedFingerprint.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/data/fingerprint/HashedFingerprint.java similarity index 92% rename from src/main/java/net/caffeinemc/mods/sodium/client/data/fingerprint/HashedFingerprint.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/data/fingerprint/HashedFingerprint.java index eda5bc8c61..10a2a8b0f5 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/data/fingerprint/HashedFingerprint.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/data/fingerprint/HashedFingerprint.java @@ -2,8 +2,8 @@ import com.google.gson.Gson; import com.google.gson.annotations.SerializedName; +import net.caffeinemc.mods.sodium.client.services.PlatformInfoAccess; import net.caffeinemc.mods.sodium.client.util.FileUtil; -import net.fabricmc.loader.api.FabricLoader; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -68,8 +68,7 @@ public static void writeToDisk(@NotNull HashedFingerprint data) { } private static Path getFilePath() { - return FabricLoader.getInstance() - .getConfigDir() + return PlatformInfoAccess.getInstance().getConfigDirectory() .resolve("sodium-fingerprint.json"); } } diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/GlObject.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/GlObject.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/GlObject.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/GlObject.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/GlBufferArena.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/GlBufferArena.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/GlBufferArena.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/GlBufferArena.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/GlBufferSegment.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/GlBufferSegment.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/GlBufferSegment.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/GlBufferSegment.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/PendingBufferCopyCommand.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/PendingBufferCopyCommand.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/PendingBufferCopyCommand.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/PendingBufferCopyCommand.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/PendingUpload.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/PendingUpload.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/PendingUpload.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/PendingUpload.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/staging/FallbackStagingBuffer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/staging/FallbackStagingBuffer.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/staging/FallbackStagingBuffer.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/staging/FallbackStagingBuffer.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/staging/MappedStagingBuffer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/staging/MappedStagingBuffer.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/staging/MappedStagingBuffer.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/staging/MappedStagingBuffer.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/staging/StagingBuffer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/staging/StagingBuffer.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/staging/StagingBuffer.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/arena/staging/StagingBuffer.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/array/GlVertexArray.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/array/GlVertexArray.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/array/GlVertexArray.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/array/GlVertexArray.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/attribute/GlVertexAttribute.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/attribute/GlVertexAttribute.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/attribute/GlVertexAttribute.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/attribute/GlVertexAttribute.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/attribute/GlVertexAttributeBinding.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/attribute/GlVertexAttributeBinding.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/attribute/GlVertexAttributeBinding.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/attribute/GlVertexAttributeBinding.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/attribute/GlVertexAttributeFormat.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/attribute/GlVertexAttributeFormat.java similarity index 61% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/attribute/GlVertexAttributeFormat.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/attribute/GlVertexAttributeFormat.java index b828826112..91d42c1662 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/gl/attribute/GlVertexAttributeFormat.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/attribute/GlVertexAttributeFormat.java @@ -7,15 +7,7 @@ */ public record GlVertexAttributeFormat(int typeId, int size) { public static final GlVertexAttributeFormat FLOAT = new GlVertexAttributeFormat(GL33C.GL_FLOAT, 4); - - public static final GlVertexAttributeFormat BYTE = new GlVertexAttributeFormat(GL33C.GL_BYTE, 1); - public static final GlVertexAttributeFormat UNSIGNED_BYTE = new GlVertexAttributeFormat(GL33C.GL_UNSIGNED_BYTE, 1); - - public static final GlVertexAttributeFormat SHORT = new GlVertexAttributeFormat(GL33C.GL_SHORT, 2); public static final GlVertexAttributeFormat UNSIGNED_SHORT = new GlVertexAttributeFormat(GL33C.GL_UNSIGNED_SHORT, 2); - - public static final GlVertexAttributeFormat INT = new GlVertexAttributeFormat(GL33C.GL_INT, 4); + public static final GlVertexAttributeFormat UNSIGNED_BYTE = new GlVertexAttributeFormat(GL33C.GL_UNSIGNED_BYTE, 1); public static final GlVertexAttributeFormat UNSIGNED_INT = new GlVertexAttributeFormat(GL33C.GL_UNSIGNED_INT, 4); - - public static final GlVertexAttributeFormat UNSIGNED_2_10_10_10_REV = new GlVertexAttributeFormat(GL33C.GL_UNSIGNED_INT_2_10_10_10_REV, 4); } diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/attribute/GlVertexFormat.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/attribute/GlVertexFormat.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/attribute/GlVertexFormat.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/attribute/GlVertexFormat.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBuffer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBuffer.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBuffer.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBuffer.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferMapFlags.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferMapFlags.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferMapFlags.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferMapFlags.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferMapping.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferMapping.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferMapping.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferMapping.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferStorageFlags.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferStorageFlags.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferStorageFlags.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferStorageFlags.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferTarget.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferTarget.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferTarget.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferTarget.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferUsage.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferUsage.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferUsage.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlBufferUsage.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlImmutableBuffer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlImmutableBuffer.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlImmutableBuffer.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlImmutableBuffer.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlMutableBuffer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlMutableBuffer.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlMutableBuffer.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/GlMutableBuffer.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/IndexedVertexData.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/IndexedVertexData.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/IndexedVertexData.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/buffer/IndexedVertexData.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/device/CommandList.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/device/CommandList.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/device/CommandList.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/device/CommandList.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/device/DrawCommandList.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/device/DrawCommandList.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/device/DrawCommandList.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/device/DrawCommandList.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/device/GLRenderDevice.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/device/GLRenderDevice.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/device/GLRenderDevice.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/device/GLRenderDevice.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/device/MultiDrawBatch.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/device/MultiDrawBatch.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/device/MultiDrawBatch.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/device/MultiDrawBatch.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/device/RenderDevice.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/device/RenderDevice.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/device/RenderDevice.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/device/RenderDevice.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/functions/BufferStorageFunctions.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/functions/BufferStorageFunctions.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/functions/BufferStorageFunctions.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/functions/BufferStorageFunctions.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/functions/DeviceFunctions.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/functions/DeviceFunctions.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/functions/DeviceFunctions.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/functions/DeviceFunctions.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/GlProgram.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/GlProgram.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/GlProgram.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/GlProgram.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/GlShader.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/GlShader.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/GlShader.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/GlShader.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderConstants.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderConstants.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderConstants.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderConstants.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderLoader.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderLoader.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderLoader.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderLoader.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderParser.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderParser.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderParser.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderParser.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderType.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderType.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderType.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderType.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderWorkarounds.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderWorkarounds.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderWorkarounds.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/ShaderWorkarounds.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniform.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniform.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniform.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniform.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformBlock.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformBlock.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformBlock.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformBlock.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformFloat.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformFloat.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformFloat.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformFloat.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformFloat3v.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformFloat3v.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformFloat3v.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformFloat3v.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformFloat4v.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformFloat4v.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformFloat4v.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformFloat4v.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformInt.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformInt.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformInt.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformInt.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformMatrix4f.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformMatrix4f.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformMatrix4f.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/shader/uniform/GlUniformMatrix4f.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/state/GlStateTracker.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/state/GlStateTracker.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/state/GlStateTracker.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/state/GlStateTracker.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/sync/GlFence.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/sync/GlFence.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/sync/GlFence.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/sync/GlFence.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlAbstractTessellation.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlAbstractTessellation.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlAbstractTessellation.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlAbstractTessellation.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlIndexType.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlIndexType.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlIndexType.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlIndexType.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlPrimitiveType.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlPrimitiveType.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlPrimitiveType.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlPrimitiveType.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlTessellation.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlTessellation.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlTessellation.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlTessellation.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlVertexArrayTessellation.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlVertexArrayTessellation.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlVertexArrayTessellation.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/GlVertexArrayTessellation.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/TessellationBinding.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/TessellationBinding.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/TessellationBinding.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/tessellation/TessellationBinding.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/util/EnumBit.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/util/EnumBit.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/util/EnumBit.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/util/EnumBit.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/util/EnumBitField.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/util/EnumBitField.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/util/EnumBitField.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/util/EnumBitField.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gl/util/VertexRange.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gl/util/VertexRange.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gl/util/VertexRange.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gl/util/VertexRange.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumGameOptionPages.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumGameOptionPages.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumGameOptionPages.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumGameOptionPages.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumGameOptions.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumGameOptions.java similarity index 97% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumGameOptions.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumGameOptions.java index be31339ab5..8f6d383ad8 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumGameOptions.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumGameOptions.java @@ -5,9 +5,9 @@ import com.google.gson.GsonBuilder; import com.google.gson.annotations.SerializedName; import net.caffeinemc.mods.sodium.client.gui.options.TextProvider; +import net.caffeinemc.mods.sodium.client.services.PlatformInfoAccess; import net.caffeinemc.mods.sodium.client.util.FileUtil; import net.caffeinemc.mods.sodium.client.render.chunk.translucent_sorting.SortBehavior; -import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.GraphicsStatus; import net.minecraft.network.chat.Component; import java.io.FileReader; @@ -123,8 +123,7 @@ public static SodiumGameOptions loadFromDisk() { } private static Path getConfigPath() { - return FabricLoader.getInstance() - .getConfigDir() + return PlatformInfoAccess.getInstance().getConfigDirectory() .resolve(DEFAULT_FILE_NAME); } diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumOptionsGUI.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumOptionsGUI.java similarity index 97% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumOptionsGUI.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumOptionsGUI.java index 411068dad7..c980a298d8 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumOptionsGUI.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumOptionsGUI.java @@ -2,8 +2,8 @@ import net.caffeinemc.mods.sodium.client.SodiumClientMod; import net.caffeinemc.mods.sodium.client.data.fingerprint.HashedFingerprint; -import net.caffeinemc.mods.sodium.client.gui.console.Console; -import net.caffeinemc.mods.sodium.client.gui.console.message.MessageLevel; +import net.caffeinemc.mods.sodium.client.console.Console; +import net.caffeinemc.mods.sodium.client.console.message.MessageLevel; import net.caffeinemc.mods.sodium.client.gui.options.*; import net.caffeinemc.mods.sodium.client.gui.options.control.Control; import net.caffeinemc.mods.sodium.client.gui.options.control.ControlElement; @@ -12,8 +12,8 @@ import net.caffeinemc.mods.sodium.client.gui.prompt.ScreenPromptable; import net.caffeinemc.mods.sodium.client.gui.screen.ConfigCorruptedScreen; import net.caffeinemc.mods.sodium.client.gui.widgets.FlatButtonWidget; +import net.caffeinemc.mods.sodium.client.services.PlatformInfoAccess; import net.caffeinemc.mods.sodium.client.util.Dim2i; -import net.fabricmc.loader.api.FabricLoader; import net.minecraft.ChatFormatting; import net.minecraft.Util; import net.minecraft.client.Minecraft; @@ -70,7 +70,7 @@ private SodiumOptionsGUI(Screen prevScreen) { private void checkPromptTimers() { // Never show the prompt in developer workspaces. - if (FabricLoader.getInstance().isDevelopmentEnvironment()) { + if (PlatformInfoAccess.getInstance().isDevelopmentEnvironment()) { return; } @@ -357,7 +357,7 @@ private void applyChanges() { if (flags.contains(OptionFlag.REQUIRES_GAME_RESTART)) { Console.instance().logMessage(MessageLevel.WARN, - Component.translatable("sodium.console.game_restart"), 10.0); + "sodium.console.game_restart", true, 10.0); } for (OptionStorage storage : dirtyStorages) { diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/ConsoleHooks.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/ConsoleHooks.java similarity index 85% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/console/ConsoleHooks.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/ConsoleHooks.java index 5d4eb7a2c6..83300a4651 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/ConsoleHooks.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/ConsoleHooks.java @@ -1,5 +1,6 @@ package net.caffeinemc.mods.sodium.client.gui.console; +import net.caffeinemc.mods.sodium.client.console.Console; import net.minecraft.client.gui.GuiGraphics; public class ConsoleHooks { diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/ConsoleRenderer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/ConsoleRenderer.java similarity index 95% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/console/ConsoleRenderer.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/ConsoleRenderer.java index 831e758c9c..87c554e977 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/ConsoleRenderer.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/ConsoleRenderer.java @@ -1,7 +1,8 @@ package net.caffeinemc.mods.sodium.client.gui.console; -import net.caffeinemc.mods.sodium.client.gui.console.message.Message; -import net.caffeinemc.mods.sodium.client.gui.console.message.MessageLevel; +import net.caffeinemc.mods.sodium.client.console.Console; +import net.caffeinemc.mods.sodium.client.console.message.Message; +import net.caffeinemc.mods.sodium.client.console.message.MessageLevel; import net.caffeinemc.mods.sodium.api.util.ColorARGB; import net.caffeinemc.mods.sodium.api.util.ColorU8; import net.minecraft.client.Minecraft; @@ -173,7 +174,7 @@ private static int weightAlpha(double scale) { private record ActiveMessage(MessageLevel level, Component text, double duration, double timestamp) { public static ActiveMessage create(Message message, double timestamp) { - var text = message.text() + var text = (message.translated() ? Component.translatable(message.text()) : Component.literal(message.text())) .copy() .withStyle((style) -> style.withFont(Minecraft.UNIFORM_FONT)); diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/Option.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/Option.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/Option.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/Option.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionFlag.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionFlag.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionFlag.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionFlag.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionGroup.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionGroup.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionGroup.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionGroup.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionImpact.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionImpact.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionImpact.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionImpact.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionImpl.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionImpl.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionImpl.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionImpl.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionPage.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionPage.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionPage.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/OptionPage.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/TextProvider.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/TextProvider.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/TextProvider.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/TextProvider.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/binding/GenericBinding.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/binding/GenericBinding.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/binding/GenericBinding.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/binding/GenericBinding.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/binding/OptionBinding.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/binding/OptionBinding.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/binding/OptionBinding.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/binding/OptionBinding.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/binding/compat/VanillaBooleanOptionBinding.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/binding/compat/VanillaBooleanOptionBinding.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/binding/compat/VanillaBooleanOptionBinding.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/binding/compat/VanillaBooleanOptionBinding.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/Control.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/Control.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/Control.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/Control.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/ControlElement.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/ControlElement.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/ControlElement.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/ControlElement.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/ControlValueFormatter.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/ControlValueFormatter.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/ControlValueFormatter.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/ControlValueFormatter.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/CyclingControl.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/CyclingControl.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/CyclingControl.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/CyclingControl.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/SliderControl.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/SliderControl.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/SliderControl.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/SliderControl.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/TickBoxControl.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/TickBoxControl.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/TickBoxControl.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/TickBoxControl.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/storage/MinecraftOptionsStorage.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/storage/MinecraftOptionsStorage.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/storage/MinecraftOptionsStorage.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/storage/MinecraftOptionsStorage.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/storage/OptionStorage.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/storage/OptionStorage.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/storage/OptionStorage.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/storage/OptionStorage.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/storage/SodiumOptionsStorage.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/storage/SodiumOptionsStorage.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/options/storage/SodiumOptionsStorage.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/storage/SodiumOptionsStorage.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/prompt/ScreenPrompt.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/prompt/ScreenPrompt.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/prompt/ScreenPrompt.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/prompt/ScreenPrompt.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/prompt/ScreenPromptable.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/prompt/ScreenPromptable.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/prompt/ScreenPromptable.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/prompt/ScreenPromptable.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/screen/ConfigCorruptedScreen.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/screen/ConfigCorruptedScreen.java similarity index 92% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/screen/ConfigCorruptedScreen.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/screen/ConfigCorruptedScreen.java index e6c7b0e9db..6f868e41b5 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/gui/screen/ConfigCorruptedScreen.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/screen/ConfigCorruptedScreen.java @@ -1,8 +1,8 @@ package net.caffeinemc.mods.sodium.client.gui.screen; import net.caffeinemc.mods.sodium.client.SodiumClientMod; -import net.caffeinemc.mods.sodium.client.gui.console.Console; -import net.caffeinemc.mods.sodium.client.gui.console.message.MessageLevel; +import net.caffeinemc.mods.sodium.client.console.Console; +import net.caffeinemc.mods.sodium.client.console.message.MessageLevel; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; @@ -54,7 +54,7 @@ protected void init() { int buttonY = this.height - SCREEN_PADDING - BUTTON_HEIGHT; this.addRenderableWidget(Button.builder(Component.literal("Continue"), (btn) -> { - Console.instance().logMessage(MessageLevel.INFO, Component.translatable("sodium.console.config_file_was_reset"), 3.0); + Console.instance().logMessage(MessageLevel.INFO, "sodium.console.config_file_was_reset", true, 3.0); SodiumClientMod.restoreDefaultOptions(); Minecraft.getInstance().setScreen(this.nextScreen.apply(this.prevScreen)); diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/widgets/AbstractWidget.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/widgets/AbstractWidget.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/widgets/AbstractWidget.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/widgets/AbstractWidget.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/widgets/FlatButtonWidget.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/widgets/FlatButtonWidget.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/widgets/FlatButtonWidget.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/gui/widgets/FlatButtonWidget.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/color/ColorProvider.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/color/ColorProvider.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/color/ColorProvider.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/color/ColorProvider.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/color/ColorProviderRegistry.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/color/ColorProviderRegistry.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/color/ColorProviderRegistry.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/color/ColorProviderRegistry.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/color/DefaultColorProviders.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/color/DefaultColorProviders.java similarity index 65% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/color/DefaultColorProviders.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/color/DefaultColorProviders.java index 99bc40ba7d..0f716c23f6 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/model/color/DefaultColorProviders.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/color/DefaultColorProviders.java @@ -2,11 +2,9 @@ import net.caffeinemc.mods.sodium.client.model.quad.ModelQuadView; import net.caffeinemc.mods.sodium.client.model.quad.blender.BlendedColorProvider; -import net.caffeinemc.mods.sodium.client.world.biome.BiomeColorSource; import net.caffeinemc.mods.sodium.client.world.LevelSlice; -import net.caffeinemc.mods.sodium.api.util.ColorARGB; -import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler; import net.minecraft.client.color.block.BlockColor; +import net.minecraft.client.renderer.BiomeColors; import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.FluidState; @@ -17,9 +15,7 @@ public static ColorProvider adapt(BlockColor color) { return new VanillaAdapter(color); } - public static ColorProvider adapt(FluidRenderHandler handler) { - return new FabricFluidAdapter(handler); - } + private static final ThreadLocal blockPosHolder = ThreadLocal.withInitial(BlockPos.MutableBlockPos::new); public static class GrassColorProvider extends BlendedColorProvider { public static final ColorProvider BLOCKS = new GrassColorProvider<>(); @@ -30,7 +26,7 @@ private GrassColorProvider() { @Override protected int getColor(LevelSlice slice, int x, int y, int z) { - return slice.getColor(BiomeColorSource.GRASS, x, y, z); + return BiomeColors.getAverageGrassColor(slice, blockPosHolder.get().set(x, y, z)); } } @@ -43,7 +39,7 @@ private FoliageColorProvider() { @Override protected int getColor(LevelSlice slice, int x, int y, int z) { - return slice.getColor(BiomeColorSource.FOLIAGE, x, y, z); + return BiomeColors.getAverageFoliageColor(slice, blockPosHolder.get().set(x, y, z)); } } @@ -57,7 +53,7 @@ private WaterColorProvider() { @Override protected int getColor(LevelSlice slice, int x, int y, int z) { - return slice.getColor(BiomeColorSource.WATER, x, y, z); + return BiomeColors.getAverageWaterColor(slice, blockPosHolder.get().set(x, y, z)); } } @@ -70,20 +66,7 @@ private VanillaAdapter(BlockColor color) { @Override public void getColors(LevelSlice slice, BlockPos pos, BlockState state, ModelQuadView quad, int[] output) { - Arrays.fill(output, ColorARGB.toABGR(this.color.getColor(state, slice, pos, quad.getColorIndex()))); - } - } - - private static class FabricFluidAdapter implements ColorProvider { - private final FluidRenderHandler handler; - - public FabricFluidAdapter(FluidRenderHandler handler) { - this.handler = handler; - } - - @Override - public void getColors(LevelSlice slice, BlockPos pos, FluidState state, ModelQuadView quad, int[] output) { - Arrays.fill(output, this.handler.getFluidColor(slice, pos, state)); + Arrays.fill(output, this.color.getColor(state, slice, pos, quad.getColorIndex())); } } } diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/color/interop/BlockColorsExtension.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/color/interop/BlockColorsExtension.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/color/interop/BlockColorsExtension.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/color/interop/BlockColorsExtension.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/color/interop/ItemColorsExtension.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/color/interop/ItemColorsExtension.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/color/interop/ItemColorsExtension.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/color/interop/ItemColorsExtension.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/light/LightMode.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/LightMode.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/light/LightMode.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/LightMode.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/light/LightPipeline.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/LightPipeline.java similarity index 86% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/light/LightPipeline.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/LightPipeline.java index d6affb784d..29eb8f57f1 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/model/light/LightPipeline.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/LightPipeline.java @@ -18,6 +18,7 @@ public interface LightPipeline { * @param cullFace The cull face of the quad * @param lightFace The light face of the quad * @param shade True if the block is shaded by ambient occlusion + * @param isFluid True if the block is being drawn by the fluid renderer */ - void calculate(ModelQuadView quad, BlockPos pos, QuadLightData out, Direction cullFace, Direction lightFace, boolean shade); + void calculate(ModelQuadView quad, BlockPos pos, QuadLightData out, Direction cullFace, Direction lightFace, boolean shade, boolean isFluid); } diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/light/LightPipelineProvider.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/LightPipelineProvider.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/light/LightPipelineProvider.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/LightPipelineProvider.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/ArrayLightDataCache.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/ArrayLightDataCache.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/ArrayLightDataCache.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/ArrayLightDataCache.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/HashLightDataCache.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/HashLightDataCache.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/HashLightDataCache.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/HashLightDataCache.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/LightDataAccess.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/LightDataAccess.java similarity index 92% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/LightDataAccess.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/LightDataAccess.java index c4c4bc143a..0ded5bc8c9 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/LightDataAccess.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/LightDataAccess.java @@ -1,5 +1,6 @@ package net.caffeinemc.mods.sodium.client.model.light.data; +import net.caffeinemc.mods.sodium.client.services.PlatformBlockAccess; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.LightTexture; import net.minecraft.core.BlockPos; @@ -68,7 +69,7 @@ protected int compute(int x, int y, int z) { boolean fo = state.isSolidRender(level, pos); boolean fc = state.isCollisionShapeFullBlock(level, pos); - int lu = state.getLightEmission(); + int lu = PlatformBlockAccess.getInstance().getLightEmission(state, level, pos); // OPTIMIZE: Do not calculate light data if the block is full and opaque and does not emit light. int bl; @@ -77,8 +78,14 @@ protected int compute(int x, int y, int z) { bl = 0; sl = 0; } else { - bl = level.getBrightness(LightLayer.BLOCK, pos); - sl = level.getBrightness(LightLayer.SKY, pos); + if (em) { + bl = level.getBrightness(LightLayer.BLOCK, pos); + sl = level.getBrightness(LightLayer.SKY, pos); + } else { + int light = LevelRenderer.getLightColor(level, state, pos); + bl = LightTexture.block(light); + sl = LightTexture.sky(light); + } } // FIX: Do not apply AO from blocks that emit light diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/QuadLightData.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/QuadLightData.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/QuadLightData.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/QuadLightData.java diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/SingleBlockLightDataCache.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/SingleBlockLightDataCache.java new file mode 100644 index 0000000000..267f95a683 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/data/SingleBlockLightDataCache.java @@ -0,0 +1,60 @@ +package net.caffeinemc.mods.sodium.client.model.light.data; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockAndTintGetter; + +import java.util.Arrays; + +/** + * Adaptation of {@link ArrayLightDataCache} that stores data for + * only one block and its neighbors. + */ +public class SingleBlockLightDataCache extends LightDataAccess { + // Radius of 2 is required: block models may create geometry in up to a 3x3x3 region, which requires light to be + // queried from neighbours of any block in this region + private static final int NEIGHBOR_BLOCK_RADIUS = 2; + private static final int BLOCK_LENGTH = 1 + (NEIGHBOR_BLOCK_RADIUS * 2); + + private final int[] light; + + private int xOffset, yOffset, zOffset; + + public SingleBlockLightDataCache() { + this.light = new int[BLOCK_LENGTH * BLOCK_LENGTH * BLOCK_LENGTH]; + } + + public void reset(BlockPos origin, BlockAndTintGetter blockView) { + this.xOffset = origin.getX() - NEIGHBOR_BLOCK_RADIUS; + this.yOffset = origin.getY() - NEIGHBOR_BLOCK_RADIUS; + this.zOffset = origin.getZ() - NEIGHBOR_BLOCK_RADIUS; + + Arrays.fill(this.light, 0); + + this.level = blockView; + } + + public void release() { + this.level = null; + } + + private int index(int x, int y, int z) { + int x2 = x - this.xOffset; + int y2 = y - this.yOffset; + int z2 = z - this.zOffset; + + return (z2 * BLOCK_LENGTH * BLOCK_LENGTH) + (y2 * BLOCK_LENGTH) + x2; + } + + @Override + public int get(int x, int y, int z) { + int l = this.index(x, y, z); + + int word = this.light[l]; + + if (word != 0) { + return word; + } + + return this.light[l] = this.compute(x, y, z); + } +} \ No newline at end of file diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/light/flat/FlatLightPipeline.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/flat/FlatLightPipeline.java similarity index 88% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/light/flat/FlatLightPipeline.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/flat/FlatLightPipeline.java index 83dbca2d98..de2fd59918 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/model/light/flat/FlatLightPipeline.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/flat/FlatLightPipeline.java @@ -5,6 +5,7 @@ import net.caffeinemc.mods.sodium.client.model.light.data.QuadLightData; import net.caffeinemc.mods.sodium.client.model.quad.ModelQuadView; import net.caffeinemc.mods.sodium.client.model.quad.properties.ModelQuadFlags; +import net.caffeinemc.mods.sodium.client.services.PlatformBlockAccess; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.LightTexture; import net.minecraft.core.BlockPos; @@ -30,25 +31,27 @@ public FlatLightPipeline(LightDataAccess lightCache) { } @Override - public void calculate(ModelQuadView quad, BlockPos pos, QuadLightData out, Direction cullFace, Direction lightFace, boolean shade) { + public void calculate(ModelQuadView quad, BlockPos pos, QuadLightData out, Direction cullFace, Direction lightFace, boolean shade, boolean isFluid) { int lightmap; // To match vanilla behavior, use the cull face if it exists/is available if (cullFace != null) { lightmap = getOffsetLightmap(pos, cullFace); + Arrays.fill(out.br, this.lightCache.getLevel().getShade(lightFace, shade)); } else { int flags = quad.getFlags(); // If the face is aligned, use the light data above it // To match vanilla behavior, also treat the face as aligned if it is parallel and the block state is a full cube if ((flags & ModelQuadFlags.IS_ALIGNED) != 0 || ((flags & ModelQuadFlags.IS_PARALLEL) != 0 && unpackFC(this.lightCache.get(pos)))) { lightmap = getOffsetLightmap(pos, lightFace); + Arrays.fill(out.br, this.lightCache.getLevel().getShade(lightFace, shade)); } else { lightmap = getEmissiveLightmap(this.lightCache.get(pos)); + Arrays.fill(out.br, PlatformBlockAccess.getInstance().getAccurateBlockShade(quad, this.lightCache.getLevel(), shade)); } } Arrays.fill(out.lm, lightmap); - Arrays.fill(out.br, this.lightCache.getLevel().getShade(lightFace, shade)); } /** diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/AoCompletionFlags.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/AoCompletionFlags.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/AoCompletionFlags.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/AoCompletionFlags.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/AoFaceData.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/AoFaceData.java similarity index 85% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/AoFaceData.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/AoFaceData.java index 13a3129882..2fca84b4d6 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/AoFaceData.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/AoFaceData.java @@ -155,6 +155,33 @@ public void initLightData(LightDataAccess cache, BlockPos pos, Direction directi this.flags |= AoCompletionFlags.HAS_LIGHT_DATA; } + static AoFaceData weightedMean(AoFaceData in0, float w0, AoFaceData in1, float w1, AoFaceData out) { + out.ao[0] = in0.ao[0] * w0 + in1.ao[0] * w1; + out.ao[1] = in0.ao[1] * w0 + in1.ao[1] * w1; + out.ao[2] = in0.ao[2] * w0 + in1.ao[2] * w1; + out.ao[3] = in0.ao[3] * w0 + in1.ao[3] * w1; + + if (!in0.hasUnpackedLightData()) in0.unpackLightData(); + if (!in1.hasUnpackedLightData()) in1.unpackLightData(); + + out.bl[0] = (int) (in0.bl[0] * w0 + in1.bl[0] * w1); + out.bl[1] = (int) (in0.bl[1] * w0 + in1.bl[1] * w1); + out.bl[2] = (int) (in0.bl[2] * w0 + in1.bl[2] * w1); + out.bl[3] = (int) (in0.bl[3] * w0 + in1.bl[3] * w1); + + out.sl[0] = (int) (in0.sl[0] * w0 + in1.sl[0] * w1); + out.sl[1] = (int) (in0.sl[1] * w0 + in1.sl[1] * w1); + out.sl[2] = (int) (in0.sl[2] * w0 + in1.sl[2] * w1); + out.sl[3] = (int) (in0.sl[3] * w0 + in1.sl[3] * w1); + + out.lm[0] = packLight(out.sl[0], out.bl[0]); + out.lm[1] = packLight(out.sl[1], out.bl[1]); + out.lm[2] = packLight(out.sl[2], out.bl[2]); + out.lm[3] = packLight(out.sl[3], out.bl[3]); + + return out; + } + public void unpackLightData() { int[] lm = this.lm; @@ -203,6 +230,10 @@ private static float unpackBlockLight(int i) { return i & 0xFF; } + private static int packLight(float sl, float bl) { + return (((int) sl & 0xFF) << 16) | ((int) bl & 0xFF); + } + private static int calculateCornerBrightness(int a, int b, int c, int d, boolean aem, boolean bem, boolean cem, boolean dem) { // FIX: Normalize corner vectors correctly to the minimum non-zero value between each one to prevent // strange issues diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/AoNeighborInfo.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/AoNeighborInfo.java similarity index 88% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/AoNeighborInfo.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/AoNeighborInfo.java index 61b83f37d6..0b473eab32 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/AoNeighborInfo.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/AoNeighborInfo.java @@ -1,18 +1,18 @@ package net.caffeinemc.mods.sodium.client.model.light.smooth; import net.minecraft.core.Direction; +import net.minecraft.util.Mth; /** * The neighbor information for each face of a block, used when performing smooth lighting in order to calculate * the occlusion of each corner. */ -@SuppressWarnings("UnnecessaryLocalVariable") enum AoNeighborInfo { DOWN(new Direction[] { Direction.WEST, Direction.EAST, Direction.NORTH, Direction.SOUTH }, 0.5F) { @Override public void calculateCornerWeights(float x, float y, float z, float[] out) { - final float u = z; - final float v = 1.0f - x; + final float u = Mth.clamp(z, 0.0f, 1.0f); + final float v = Mth.clamp(1.0f - x, 0.0f, 1.0f); out[0] = v * u; out[1] = v * (1.0f - u); @@ -35,14 +35,14 @@ public void mapCorners(int[] lm0, float[] ao0, int[] lm1, float[] ao1) { @Override public float getDepth(float x, float y, float z) { - return y; + return Mth.clamp(y, 0.0F, 1.0F); } }, UP(new Direction[] { Direction.EAST, Direction.WEST, Direction.NORTH, Direction.SOUTH }, 1.0F) { @Override public void calculateCornerWeights(float x, float y, float z, float[] out) { - final float u = z; - final float v = x; + final float u = Mth.clamp(z, 0.0f, 1.0f); + final float v = Mth.clamp(x, 0.0f, 1.0f); out[0] = v * u; out[1] = v * (1.0f - u); @@ -65,14 +65,14 @@ public void mapCorners(int[] lm0, float[] ao0, int[] lm1, float[] ao1) { @Override public float getDepth(float x, float y, float z) { - return 1.0f - y; + return 1.0f - Mth.clamp(y, 0.0F, 1.0F); } }, NORTH(new Direction[] { Direction.UP, Direction.DOWN, Direction.EAST, Direction.WEST }, 0.8F) { @Override public void calculateCornerWeights(float x, float y, float z, float[] out) { - final float u = 1.0f - x; - final float v = y; + final float u = Mth.clamp(1.0f - x, 0.0f, 1.0f); + final float v = Mth.clamp(y, 0.0f, 1.0f); out[0] = v * u; out[1] = v * (1.0f - u); @@ -95,14 +95,14 @@ public void mapCorners(int[] lm0, float[] ao0, int[] lm1, float[] ao1) { @Override public float getDepth(float x, float y, float z) { - return z; + return Mth.clamp(z, 0.0F, 1.0F); } }, SOUTH(new Direction[] { Direction.WEST, Direction.EAST, Direction.DOWN, Direction.UP }, 0.8F) { @Override public void calculateCornerWeights(float x, float y, float z, float[] out) { - final float u = y; - final float v = 1.0f - x; + final float u = Mth.clamp(y, 0.0f, 1.0f); + final float v = Mth.clamp(1.0f - x, 0.0f, 1.0f); out[0] = u * v; out[1] = (1.0f - u) * v; @@ -125,14 +125,14 @@ public void mapCorners(int[] lm0, float[] ao0, int[] lm1, float[] ao1) { @Override public float getDepth(float x, float y, float z) { - return 1.0f - z; + return 1.0f - Mth.clamp(z, 0.0F, 1.0F); } }, WEST(new Direction[] { Direction.UP, Direction.DOWN, Direction.NORTH, Direction.SOUTH }, 0.6F) { @Override public void calculateCornerWeights(float x, float y, float z, float[] out) { - final float u = z; - final float v = y; + final float u = Mth.clamp(z, 0.0f, 1.0f); + final float v = Mth.clamp(y, 0.0f, 1.0f); out[0] = v * u; out[1] = v * (1.0f - u); @@ -155,14 +155,14 @@ public void mapCorners(int[] lm0, float[] ao0, int[] lm1, float[] ao1) { @Override public float getDepth(float x, float y, float z) { - return x; + return Mth.clamp(x, 0.0F, 1.0F); } }, EAST(new Direction[] { Direction.DOWN, Direction.UP, Direction.NORTH, Direction.SOUTH }, 0.6F) { @Override public void calculateCornerWeights(float x, float y, float z, float[] out) { - final float u = z; - final float v = 1.0f - y; + final float u = Mth.clamp(z, 0.0f, 1.0f); + final float v = Mth.clamp(1.0f - y, 0.0f, 1.0f); out[0] = v * u; out[1] = v * (1.0f - u); @@ -185,7 +185,7 @@ public void mapCorners(int[] lm0, float[] ao0, int[] lm1, float[] ao1) { @Override public float getDepth(float x, float y, float z) { - return 1.0f - x; + return 1.0f - Mth.clamp(x, 0.0F, 1.0F); } }; diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/SmoothLightPipeline.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/SmoothLightPipeline.java similarity index 66% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/SmoothLightPipeline.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/SmoothLightPipeline.java index f27230914f..27ddb76f01 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/SmoothLightPipeline.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/light/smooth/SmoothLightPipeline.java @@ -1,5 +1,6 @@ package net.caffeinemc.mods.sodium.client.model.light.smooth; +import net.caffeinemc.mods.sodium.api.util.NormI8; import net.caffeinemc.mods.sodium.client.model.light.LightPipeline; import net.caffeinemc.mods.sodium.client.model.light.data.LightDataAccess; import net.caffeinemc.mods.sodium.client.model.light.data.QuadLightData; @@ -8,6 +9,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.util.Mth; +import org.joml.Vector3f; /** * A light pipeline which produces smooth interpolated lighting and ambient occlusion for model quads. This @@ -64,7 +66,7 @@ public SmoothLightPipeline(LightDataAccess cache) { } @Override - public void calculate(ModelQuadView quad, BlockPos pos, QuadLightData out, Direction cullFace, Direction lightFace, boolean shade) { + public void calculate(ModelQuadView quad, BlockPos pos, QuadLightData out, Direction cullFace, Direction lightFace, boolean shade, boolean isFluid) { this.updateCachedData(pos.asLong()); int flags = quad.getFlags(); @@ -77,17 +79,17 @@ public void calculate(ModelQuadView quad, BlockPos pos, QuadLightData out, Direc // To match vanilla behavior, also treat the face as aligned if it is parallel and the block state is a full cube if ((flags & ModelQuadFlags.IS_ALIGNED) != 0 || ((flags & ModelQuadFlags.IS_PARALLEL) != 0 && LightDataAccess.unpackFC(this.lightCache.get(pos)))) { if ((flags & ModelQuadFlags.IS_PARTIAL) == 0) { - this.applyAlignedFullFace(neighborInfo, pos, lightFace, out); + this.applyAlignedFullFace(neighborInfo, pos, lightFace, out, shade); } else { - this.applyAlignedPartialFace(neighborInfo, quad, pos, lightFace, out); + this.applyAlignedPartialFace(neighborInfo, quad, pos, lightFace, out, shade); } } else if ((flags & ModelQuadFlags.IS_PARALLEL) != 0) { - this.applyParallelFace(neighborInfo, quad, pos, lightFace, out); + this.applyParallelFace(neighborInfo, quad, pos, lightFace, out, shade); + } else if (isFluid) { + this.applyNonParallelFace(neighborInfo, quad, pos, lightFace, out, shade); } else { - this.applyNonParallelFace(neighborInfo, quad, pos, lightFace, out); + this.applyIrregularFace(pos, quad, out, shade); } - - this.applySidedBrightness(out, lightFace, shade); } /** @@ -96,8 +98,8 @@ public void calculate(ModelQuadView quad, BlockPos pos, QuadLightData out, Direc * have two contributing sides. * Flags: IS_ALIGNED, !IS_PARTIAL */ - private void applyAlignedFullFace(AoNeighborInfo neighborInfo, BlockPos pos, Direction dir, QuadLightData out) { - AoFaceData faceData = this.getCachedFaceData(pos, dir, true); + private void applyAlignedFullFace(AoNeighborInfo neighborInfo, BlockPos pos, Direction dir, QuadLightData out, boolean shade) { + AoFaceData faceData = this.getCachedFaceData(pos, dir, true, shade); neighborInfo.mapCorners(faceData.lm, faceData.ao, out.lm, out.br); } @@ -105,7 +107,7 @@ private void applyAlignedFullFace(AoNeighborInfo neighborInfo, BlockPos pos, Dir * Calculates the light data for a grid-aligned quad that does not cover the entire block volume's face. * Flags: IS_ALIGNED, IS_PARTIAL */ - private void applyAlignedPartialFace(AoNeighborInfo neighborInfo, ModelQuadView quad, BlockPos pos, Direction dir, QuadLightData out) { + private void applyAlignedPartialFace(AoNeighborInfo neighborInfo, ModelQuadView quad, BlockPos pos, Direction dir, QuadLightData out, boolean shade) { for (int i = 0; i < 4; i++) { // Clamp the vertex positions to the block's boundaries to prevent weird errors in lighting float cx = clamp(quad.getX(i)); @@ -114,18 +116,18 @@ private void applyAlignedPartialFace(AoNeighborInfo neighborInfo, ModelQuadView float[] weights = this.weights; neighborInfo.calculateCornerWeights(cx, cy, cz, weights); - this.applyAlignedPartialFaceVertex(pos, dir, weights, i, out, true); + this.applyAlignedPartialFaceVertex(pos, dir, weights, i, out, true, shade); } } /** * This method is the same as {@link #applyNonParallelFace(AoNeighborInfo, ModelQuadView, BlockPos, Direction, - * QuadLightData)} but with the check for a depth of approximately 0 removed. If the quad is parallel but not + * QuadLightData, boolean)} but with the check for a depth of approximately 0 removed. If the quad is parallel but not * aligned, all of its vertices will have the same depth and this depth must be approximately greater than 0, * meaning the check for 0 will always return false. * Flags: !IS_ALIGNED, IS_PARALLEL */ - private void applyParallelFace(AoNeighborInfo neighborInfo, ModelQuadView quad, BlockPos pos, Direction dir, QuadLightData out) { + private void applyParallelFace(AoNeighborInfo neighborInfo, ModelQuadView quad, BlockPos pos, Direction dir, QuadLightData out, boolean shade) { for (int i = 0; i < 4; i++) { // Clamp the vertex positions to the block's boundaries to prevent weird errors in lighting float cx = clamp(quad.getX(i)); @@ -140,11 +142,11 @@ private void applyParallelFace(AoNeighborInfo neighborInfo, ModelQuadView quad, // If the quad is approximately grid-aligned (not inset) to the other side of the block, avoid unnecessary // computation by treating it is as aligned if (Mth.equal(depth, 1.0F)) { - this.applyAlignedPartialFaceVertex(pos, dir, weights, i, out, false); + this.applyAlignedPartialFaceVertex(pos, dir, weights, i, out, false, shade); } else { // Blend the occlusion factor between the blocks directly beside this face and the blocks above it // based on how inset the face is. This fixes a few issues with blocks such as farmland and paths. - this.applyInsetPartialFaceVertex(pos, dir, depth, 1.0f - depth, weights, i, out); + this.applyInsetPartialFaceVertex(pos, dir, depth, 1.0f - depth, weights, i, out, shade); } } } @@ -152,7 +154,7 @@ private void applyParallelFace(AoNeighborInfo neighborInfo, ModelQuadView quad, /** * Flags: !IS_ALIGNED, !IS_PARALLEL */ - private void applyNonParallelFace(AoNeighborInfo neighborInfo, ModelQuadView quad, BlockPos pos, Direction dir, QuadLightData out) { + private void applyNonParallelFace(AoNeighborInfo neighborInfo, ModelQuadView quad, BlockPos pos, Direction dir, QuadLightData out, boolean shade) { for (int i = 0; i < 4; i++) { // Clamp the vertex positions to the block's boundaries to prevent weird errors in lighting float cx = clamp(quad.getX(i)); @@ -166,19 +168,19 @@ private void applyNonParallelFace(AoNeighborInfo neighborInfo, ModelQuadView qua // If the quad is approximately grid-aligned (not inset), avoid unnecessary computation by treating it is as aligned if (Mth.equal(depth, 0.0F)) { - this.applyAlignedPartialFaceVertex(pos, dir, weights, i, out, true); + this.applyAlignedPartialFaceVertex(pos, dir, weights, i, out, true, shade); } else if (Mth.equal(depth, 1.0F)) { - this.applyAlignedPartialFaceVertex(pos, dir, weights, i, out, false); + this.applyAlignedPartialFaceVertex(pos, dir, weights, i, out, false, shade); } else { // Blend the occlusion factor between the blocks directly beside this face and the blocks above it // based on how inset the face is. This fixes a few issues with blocks such as farmland and paths. - this.applyInsetPartialFaceVertex(pos, dir, depth, 1.0f - depth, weights, i, out); + this.applyInsetPartialFaceVertex(pos, dir, depth, 1.0f - depth, weights, i, out, shade); } } } - private void applyAlignedPartialFaceVertex(BlockPos pos, Direction dir, float[] w, int i, QuadLightData out, boolean offset) { - AoFaceData faceData = this.getCachedFaceData(pos, dir, offset); + private void applyAlignedPartialFaceVertex(BlockPos pos, Direction dir, float[] w, int i, QuadLightData out, boolean offset, boolean shade) { + AoFaceData faceData = this.getCachedFaceData(pos, dir, offset, shade); if (!faceData.hasUnpackedLightData()) { faceData.unpackLightData(); @@ -192,14 +194,14 @@ private void applyAlignedPartialFaceVertex(BlockPos pos, Direction dir, float[] out.lm[i] = getLightMapCoord(sl, bl); } - private void applyInsetPartialFaceVertex(BlockPos pos, Direction dir, float n1d, float n2d, float[] w, int i, QuadLightData out) { - AoFaceData n1 = this.getCachedFaceData(pos, dir, false); + private void applyInsetPartialFaceVertex(BlockPos pos, Direction dir, float n1d, float n2d, float[] w, int i, QuadLightData out, boolean shade) { + AoFaceData n1 = this.getCachedFaceData(pos, dir, false, shade); if (!n1.hasUnpackedLightData()) { n1.unpackLightData(); } - AoFaceData n2 = this.getCachedFaceData(pos, dir, true); + AoFaceData n2 = this.getCachedFaceData(pos, dir, true, shade); if (!n2.hasUnpackedLightData()) { n2.unpackLightData(); @@ -214,23 +216,119 @@ private void applyInsetPartialFaceVertex(BlockPos pos, Direction dir, float n1d, out.lm[i] = getLightMapCoord(sl, bl); } - private void applySidedBrightness(QuadLightData out, Direction face, boolean shade) { + /** used exclusively in irregular face to avoid new heap allocations each call. */ + private final Vector3f vertexNormal = new Vector3f(); + private final AoFaceData tmpFace = new AoFaceData(); + + private AoFaceData gatherInsetFace(ModelQuadView quad, BlockPos blockPos, int vertexIndex, Direction lightFace, boolean shade) { + final float w1 = AoNeighborInfo.get(lightFace).getDepth(quad.getX(vertexIndex), quad.getY(vertexIndex), quad.getZ(vertexIndex)); + + if (Mth.equal(w1, 0)) { + return getCachedFaceData(blockPos, lightFace, true, shade); + } else if (Mth.equal(w1, 1)) { + return getCachedFaceData(blockPos, lightFace, false, shade); + } else { + tmpFace.reset(); + final float w0 = 1 - w1; + return AoFaceData.weightedMean(getCachedFaceData(blockPos, lightFace, true, shade), w0, getCachedFaceData(blockPos, lightFace, false, shade), w1, tmpFace); + } + } + + /** + * Calculates the light data for a quad that does not follow any grid and is not parallel to it's light face. + * Flags: !IS_ALIGNED, !IS_PARTIAL, !IS_FULL + */ + private void applyIrregularFace(BlockPos blockPos, ModelQuadView quad, QuadLightData out, boolean shade) { + final float[] w = this.weights; + final float[] aoResult = out.br; + final int[] lightResult = out.lm; + + for (int i = 0; i < 4; i++) { + // TODO: Avoid this if the accurate normal is the face normal + Vector3f normal = NormI8.unpack(quad.getAccurateNormal(i), vertexNormal); + float ao = 0, sky = 0, block = 0, maxAo = 0; + float maxSky = 0, maxBlock = 0; + + final float x = normal.x(); + + if (!Mth.equal(0f, x)) { + final Direction face = x > 0 ? Direction.EAST : Direction.WEST; + final AoFaceData fd = gatherInsetFace(quad, blockPos, i, face, shade); + AoNeighborInfo.get(face).calculateCornerWeights(quad.getX(i), quad.getY(i), quad.getZ(i), w); + final float n = x * x; + final float a = fd.getBlendedShade(w); + final float s = fd.getBlendedSkyLight(w); + final float b = fd.getBlendedBlockLight(w); + ao += n * a; + sky += n * s; + block += n * b; + maxAo = a; + maxSky = s; + maxBlock = b; + } + + final float y = normal.y(); + + if (!Mth.equal(0f, y)) { + final Direction face = y > 0 ? Direction.UP : Direction.DOWN; + final AoFaceData fd = gatherInsetFace(quad, blockPos, i, face, shade); + AoNeighborInfo.get(face).calculateCornerWeights(quad.getX(i), quad.getY(i), quad.getZ(i), w); + final float n = y * y; + final float a = fd.getBlendedShade(w); + final float s = fd.getBlendedSkyLight(w); + final float b = fd.getBlendedBlockLight(w); + ao += n * a; + sky += n * s; + block += n * b; + maxAo = Math.max(maxAo, a); + maxSky = Math.max(maxSky, s); + maxBlock = Math.max(maxBlock, b); + } + + final float z = normal.z(); + + if (!Mth.equal(0f, z)) { + final Direction face = z > 0 ? Direction.SOUTH : Direction.NORTH; + final AoFaceData fd = gatherInsetFace(quad, blockPos, i, face, shade); + AoNeighborInfo.get(face).calculateCornerWeights(quad.getX(i), quad.getY(i), quad.getZ(i), w); + final float n = z * z; + final float a = fd.getBlendedShade(w); + final float s = fd.getBlendedSkyLight(w); + final float b = fd.getBlendedBlockLight(w); + ao += n * a; + sky += n * s; + block += n * b; + maxAo = Math.max(maxAo, a); + maxSky = Math.max(maxSky, s); + maxBlock = Math.max(maxBlock, b); + } + + aoResult[i] = (ao + maxAo) * 0.5f; + lightResult[i] = (((int) ((sky + maxSky) * 0.5f) & 0xF0) << 16) | ((int) ((block + maxBlock) * 0.5f) & 0xF0); + } + } + + private void applySidedBrightness(AoFaceData out, Direction face, boolean shade) { float brightness = this.lightCache.getLevel().getShade(face, shade); - float[] br = out.br; + float[] ao = out.ao; - for (int i = 0; i < br.length; i++) { - br[i] *= brightness; + for (int i = 0; i < ao.length; i++) { + ao[i] *= brightness; } } /** * Returns the cached data for a given facing or calculates it if it hasn't been cached. */ - private AoFaceData getCachedFaceData(BlockPos pos, Direction face, boolean offset) { + private AoFaceData getCachedFaceData(BlockPos pos, Direction face, boolean offset, boolean shade) { AoFaceData data = this.cachedFaceData[offset ? face.ordinal() : face.ordinal() + 6]; if (!data.hasLightData()) { data.initLightData(this.lightCache, pos, face, offset); + + this.applySidedBrightness(data, face, shade); + + data.unpackLightData(); } return data; diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/BakedQuadView.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/BakedQuadView.java similarity index 91% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/quad/BakedQuadView.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/BakedQuadView.java index b95ee43fa2..8acff21468 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/BakedQuadView.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/BakedQuadView.java @@ -5,7 +5,7 @@ public interface BakedQuadView extends ModelQuadView { ModelQuadFacing getNormalFace(); - int getNormal(); + int getFaceNormal(); boolean hasShade(); } diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/ModelQuad.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/ModelQuad.java similarity index 84% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/quad/ModelQuad.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/ModelQuad.java index 3b19d98698..d5f650313d 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/ModelQuad.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/ModelQuad.java @@ -16,6 +16,7 @@ public class ModelQuad implements ModelQuadViewMutable { private Direction direction; private int colorIdx; + private int faceNormal; @Override public void setX(int idx, float x) { @@ -52,6 +53,16 @@ public void setLight(int idx, int light) { this.data[ModelQuadUtil.vertexOffset(idx) + ModelQuadUtil.LIGHT_INDEX] = light; } + @Override + public void setNormal(int idx, int normal) { + this.data[ModelQuadUtil.vertexOffset(idx) + ModelQuadUtil.NORMAL_INDEX] = normal; + } + + @Override + public void setFaceNormal(int normal) { + this.faceNormal = normal; + } + @Override public void setFlags(int flags) { this.flags = flags; @@ -107,6 +118,21 @@ public float getTexV(int idx) { return Float.intBitsToFloat(this.data[ModelQuadUtil.vertexOffset(idx) + ModelQuadUtil.TEXTURE_INDEX + 1]); } + @Override + public int getVertexNormal(int idx) { + return this.data[ModelQuadUtil.vertexOffset(idx) + ModelQuadUtil.NORMAL_INDEX]; + } + + @Override + public int getFaceNormal() { + return faceNormal; + } + + @Override + public int getLight(int idx) { + return this.data[ModelQuadUtil.vertexOffset(idx) + ModelQuadUtil.LIGHT_INDEX]; + } + @Override public int getFlags() { return this.flags; diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/ModelQuadView.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/ModelQuadView.java similarity index 81% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/quad/ModelQuadView.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/ModelQuadView.java index fb0a0ee88b..08369fb0af 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/ModelQuadView.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/ModelQuadView.java @@ -39,6 +39,21 @@ public interface ModelQuadView { */ float getTexV(int idx); + /** + * @return The packed normal set for the vertex at index {@param idx}. + */ + int getVertexNormal(int idx); + + /** + * @return The computed normal. + */ + int getFaceNormal(); + + /** + * @return The packed light set for the vertex at index {@param idx}. + */ + int getLight(int idx); + /** * @return The integer bit flags containing the {@link ModelQuadFlags} for this quad */ @@ -101,4 +116,15 @@ default int calculateNormal() { return NormI8.pack(normX, normY, normZ); } + + /** + * Returns the most accurate normal value for this vertex. + * @param i The vertex index. + * @return the per-vertex normal if it is set, otherwise the face normal. + */ + default int getAccurateNormal(int i) { + int normal = getVertexNormal(i); + + return normal == 0 ? getFaceNormal() : normal; + } } diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/ModelQuadViewMutable.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/ModelQuadViewMutable.java similarity index 86% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/quad/ModelQuadViewMutable.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/ModelQuadViewMutable.java index 13d0345481..30753db6ca 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/ModelQuadViewMutable.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/ModelQuadViewMutable.java @@ -43,6 +43,16 @@ public interface ModelQuadViewMutable extends ModelQuadView { */ void setLight(int idx, int light); + /** + * Sets the normal vector of the vertex at index {@param idx} to the value {@param normal} + */ + void setNormal(int idx, int normal); + + /** + * Sets the normal vector of the face to the value {@param normal} + */ + void setFaceNormal(int normal); + /** * Sets the bit-flag field which contains the {@link ModelQuadFlags} for this quad */ diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/blender/BlendedColorProvider.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/blender/BlendedColorProvider.java similarity index 98% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/quad/blender/BlendedColorProvider.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/blender/BlendedColorProvider.java index e74314d643..38e58f9fdb 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/blender/BlendedColorProvider.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/blender/BlendedColorProvider.java @@ -66,7 +66,7 @@ private int getVertexColor(LevelSlice slice, BlockPos pos, ModelQuadView quad, i x0 = z0; } - return ColorARGB.toABGR(x0); + return x0; } protected abstract int getColor(LevelSlice slice, int x, int y, int z); diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadFacing.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadFacing.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadFacing.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadFacing.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadFlags.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadFlags.java similarity index 96% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadFlags.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadFlags.java index 6b46654731..856aed983c 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadFlags.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadFlags.java @@ -20,6 +20,12 @@ public class ModelQuadFlags { */ public static final int IS_ALIGNED = 0b100; + /** + * Number of flags. + */ + public static final int FLAG_BIT_COUNT = 3; + + /** * @return True if the bit-flag of {@link ModelQuadFlags} contains the given flag */ diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadOrientation.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadOrientation.java similarity index 63% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadOrientation.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadOrientation.java index 21e5c6121f..19c7e61820 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadOrientation.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadOrientation.java @@ -1,5 +1,7 @@ package net.caffeinemc.mods.sodium.client.model.quad.properties; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; + /** * Defines the orientation of vertices in a model quad. This information be used to re-orient the quad's vertices to a * consistent order, eliminating a number of shading issues caused by anisotropy problems. @@ -43,4 +45,27 @@ public static ModelQuadOrientation orientByBrightness(float[] brightnesses, int[ return FLIP; } } + + /** + * Determines the orientation of the vertices in the quad. + */ + public static ModelQuadOrientation orientByBrightness(float[] brightnesses, QuadView quad) { + // If one side of the quad is brighter, flip the sides + float br02 = brightnesses[0] + brightnesses[2]; + float br13 = brightnesses[1] + brightnesses[3]; + if (br02 > br13) { + return NORMAL; + } else if (br02 < br13) { + return FLIP; + } + + // If one side of the quad is darker, flip the sides + int lm02 = quad.lightmap(0) + quad.lightmap(2); + int lm13 = quad.lightmap(1) + quad.lightmap(3); + if (lm02 <= lm13) { + return NORMAL; + } else { + return FLIP; + } + } } diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadWinding.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadWinding.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadWinding.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadWinding.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/SodiumWorldRenderer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/SodiumWorldRenderer.java similarity index 92% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/SodiumWorldRenderer.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/SodiumWorldRenderer.java index 9d8fcfae23..b6ebe820f1 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/render/SodiumWorldRenderer.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/SodiumWorldRenderer.java @@ -45,6 +45,7 @@ import java.util.Collection; import java.util.Iterator; import java.util.SortedSet; +import java.util.function.Consumer; /** * Provides an extension to vanilla's {@link LevelRenderer}. @@ -405,6 +406,49 @@ private static void renderBlockEntity(PoseStack matrices, matrices.popPose(); } + public void iterateVisibleBlockEntities(Consumer blockEntityConsumer) { + SortedRenderLists renderLists = this.renderSectionManager.getRenderLists(); + Iterator renderListIterator = renderLists.iterator(); + + while (renderListIterator.hasNext()) { + var renderList = renderListIterator.next(); + + var renderRegion = renderList.getRegion(); + var renderSectionIterator = renderList.sectionsWithEntitiesIterator(); + + if (renderSectionIterator == null) { + continue; + } + + while (renderSectionIterator.hasNext()) { + var renderSectionId = renderSectionIterator.nextByteAsInt(); + var renderSection = renderRegion.getSection(renderSectionId); + + var blockEntities = renderSection.getCulledBlockEntities(); + + if (blockEntities == null) { + continue; + } + + for (BlockEntity blockEntity : blockEntities) { + blockEntityConsumer.accept(blockEntity); + } + } + } + + for (var renderSection : this.renderSectionManager.getSectionsWithGlobalEntities()) { + var blockEntities = renderSection.getGlobalBlockEntities(); + + if (blockEntities == null) { + continue; + } + + for (BlockEntity blockEntity : blockEntities) { + blockEntityConsumer.accept(blockEntity); + } + } + } + // the volume of a section multiplied by the number of sections to be checked at most private static final double MAX_ENTITY_CHECK_VOLUME = 16 * 16 * 16 * 15; diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ChunkRenderMatrices.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ChunkRenderMatrices.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ChunkRenderMatrices.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ChunkRenderMatrices.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ChunkRenderer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ChunkRenderer.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ChunkRenderer.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ChunkRenderer.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ChunkUpdateType.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ChunkUpdateType.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ChunkUpdateType.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ChunkUpdateType.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/DefaultChunkRenderer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/DefaultChunkRenderer.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/DefaultChunkRenderer.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/DefaultChunkRenderer.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/LocalSectionIndex.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/LocalSectionIndex.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/LocalSectionIndex.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/LocalSectionIndex.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/NonStoringBuilderPool.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/NonStoringBuilderPool.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/NonStoringBuilderPool.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/NonStoringBuilderPool.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSection.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSection.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSection.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSection.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSectionFlags.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSectionFlags.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSectionFlags.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSectionFlags.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ShaderChunkRenderer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ShaderChunkRenderer.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ShaderChunkRenderer.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/ShaderChunkRenderer.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/SharedQuadIndexBuffer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/SharedQuadIndexBuffer.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/SharedQuadIndexBuffer.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/SharedQuadIndexBuffer.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/BuilderTaskOutput.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/BuilderTaskOutput.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/BuilderTaskOutput.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/BuilderTaskOutput.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildBuffers.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildBuffers.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildBuffers.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildBuffers.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildContext.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildContext.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildContext.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildContext.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildOutput.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildOutput.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildOutput.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildOutput.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkSortOutput.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkSortOutput.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkSortOutput.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkSortOutput.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/buffers/BakedChunkModelBuilder.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/buffers/BakedChunkModelBuilder.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/buffers/BakedChunkModelBuilder.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/buffers/BakedChunkModelBuilder.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/buffers/ChunkModelBuilder.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/buffers/ChunkModelBuilder.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/buffers/ChunkModelBuilder.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/buffers/ChunkModelBuilder.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/buffers/ChunkVertexConsumer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/buffers/ChunkVertexConsumer.java similarity index 88% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/buffers/ChunkVertexConsumer.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/buffers/ChunkVertexConsumer.java index bdafe5bb4a..25ff13d50c 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/buffers/ChunkVertexConsumer.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/buffers/ChunkVertexConsumer.java @@ -9,7 +9,8 @@ import net.caffeinemc.mods.sodium.client.render.chunk.vertex.format.ChunkVertexEncoder; import net.caffeinemc.mods.sodium.api.util.ColorABGR; import net.caffeinemc.mods.sodium.api.util.ColorARGB; -import net.caffeinemc.mods.sodium.client.render.frapi.SpriteFinderCache; +import net.caffeinemc.mods.sodium.client.services.PlatformBlockAccess; +import net.caffeinemc.mods.sodium.client.services.PlatformTextureAccess; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.core.Direction; import org.jetbrains.annotations.NotNull; @@ -26,8 +27,6 @@ public class ChunkVertexConsumer implements VertexConsumer { private final ChunkVertexEncoder.Vertex[] vertices = ChunkVertexEncoder.Vertex.uninitializedQuad(); private Material material; - private boolean isColorFixed; - private int fixedColor = 0xFFFFFFFF; private int vertexIndex; private int writtenAttributes; private TranslucentGeometryCollector collector; @@ -44,9 +43,9 @@ public void setData(Material material, TranslucentGeometryCollector collector) { @Override public @NotNull VertexConsumer addVertex(float x, float y, float z) { ChunkVertexEncoder.Vertex vertex = this.vertices[this.vertexIndex]; - vertex.x = (float) x; - vertex.y = (float) y; - vertex.z = (float) z; + vertex.x = x; + vertex.y = y; + vertex.z = z; this.writtenAttributes |= ATTRIBUTE_POSITION_BIT; return potentiallyEndVertex(); } @@ -54,10 +53,6 @@ public void setData(Material material, TranslucentGeometryCollector collector) { // Writing color ignores alpha since alpha is used as a color multiplier by Sodium. @Override public @NotNull VertexConsumer setColor(int red, int green, int blue, int alpha) { - if (this.isColorFixed) { - throw new IllegalStateException(); - } - ChunkVertexEncoder.Vertex vertex = this.vertices[this.vertexIndex]; vertex.color = ColorABGR.pack(red, green, blue, 0xFF); this.writtenAttributes |= ATTRIBUTE_COLOR_BIT; @@ -66,10 +61,6 @@ public void setData(Material material, TranslucentGeometryCollector collector) { @Override public @NotNull VertexConsumer setColor(float red, float green, float blue, float alpha) { - if (this.isColorFixed) { - throw new IllegalStateException(); - } - ChunkVertexEncoder.Vertex vertex = this.vertices[this.vertexIndex]; vertex.color = ColorABGR.pack(red, green, blue, 1); this.writtenAttributes |= ATTRIBUTE_COLOR_BIT; @@ -78,10 +69,6 @@ public void setData(Material material, TranslucentGeometryCollector collector) { @Override public @NotNull VertexConsumer setColor(int argb) { - if (this.isColorFixed) { - throw new IllegalStateException(); - } - ChunkVertexEncoder.Vertex vertex = this.vertices[this.vertexIndex]; vertex.color = ColorARGB.toABGR(argb, 0xFF); this.writtenAttributes |= ATTRIBUTE_COLOR_BIT; @@ -131,12 +118,6 @@ public void setData(Material material, TranslucentGeometryCollector collector) { } public VertexConsumer potentiallyEndVertex() { - if (this.isColorFixed) { - ChunkVertexEncoder.Vertex vertex = this.vertices[this.vertexIndex]; - vertex.color = this.fixedColor; - this.writtenAttributes |= ATTRIBUTE_COLOR_BIT; - } - if (this.writtenAttributes != REQUIRED_ATTRIBUTES) { return this; } @@ -163,7 +144,7 @@ public VertexConsumer potentiallyEndVertex() { v += vertex.v; } - TextureAtlasSprite sprite = SpriteFinderCache.forBlockAtlas().find(u * 0.25f, v * 0.25f); + TextureAtlasSprite sprite = PlatformTextureAccess.getInstance().findInBlockAtlas(u * 0.25f, v * 0.25f); if (sprite != null) { this.modelBuilder.addSprite(sprite); diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkBuilder.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkBuilder.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkBuilder.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkBuilder.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJob.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJob.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJob.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJob.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobCollector.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobCollector.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobCollector.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobCollector.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobQueue.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobQueue.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobQueue.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobQueue.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobResult.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobResult.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobResult.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobResult.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobTyped.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobTyped.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobTyped.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobTyped.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockOcclusionCache.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockOcclusionCache.java similarity index 95% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockOcclusionCache.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockOcclusionCache.java index 432aae1259..294b2b96e4 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockOcclusionCache.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockOcclusionCache.java @@ -2,6 +2,7 @@ import it.unimi.dsi.fastutil.Hash; import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenCustomHashMap; +import net.caffeinemc.mods.sodium.client.services.PlatformBlockAccess; import net.caffeinemc.mods.sodium.client.util.DirectionUtil; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -44,7 +45,7 @@ public boolean shouldDrawSide(BlockState selfState, BlockGetter view, BlockPos s // Blocks can define special behavior to control whether faces are rendered. // This is mostly used by transparent blocks (Leaves, Glass, etc.) to not render interior faces between blocks // of the same type. - if (selfState.skipRendering(otherState, facing)) { + if (selfState.skipRendering(otherState, facing) || PlatformBlockAccess.getInstance().shouldSkipRender(view, selfState, otherState, selfPos, otherPos, facing)) { return false; } diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderCache.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderCache.java similarity index 90% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderCache.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderCache.java index cdeb4b969d..c183c305e3 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderCache.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderCache.java @@ -3,6 +3,7 @@ import net.caffeinemc.mods.sodium.client.model.color.ColorProviderRegistry; import net.caffeinemc.mods.sodium.client.model.light.LightPipelineProvider; import net.caffeinemc.mods.sodium.client.model.light.data.ArrayLightDataCache; +import net.caffeinemc.mods.sodium.client.services.PlatformLevelAccess; import net.caffeinemc.mods.sodium.client.world.LevelSlice; import net.caffeinemc.mods.sodium.client.world.cloned.ChunkRenderContext; import net.minecraft.client.Minecraft; @@ -27,7 +28,7 @@ public BlockRenderCache(Minecraft minecraft, ClientLevel level) { var colorRegistry = new ColorProviderRegistry(minecraft.getBlockColors()); this.blockRenderer = new BlockRenderer(colorRegistry, lightPipelineProvider); - this.fluidRenderer = new FluidRenderer(colorRegistry, lightPipelineProvider); + this.fluidRenderer = PlatformLevelAccess.getInstance().createPlatformFluidRenderer(colorRegistry, lightPipelineProvider); this.blockModels = minecraft.getModelManager().getBlockModelShaper(); } diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderContext.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderContext.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderContext.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderContext.java diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderer.java new file mode 100644 index 0000000000..9d29915ec9 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderer.java @@ -0,0 +1,186 @@ +package net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline; + +import net.caffeinemc.mods.sodium.client.model.color.ColorProvider; +import net.caffeinemc.mods.sodium.client.model.color.ColorProviderRegistry; +import net.caffeinemc.mods.sodium.client.model.light.LightMode; +import net.caffeinemc.mods.sodium.client.model.light.LightPipelineProvider; +import net.caffeinemc.mods.sodium.client.model.quad.properties.ModelQuadFacing; +import net.caffeinemc.mods.sodium.client.model.quad.properties.ModelQuadOrientation; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildBuffers; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.buffers.ChunkModelBuilder; +import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.DefaultMaterials; +import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.Material; +import net.caffeinemc.mods.sodium.client.render.chunk.translucent_sorting.TranslucentGeometryCollector; +import net.caffeinemc.mods.sodium.client.render.chunk.vertex.builder.ChunkMeshBufferBuilder; +import net.caffeinemc.mods.sodium.client.render.chunk.vertex.format.ChunkVertexEncoder; +import net.caffeinemc.mods.sodium.client.render.frapi.helper.ColorHelper; +import net.caffeinemc.mods.sodium.client.render.frapi.mesh.MutableQuadViewImpl; +import net.caffeinemc.mods.sodium.client.render.frapi.render.AbstractBlockRenderContext; +import net.caffeinemc.mods.sodium.client.services.PlatformModelAccess; +import net.caffeinemc.mods.sodium.client.services.PlatformTextureAccess; +import net.caffeinemc.mods.sodium.client.services.SodiumModelData; +import net.caffeinemc.mods.sodium.client.world.LevelSlice; +import net.caffeinemc.mods.sodium.api.util.ColorARGB; +import net.fabricmc.fabric.api.renderer.v1.material.BlendMode; +import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; +import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; +import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.client.renderer.ItemBlockRenderTypes; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.SingleThreadedRandomSource; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.Nullable; +import org.joml.Vector3f; + +public class BlockRenderer extends AbstractBlockRenderContext { + private final ColorProviderRegistry colorProviderRegistry; + private final int[] vertexColors = new int[4]; + private final ChunkVertexEncoder.Vertex[] vertices = ChunkVertexEncoder.Vertex.uninitializedQuad(); + + private ChunkBuildBuffers buffers; + + private final Vector3f posOffset = new Vector3f(); + @Nullable + private ColorProvider colorProvider; + private TranslucentGeometryCollector collector; + + public BlockRenderer(ColorProviderRegistry colorRegistry, LightPipelineProvider lighters) { + this.colorProviderRegistry = colorRegistry; + this.lighters = lighters; + + this.random = new SingleThreadedRandomSource(42L); + } + + public void prepare(ChunkBuildBuffers buffers, LevelSlice level, TranslucentGeometryCollector collector) { + this.buffers = buffers; + this.level = level; + this.collector = collector; + this.slice = level; + } + + public void release() { + this.buffers = null; + this.level = null; + this.collector = null; + this.slice = null; + } + + public void renderModel(BakedModel model, BlockState state, BlockPos pos, BlockPos origin) { + this.state = state; + this.pos = pos; + + this.randomSeed = state.getSeed(pos); + + this.posOffset.set(origin.getX(), origin.getY(), origin.getZ()); + if (state.hasOffsetFunction()) { + Vec3 modelOffset = state.getOffset(this.level, pos); + this.posOffset.add((float) modelOffset.x, (float) modelOffset.y, (float) modelOffset.z); + } + + this.colorProvider = this.colorProviderRegistry.getColorProvider(state.getBlock()); + + type = ItemBlockRenderTypes.getChunkRenderType(state); + + this.prepareCulling(true); + this.prepareAoInfo(model.useAmbientOcclusion()); + + modelData = PlatformModelAccess.getInstance().getModelData(slice, model, state, pos, slice.getPlatformModelData(pos)); + + Iterable renderTypes = PlatformModelAccess.getInstance().getModelRenderTypes(level, model, state, pos, random, modelData); + + for (RenderType type : renderTypes) { + this.type = type; + ((FabricBakedModel) model).emitBlockQuads(this.level, state, pos, this.randomSupplier, this); + } + + type = null; + modelData = SodiumModelData.EMPTY; + } + + /** + * Process quad, after quad transforms and the culling check have been applied. + */ + @Override + protected void processQuad(MutableQuadViewImpl quad) { + final RenderMaterial mat = quad.material(); + final int colorIndex = mat.disableColorIndex() ? -1 : quad.colorIndex(); + final TriState aoMode = mat.ambientOcclusion(); + final LightMode lightMode; + if (aoMode == TriState.DEFAULT) { + lightMode = this.defaultLightMode; + } else { + lightMode = this.useAmbientOcclusion && aoMode.get() ? LightMode.SMOOTH : LightMode.FLAT; + } + final boolean emissive = mat.emissive(); + + Material material; + + final BlendMode blendMode = mat.blendMode(); + if (blendMode == BlendMode.DEFAULT) { + material = DefaultMaterials.forRenderLayer(type); + } else { + material = DefaultMaterials.forRenderLayer(blendMode.blockRenderLayer == null ? type : blendMode.blockRenderLayer); + } + + ChunkModelBuilder builder = this.buffers.get(material); + + this.colorizeQuad(quad, colorIndex); + this.shadeQuad(quad, lightMode, emissive); + this.bufferQuad(quad, this.quadLightData.br, material, builder); + } + + private void colorizeQuad(MutableQuadViewImpl quad, int colorIndex) { + if (colorIndex != -1) { + ColorProvider colorProvider = this.colorProvider; + + if (colorProvider != null) { + int[] vertexColors = this.vertexColors; + colorProvider.getColors(this.slice, this.pos, this.state, quad, vertexColors); + + for (int i = 0; i < 4; i++) { + // Set alpha to 0xFF in case a quad transform inspects the color. + // We do not support per-vertex alpha, however, so this will get discarded at vertex encoding time. + quad.color(i, ColorHelper.multiplyColor(0xFF000000 | vertexColors[i], quad.color(i))); + } + } + } + } + + private void bufferQuad(MutableQuadViewImpl quad, float[] brightnesses, Material material, ChunkModelBuilder modelBuilder) { + ModelQuadOrientation orientation = defaultLightMode == LightMode.FLAT ? ModelQuadOrientation.NORMAL : ModelQuadOrientation.orientByBrightness(brightnesses, quad); + ChunkVertexEncoder.Vertex[] vertices = this.vertices; + Vector3f offset = this.posOffset; + + for (int dstIndex = 0; dstIndex < 4; dstIndex++) { + int srcIndex = orientation.getVertexIndex(dstIndex); + + ChunkVertexEncoder.Vertex out = vertices[dstIndex]; + out.x = quad.x(srcIndex) + offset.x; + out.y = quad.y(srcIndex) + offset.y; + out.z = quad.z(srcIndex) + offset.z; + + // FRAPI uses ARGB color format; convert to ABGR. + // Due to our vertex format, the alpha from the quad color is ignored entirely. + out.color = ColorARGB.toABGR(quad.color(srcIndex), brightnesses[srcIndex]); + + out.u = quad.u(srcIndex); + out.v = quad.v(srcIndex); + + out.light = quad.lightmap(srcIndex); + } + + ModelQuadFacing normalFace = quad.normalFace(); + + if (material == DefaultMaterials.TRANSLUCENT && collector != null) { + collector.appendQuad(quad.getFaceNormal(), vertices, normalFace); + } + + ChunkMeshBufferBuilder vertexBuffer = modelBuilder.getVertexBuffer(normalFace); + vertexBuffer.push(vertices, material); + + modelBuilder.addSprite(PlatformTextureAccess.getInstance().findInBlockAtlas(quad.getTexU(0), quad.getTexV(0))); + } +} \ No newline at end of file diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/DefaultFluidRenderer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/DefaultFluidRenderer.java similarity index 91% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/DefaultFluidRenderer.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/DefaultFluidRenderer.java index 483eea8418..548461405e 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/DefaultFluidRenderer.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/DefaultFluidRenderer.java @@ -2,6 +2,7 @@ import net.caffeinemc.mods.sodium.api.util.ColorABGR; +import net.caffeinemc.mods.sodium.api.util.ColorARGB; import net.caffeinemc.mods.sodium.api.util.NormI8; import net.caffeinemc.mods.sodium.client.model.color.ColorProvider; import net.caffeinemc.mods.sodium.client.model.color.ColorProviderRegistry; @@ -20,10 +21,9 @@ import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.Material; import net.caffeinemc.mods.sodium.client.render.chunk.translucent_sorting.TranslucentGeometryCollector; import net.caffeinemc.mods.sodium.client.render.chunk.vertex.format.ChunkVertexEncoder; +import net.caffeinemc.mods.sodium.client.services.PlatformBlockAccess; import net.caffeinemc.mods.sodium.client.util.DirectionUtil; import net.caffeinemc.mods.sodium.client.world.LevelSlice; -import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler; -import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.core.BlockPos; @@ -98,7 +98,7 @@ private boolean isSideExposed(BlockAndTintGetter world, int x, int y, int z, Dir return true; } - public void render(LevelSlice level, FluidState fluidState, BlockPos blockPos, BlockPos offset, TranslucentGeometryCollector collector, ChunkModelBuilder meshBuilder, Material material, FluidRenderHandler handler) { + public void render(LevelSlice level, FluidState fluidState, BlockPos blockPos, BlockPos offset, TranslucentGeometryCollector collector, ChunkModelBuilder meshBuilder, Material material, ColorProvider colorProvider, TextureAtlasSprite[] sprites) { int posX = blockPos.getX(); int posY = blockPos.getY(); int posZ = blockPos.getZ(); @@ -119,10 +119,6 @@ public void render(LevelSlice level, FluidState fluidState, BlockPos blockPos, B boolean isWater = fluidState.is(FluidTags.WATER); - final ColorProvider colorProvider = this.getColorProvider(fluid, handler); - - TextureAtlasSprite[] sprites = handler.getFluidSprites(level, blockPos, fluidState); - float fluidHeight = this.fluidHeight(level, fluid, blockPos, Direction.UP); float northWestHeight, southWestHeight, southEastHeight, northEastHeight; if (fluidHeight >= 1.0f) { @@ -234,7 +230,7 @@ && isAlignedEquals(southEastHeight, southWestHeight) setVertex(quad, 3, 1.0F, northEastHeight, 0.0f, u4, v4); } - this.updateQuad(quad, level, blockPos, lighter, Direction.UP, 1.0F, colorProvider, fluidState); + this.updateQuad(quad, level, blockPos, lighter, Direction.UP, ModelQuadFacing.POS_Y, 1.0F, colorProvider, fluidState); this.writeQuad(meshBuilder, collector, material, offset, quad, aligned ? ModelQuadFacing.POS_Y : ModelQuadFacing.UNASSIGNED, false); if (fluidState.shouldRenderBackwardUpFace(level, this.scratchPos.set(posX, posY + 1, posZ))) { @@ -257,7 +253,7 @@ && isAlignedEquals(southEastHeight, southWestHeight) setVertex(quad, 2, 1.0F, yOffset, 0.0f, maxU, minV); setVertex(quad, 3, 1.0F, yOffset, 1.0F, maxU, maxV); - this.updateQuad(quad, level, blockPos, lighter, Direction.DOWN, 1.0F, colorProvider, fluidState); + this.updateQuad(quad, level, blockPos, lighter, Direction.DOWN, ModelQuadFacing.NEG_Y, 1.0F, colorProvider, fluidState); this.writeQuad(meshBuilder, collector, material, offset, quad, ModelQuadFacing.NEG_Y, false); } @@ -330,11 +326,11 @@ && isAlignedEquals(southEastHeight, southWestHeight) boolean isOverlay = false; - if (sprites.length > 2) { + if (sprites.length > 2 && sprites[2] != null) { BlockPos adjPos = this.scratchPos.set(adjX, adjY, adjZ); BlockState adjBlock = level.getBlockState(adjPos); - if (FluidRenderHandlerRegistry.INSTANCE.isBlockTransparent(adjBlock.getBlock())) { + if (PlatformBlockAccess.getInstance().shouldShowFluidOverlay(adjBlock, level, adjPos, fluidState)) { sprite = sprites[2]; isOverlay = true; } @@ -357,7 +353,7 @@ && isAlignedEquals(southEastHeight, southWestHeight) ModelQuadFacing facing = ModelQuadFacing.fromDirection(dir); - this.updateQuad(quad, level, blockPos, lighter, dir, br, colorProvider, fluidState); + this.updateQuad(quad, level, blockPos, lighter, dir, facing, br, colorProvider, fluidState); this.writeQuad(meshBuilder, collector, material, offset, quad, facing, false); if (!isOverlay) { @@ -372,38 +368,28 @@ private static boolean isAlignedEquals(float a, float b) { return Math.abs(a - b) <= ALIGNED_EQUALS_EPSILON; } - private ColorProvider getColorProvider(Fluid fluid, FluidRenderHandler handler) { - var override = this.colorProviderRegistry.getColorProvider(fluid); + private void updateQuad(ModelQuadViewMutable quad, LevelSlice level, BlockPos pos, LightPipeline lighter, Direction dir, ModelQuadFacing facing, float brightness, + ColorProvider colorProvider, FluidState fluidState) { - if (override != null) { - return override; + int normal; + if (facing.isAligned()) { + normal = facing.getPackedAlignedNormal(); + } else { + normal = quad.calculateNormal(); } - return DefaultColorProviders.adapt(handler); - } - - private static FluidRenderHandler getFluidRenderHandler(FluidState fluidState) { - FluidRenderHandler handler = FluidRenderHandlerRegistry.INSTANCE.get(fluidState.getType()); - - // Match the vanilla FluidRenderer's behavior if the handler is null - if (handler == null) { - boolean isLava = fluidState.is(FluidTags.LAVA); - handler = FluidRenderHandlerRegistry.INSTANCE.get(isLava ? Fluids.LAVA : Fluids.WATER); - } - return handler; - } + quad.setFaceNormal(normal); - private void updateQuad(ModelQuadView quad, LevelSlice level, BlockPos pos, LightPipeline lighter, Direction dir, float brightness, - ColorProvider colorProvider, FluidState fluidState) { QuadLightData light = this.quadLightData; - lighter.calculate(quad, pos, light, null, dir, false); + + lighter.calculate(quad, pos, light, null, dir, false, true); colorProvider.getColors(level, pos, fluidState, quad, this.quadColors); // multiply the per-vertex color against the combined brightness // the combined brightness is the per-vertex brightness multiplied by the block's brightness for (int i = 0; i < 4; i++) { - this.quadColors[i] = ColorABGR.withAlpha(this.quadColors[i], light.br[i] * brightness); + this.quadColors[i] = ColorARGB.toABGR(this.quadColors[i], light.br[i] * brightness); } } @@ -431,14 +417,18 @@ private void writeQuad(ChunkModelBuilder builder, TranslucentGeometryCollector c if (material.isTranslucent() && collector != null) { int normal; + if (facing.isAligned()) { normal = facing.getPackedAlignedNormal(); } else { - normal = quad.calculateNormal(); + // This was updated earlier in updateQuad. There is no situation where the normal vector should have changed. + normal = quad.getFaceNormal(); } + if (flip) { normal = NormI8.flipPacked(normal); } + collector.appendQuad(normal, vertices, facing); } diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/FluidRenderer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/FluidRenderer.java new file mode 100644 index 0000000000..5a9a16766d --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/FluidRenderer.java @@ -0,0 +1,14 @@ +package net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline; + +import net.caffeinemc.mods.sodium.client.model.color.ColorProviderRegistry; +import net.caffeinemc.mods.sodium.client.model.light.LightPipelineProvider; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildBuffers; +import net.caffeinemc.mods.sodium.client.render.chunk.translucent_sorting.TranslucentGeometryCollector; +import net.caffeinemc.mods.sodium.client.world.LevelSlice; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; + +public abstract class FluidRenderer { + public abstract void render(LevelSlice level, BlockState blockState, FluidState fluidState, BlockPos blockPos, BlockPos offset, TranslucentGeometryCollector collector, ChunkBuildBuffers buffers); +} diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/tasks/ChunkBuilderMeshingTask.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/tasks/ChunkBuilderMeshingTask.java similarity index 91% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/tasks/ChunkBuilderMeshingTask.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/tasks/ChunkBuilderMeshingTask.java index 1070f0c462..4ab680ef8b 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/tasks/ChunkBuilderMeshingTask.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/tasks/ChunkBuilderMeshingTask.java @@ -9,15 +9,18 @@ import net.caffeinemc.mods.sodium.client.render.chunk.compile.executor.ChunkBuilder; import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.BlockRenderCache; import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.BlockRenderContext; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.BlockRenderer; import net.caffeinemc.mods.sodium.client.render.chunk.data.BuiltSectionInfo; import net.caffeinemc.mods.sodium.client.render.chunk.data.BuiltSectionMeshParts; import net.caffeinemc.mods.sodium.client.render.chunk.terrain.DefaultTerrainRenderPasses; import net.caffeinemc.mods.sodium.client.render.chunk.terrain.TerrainRenderPass; +import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.DefaultMaterials; import net.caffeinemc.mods.sodium.client.render.chunk.translucent_sorting.SortBehavior; import net.caffeinemc.mods.sodium.client.render.chunk.translucent_sorting.SortType; import net.caffeinemc.mods.sodium.client.render.chunk.translucent_sorting.TranslucentGeometryCollector; import net.caffeinemc.mods.sodium.client.render.chunk.translucent_sorting.data.PresentTranslucentData; import net.caffeinemc.mods.sodium.client.render.chunk.translucent_sorting.data.TranslucentData; +import net.caffeinemc.mods.sodium.client.services.PlatformLevelAccess; import net.caffeinemc.mods.sodium.client.util.task.CancellationToken; import net.caffeinemc.mods.sodium.client.world.LevelSlice; import net.caffeinemc.mods.sodium.client.world.cloned.ChunkRenderContext; @@ -77,11 +80,14 @@ public ChunkBuildOutput execute(ChunkBuildContext buildContext, CancellationToke BlockPos.MutableBlockPos blockPos = new BlockPos.MutableBlockPos(minX, minY, minZ); BlockPos.MutableBlockPos modelOffset = new BlockPos.MutableBlockPos(); - TranslucentGeometryCollector collector = null; + TranslucentGeometryCollector collector; if (SodiumClientMod.options().performance.getSortBehavior() != SortBehavior.OFF) { collector = new TranslucentGeometryCollector(render.getPosition()); + } else { + collector = null; } - BlockRenderContext context = new BlockRenderContext(slice, collector); + BlockRenderer blockRenderer = cache.getBlockRenderer(); + blockRenderer.prepare(buffers, slice, collector); try { for (int y = minY; y < maxY; y++) { @@ -102,13 +108,8 @@ public ChunkBuildOutput execute(ChunkBuildContext buildContext, CancellationToke if (blockState.getRenderShape() == RenderShape.MODEL) { BakedModel model = cache.getBlockModels() - .getBlockModel(blockState); - - long seed = blockState.getSeed(blockPos); - - context.update(blockPos, modelOffset, blockState, model, seed); - cache.getBlockRenderer() - .renderModel(context, buffers); + .getBlockModel(blockState); + blockRenderer.renderModel(model, blockState, blockPos, modelOffset); } FluidState fluidState = blockState.getFluidState(); @@ -143,6 +144,11 @@ public ChunkBuildOutput execute(ChunkBuildContext buildContext, CancellationToke throw fillCrashInfo(CrashReport.forThrowable(ex, "Encountered exception while building chunk meshes"), slice, blockPos); } + PlatformLevelAccess.INSTANCE.renderAdditionalRenderers(renderContext.getRenderers(), type -> buffers.get(DefaultMaterials.forRenderLayer(type)).asFallbackVertexConsumer(DefaultMaterials.forRenderLayer(type), collector), + slice); + + blockRenderer.release(); + SortType sortType = SortType.NONE; if (collector != null) { sortType = collector.finishRendering(); diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/tasks/ChunkBuilderSortingTask.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/tasks/ChunkBuilderSortingTask.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/tasks/ChunkBuilderSortingTask.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/tasks/ChunkBuilderSortingTask.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/tasks/ChunkBuilderTask.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/tasks/ChunkBuilderTask.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/tasks/ChunkBuilderTask.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/tasks/ChunkBuilderTask.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/data/BuiltSectionInfo.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/data/BuiltSectionInfo.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/data/BuiltSectionInfo.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/data/BuiltSectionInfo.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/data/BuiltSectionMeshParts.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/data/BuiltSectionMeshParts.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/data/BuiltSectionMeshParts.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/data/BuiltSectionMeshParts.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/data/SectionRenderDataStorage.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/data/SectionRenderDataStorage.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/data/SectionRenderDataStorage.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/data/SectionRenderDataStorage.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/data/SectionRenderDataUnsafe.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/data/SectionRenderDataUnsafe.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/data/SectionRenderDataUnsafe.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/data/SectionRenderDataUnsafe.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/ChunkRenderList.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/ChunkRenderList.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/ChunkRenderList.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/ChunkRenderList.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/ChunkRenderListIterable.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/ChunkRenderListIterable.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/ChunkRenderListIterable.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/ChunkRenderListIterable.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/SortedRenderLists.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/SortedRenderLists.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/SortedRenderLists.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/SortedRenderLists.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/VisibleChunkCollector.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/VisibleChunkCollector.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/VisibleChunkCollector.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/VisibleChunkCollector.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/map/ChunkStatus.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/map/ChunkStatus.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/map/ChunkStatus.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/map/ChunkStatus.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/map/ChunkTracker.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/map/ChunkTracker.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/map/ChunkTracker.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/map/ChunkTracker.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/map/ChunkTrackerHolder.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/map/ChunkTrackerHolder.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/map/ChunkTrackerHolder.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/map/ChunkTrackerHolder.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/map/ClientChunkEventListener.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/map/ClientChunkEventListener.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/map/ClientChunkEventListener.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/map/ClientChunkEventListener.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/GraphDirection.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/GraphDirection.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/GraphDirection.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/GraphDirection.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/GraphDirectionSet.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/GraphDirectionSet.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/GraphDirectionSet.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/GraphDirectionSet.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/OcclusionCuller.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/OcclusionCuller.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/OcclusionCuller.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/OcclusionCuller.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/VisibilityEncoding.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/VisibilityEncoding.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/VisibilityEncoding.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/VisibilityEncoding.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/region/RenderRegion.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/region/RenderRegion.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/region/RenderRegion.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/region/RenderRegion.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/region/RenderRegionManager.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/region/RenderRegionManager.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/region/RenderRegionManager.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/region/RenderRegionManager.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkFogMode.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkFogMode.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkFogMode.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkFogMode.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderBindingPoints.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderBindingPoints.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderBindingPoints.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderBindingPoints.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderFogComponent.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderFogComponent.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderFogComponent.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderFogComponent.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderInterface.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderInterface.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderInterface.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderInterface.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderOptions.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderOptions.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderOptions.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderOptions.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderTextureSlot.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderTextureSlot.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderTextureSlot.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ChunkShaderTextureSlot.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ShaderBindingContext.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ShaderBindingContext.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ShaderBindingContext.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/shader/ShaderBindingContext.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/DefaultTerrainRenderPasses.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/DefaultTerrainRenderPasses.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/DefaultTerrainRenderPasses.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/DefaultTerrainRenderPasses.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/TerrainRenderPass.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/TerrainRenderPass.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/TerrainRenderPass.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/TerrainRenderPass.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/material/DefaultMaterials.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/material/DefaultMaterials.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/material/DefaultMaterials.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/material/DefaultMaterials.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/material/Material.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/material/Material.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/material/Material.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/material/Material.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/material/parameters/AlphaCutoffParameter.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/material/parameters/AlphaCutoffParameter.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/material/parameters/AlphaCutoffParameter.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/material/parameters/AlphaCutoffParameter.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/material/parameters/MaterialParameters.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/material/parameters/MaterialParameters.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/material/parameters/MaterialParameters.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/terrain/material/parameters/MaterialParameters.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/AlignableNormal.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/AlignableNormal.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/AlignableNormal.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/AlignableNormal.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/SortBehavior.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/SortBehavior.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/SortBehavior.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/SortBehavior.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/SortType.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/SortType.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/SortType.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/SortType.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/TQuad.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/TQuad.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/TQuad.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/TQuad.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/TranslucentGeometryCollector.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/TranslucentGeometryCollector.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/TranslucentGeometryCollector.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/TranslucentGeometryCollector.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPBuildFailureException.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPBuildFailureException.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPBuildFailureException.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPBuildFailureException.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPNode.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPNode.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPNode.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPNode.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPResult.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPResult.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPResult.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPResult.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPSortState.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPSortState.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPSortState.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPSortState.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPWorkspace.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPWorkspace.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPWorkspace.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/BSPWorkspace.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/InnerBinaryPartitionBSPNode.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/InnerBinaryPartitionBSPNode.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/InnerBinaryPartitionBSPNode.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/InnerBinaryPartitionBSPNode.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/InnerFixedDoubleBSPNode.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/InnerFixedDoubleBSPNode.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/InnerFixedDoubleBSPNode.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/InnerFixedDoubleBSPNode.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/InnerMultiPartitionBSPNode.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/InnerMultiPartitionBSPNode.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/InnerMultiPartitionBSPNode.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/InnerMultiPartitionBSPNode.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/InnerPartitionBSPNode.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/InnerPartitionBSPNode.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/InnerPartitionBSPNode.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/InnerPartitionBSPNode.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/LeafDoubleBSPNode.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/LeafDoubleBSPNode.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/LeafDoubleBSPNode.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/LeafDoubleBSPNode.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/LeafMultiBSPNode.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/LeafMultiBSPNode.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/LeafMultiBSPNode.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/LeafMultiBSPNode.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/LeafSingleBSPNode.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/LeafSingleBSPNode.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/LeafSingleBSPNode.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/LeafSingleBSPNode.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/Partition.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/Partition.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/Partition.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/bsp_tree/Partition.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/AnyOrderData.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/AnyOrderData.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/AnyOrderData.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/AnyOrderData.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/CombinedCameraPos.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/CombinedCameraPos.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/CombinedCameraPos.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/CombinedCameraPos.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/DynamicBSPData.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/DynamicBSPData.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/DynamicBSPData.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/DynamicBSPData.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/DynamicData.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/DynamicData.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/DynamicData.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/DynamicData.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/DynamicSorter.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/DynamicSorter.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/DynamicSorter.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/DynamicSorter.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/DynamicTopoData.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/DynamicTopoData.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/DynamicTopoData.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/DynamicTopoData.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/MixedDirectionData.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/MixedDirectionData.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/MixedDirectionData.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/MixedDirectionData.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/NoData.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/NoData.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/NoData.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/NoData.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/PresentSortData.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/PresentSortData.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/PresentSortData.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/PresentSortData.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/PresentTranslucentData.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/PresentTranslucentData.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/PresentTranslucentData.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/PresentTranslucentData.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/SortData.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/SortData.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/SortData.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/SortData.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/Sorter.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/Sorter.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/Sorter.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/Sorter.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/SplitDirectionData.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/SplitDirectionData.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/SplitDirectionData.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/SplitDirectionData.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/StaticNormalRelativeData.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/StaticNormalRelativeData.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/StaticNormalRelativeData.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/StaticNormalRelativeData.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/StaticSorter.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/StaticSorter.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/StaticSorter.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/StaticSorter.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/StaticTopoData.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/StaticTopoData.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/StaticTopoData.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/StaticTopoData.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/TopoGraphSorting.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/TopoGraphSorting.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/TopoGraphSorting.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/TopoGraphSorting.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/TranslucentData.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/TranslucentData.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/TranslucentData.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/data/TranslucentData.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/CameraMovement.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/CameraMovement.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/CameraMovement.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/CameraMovement.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/DirectTriggers.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/DirectTriggers.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/DirectTriggers.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/DirectTriggers.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/GFNITriggers.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/GFNITriggers.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/GFNITriggers.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/GFNITriggers.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/GeometryPlanes.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/GeometryPlanes.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/GeometryPlanes.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/GeometryPlanes.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/Group.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/Group.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/Group.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/Group.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/NormalList.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/NormalList.java similarity index 97% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/NormalList.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/NormalList.java index 5c08e996ac..02878e1589 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/NormalList.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/NormalList.java @@ -2,6 +2,7 @@ import java.util.Collection; +import org.joml.Math; import org.joml.Vector3dc; import com.lodborg.intervaltree.DoubleInterval; @@ -69,9 +70,9 @@ public AlignableNormal getNormal() { } private double normalDotDouble(Vector3dc v) { - return Math.fma((double) this.normal.x, v.x(), - Math.fma((double) this.normal.y, v.y(), - (double) this.normal.z * v.z())); + return org.joml.Math.fma(this.normal.x, v.x(), + org.joml.Math.fma(this.normal.y, v.y(), + this.normal.z * v.z())); } void processMovement(SortTriggering ts, CameraMovement movement) { diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/NormalPlanes.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/NormalPlanes.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/NormalPlanes.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/NormalPlanes.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/SortTriggering.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/SortTriggering.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/SortTriggering.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/trigger/SortTriggering.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/builder/ChunkMeshBufferBuilder.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/builder/ChunkMeshBufferBuilder.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/builder/ChunkMeshBufferBuilder.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/builder/ChunkMeshBufferBuilder.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkMeshAttribute.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkMeshAttribute.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkMeshAttribute.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkMeshAttribute.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkMeshFormats.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkMeshFormats.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkMeshFormats.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkMeshFormats.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkVertexEncoder.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkVertexEncoder.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkVertexEncoder.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkVertexEncoder.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkVertexType.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkVertexType.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkVertexType.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/ChunkVertexType.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/impl/CompactChunkVertex.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/impl/CompactChunkVertex.java similarity index 70% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/impl/CompactChunkVertex.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/impl/CompactChunkVertex.java index 3a9918bef2..67dba7bdad 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/impl/CompactChunkVertex.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/vertex/format/impl/CompactChunkVertex.java @@ -12,8 +12,8 @@ public class CompactChunkVertex implements ChunkVertexType { public static final int STRIDE = 20; public static final GlVertexFormat VERTEX_FORMAT = GlVertexFormat.builder(ChunkMeshAttribute.class, STRIDE) - .addElement(ChunkMeshAttribute.POSITION_HI, 0, GlVertexAttributeFormat.UNSIGNED_2_10_10_10_REV, 4, false, false) - .addElement(ChunkMeshAttribute.POSITION_LO, 4, GlVertexAttributeFormat.UNSIGNED_2_10_10_10_REV, 4, false, false) + .addElement(ChunkMeshAttribute.POSITION_HI, 0, GlVertexAttributeFormat.UNSIGNED_INT, 1, false, true) + .addElement(ChunkMeshAttribute.POSITION_LO, 4, GlVertexAttributeFormat.UNSIGNED_INT, 1, false, true) .addElement(ChunkMeshAttribute.COLOR, 8, GlVertexAttributeFormat.UNSIGNED_BYTE, 4, true, false) .addElement(ChunkMeshAttribute.TEXTURE, 12, GlVertexAttributeFormat.UNSIGNED_SHORT, 2, false, true) .addElement(ChunkMeshAttribute.LIGHT_MATERIAL_INDEX, 16, GlVertexAttributeFormat.UNSIGNED_BYTE, 4, false, true) @@ -22,8 +22,8 @@ public class CompactChunkVertex implements ChunkVertexType { private static final int POSITION_MAX_VALUE = 1 << 20; private static final int TEXTURE_MAX_VALUE = 1 << 15; - private static final float MODEL_TRANSLATION = 8.0f; - private static final float MODEL_SCALE = 32.0f; + private static final float MODEL_ORIGIN = 8.0f; + private static final float MODEL_RANGE = 32.0f; @Override public GlVertexFormat getVertexFormat() { @@ -48,9 +48,9 @@ public ChunkVertexEncoder getEncoder() { for (int i = 0; i < 4; i++) { var vertex = vertices[i]; - int x = encodePosition(vertex.x); - int y = encodePosition(vertex.y); - int z = encodePosition(vertex.z); + int x = quantizePosition(vertex.x); + int y = quantizePosition(vertex.y); + int z = quantizePosition(vertex.z); int u = encodeTexture(texCentroidU, vertex.u); int v = encodeTexture(texCentroidV, vertex.v); @@ -82,8 +82,12 @@ private static int packPositionLo(int x, int y, int z) { ((z & 0x3FF) << 20); } - private static int encodePosition(float position) { - return Math.round((position + MODEL_TRANSLATION) * (POSITION_MAX_VALUE / MODEL_SCALE)); + private static int quantizePosition(float position) { + return ((int) (normalizePosition(position) * POSITION_MAX_VALUE)) & 0xFFFFF; + } + + private static float normalizePosition(float v) { + return (MODEL_ORIGIN + v) / MODEL_RANGE; } private static int packTexture(int u, int v) { @@ -91,22 +95,16 @@ private static int packTexture(int u, int v) { } private static int encodeTexture(float center, float x) { - // Normally, the UV coordinates are shrunk towards the center of the texture by a very small epsilon to avoid - // texture bleeding between sprites in the atlas. When compressing to smaller integer formats, this creates a - // problem, since the very small offsets can not be encoded without using a significant number of bits. - // - // Rather than encoding very small epsilons, we use a single bit to represent the sign of a constant bias - // value, which is then applied in the shader code. The sign of the bias is determined by comparing the - // coordinates to the center point of the texture region. + // Shrink the texture coordinates (towards the center of the mapped texture region) by the minimum + // addressable unit (after quantization.) Then, encode the sign of the bias that was used, and apply + // the inverse transformation on the GPU with a small epsilon. // - // By always shrinking the texture coordinates at least one unit, we also avoid needing to encode both x=0.0 and - // x=1.0, which normally requires an extra bit to represent. + // This makes it possible to use much smaller epsilons for avoiding texture bleed, since the epsilon is no + // longer encoded into the vertex data (instead, we only store the sign.) int bias = (x < center) ? 1 : -1; int quantized = floorInt(x * TEXTURE_MAX_VALUE) + bias; - // When packing the values into a 16-bit unsigned integer, the 15-bit quantized value is shifted to the left by - // one, and the least-significant bit (which is now zero-filled) is used to store the sign of the bias. - return ((quantized & 0x7FFF) << 1) | (bias >>> 31); + return (quantized & 0x7FFF) | (sign(bias) << 15); } private static int encodeLight(int light) { @@ -122,6 +120,12 @@ private static int packLightAndData(int light, int material, int section) { ((section & 0xFF) << 24); } + private static int sign(int x) { + // Shift the sign-bit to the least significant bit's position + // (0) if positive, (1) if negative + return (x >>> 31); + } + private static int floorInt(float x) { return (int) Math.floor(x); } diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/SodiumRenderer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/SodiumRenderer.java new file mode 100644 index 0000000000..7b39a52063 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/SodiumRenderer.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.client.render.frapi; + +import net.caffeinemc.mods.sodium.client.render.frapi.material.MaterialFinderImpl; +import net.caffeinemc.mods.sodium.client.render.frapi.material.RenderMaterialImpl; +import net.caffeinemc.mods.sodium.client.render.frapi.mesh.MeshBuilderImpl; +import net.fabricmc.fabric.api.renderer.v1.Renderer; +import net.fabricmc.fabric.api.renderer.v1.material.MaterialFinder; +import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; +import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder; +import net.minecraft.resources.ResourceLocation; + +import java.util.HashMap; + +/** + * The Sodium renderer implementation. + */ +public class SodiumRenderer implements Renderer { + public static final SodiumRenderer INSTANCE = new SodiumRenderer(); + + public static final RenderMaterial STANDARD_MATERIAL = INSTANCE.materialFinder().find(); + + static { + INSTANCE.registerMaterial(RenderMaterial.MATERIAL_STANDARD, STANDARD_MATERIAL); + } + + private final HashMap materialMap = new HashMap<>(); + + private SodiumRenderer() { } + + @Override + public MeshBuilder meshBuilder() { + return new MeshBuilderImpl(); + } + + @Override + public MaterialFinder materialFinder() { + return new MaterialFinderImpl(); + } + + @Override + public RenderMaterial materialById(ResourceLocation id) { + return materialMap.get(id); + } + + @Override + public boolean registerMaterial(ResourceLocation id, RenderMaterial material) { + if (materialMap.containsKey(id)) return false; + + // cast to prevent acceptance of impostor implementations + materialMap.put(id, (RenderMaterialImpl) material); + return true; + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/helper/ColorHelper.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/helper/ColorHelper.java new file mode 100644 index 0000000000..9961263598 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/helper/ColorHelper.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.client.render.frapi.helper; + +import java.nio.ByteOrder; + +/** + * Static routines of general utility for renderer implementations. + * Renderers are not required to use these helpers, but they were + * designed to be usable without the default renderer. + */ +public abstract class ColorHelper { + private ColorHelper() { } + + private static final boolean BIG_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; + + /** Component-wise multiply. Components need to be in same order in both inputs! */ + public static int multiplyColor(int color1, int color2) { + if (color1 == -1) { + return color2; + } else if (color2 == -1) { + return color1; + } + + final int alpha = ((color1 >>> 24) & 0xFF) * ((color2 >>> 24) & 0xFF) / 0xFF; + final int red = ((color1 >>> 16) & 0xFF) * ((color2 >>> 16) & 0xFF) / 0xFF; + final int green = ((color1 >>> 8) & 0xFF) * ((color2 >>> 8) & 0xFF) / 0xFF; + final int blue = (color1 & 0xFF) * (color2 & 0xFF) / 0xFF; + + return (alpha << 24) | (red << 16) | (green << 8) | blue; + } + + /** Multiplies three lowest components by shade. High byte (usually alpha) unchanged. */ + public static int multiplyRGB(int color, float shade) { + final int alpha = ((color >>> 24) & 0xFF); + final int red = (int) (((color >>> 16) & 0xFF) * shade); + final int green = (int) (((color >>> 8) & 0xFF) * shade); + final int blue = (int) ((color & 0xFF) * shade); + + return (alpha << 24) | (red << 16) | (green << 8) | blue; + } + + /** + * Component-wise max. + */ + public static int maxBrightness(int b0, int b1) { + if (b0 == 0) return b1; + if (b1 == 0) return b0; + + return Math.max(b0 & 0xFFFF, b1 & 0xFFFF) | Math.max(b0 & 0xFFFF0000, b1 & 0xFFFF0000); + } + + /* + Renderer color format: ARGB (0xAARRGGBB) + Vanilla color format (little endian): ABGR (0xAABBGGRR) + Vanilla color format (big endian): RGBA (0xRRGGBBAA) + + Why does the vanilla color format change based on endianness? + See VertexConsumer#quad. Quad data is loaded as integers into + a native byte order buffer. Color is read directly from bytes + 12, 13, 14 of each vertex. A different byte order will yield + different results. + + The renderer always uses ARGB because the API color methods + always consume and return ARGB. Vanilla block and item colors + also use ARGB. + */ + + /** + * Converts from ARGB color to ABGR color if little endian or RGBA color if big endian. + */ + public static int toVanillaColor(int color) { + if (color == -1) { + return -1; + } + + if (BIG_ENDIAN) { + // ARGB to RGBA + return ((color & 0x00FFFFFF) << 8) | ((color & 0xFF000000) >>> 24); + } else { + // ARGB to ABGR + return (color & 0xFF00FF00) | ((color & 0x00FF0000) >>> 16) | ((color & 0x000000FF) << 16); + } + } + + /** + * Converts to ARGB color from ABGR color if little endian or RGBA color if big endian. + */ + public static int fromVanillaColor(int color) { + if (color == -1) { + return -1; + } + + if (BIG_ENDIAN) { + // RGBA to ARGB + return ((color & 0xFFFFFF00) >>> 8) | ((color & 0x000000FF) << 24); + } else { + // ABGR to ARGB + return (color & 0xFF00FF00) | ((color & 0x00FF0000) >>> 16) | ((color & 0x000000FF) << 16); + } + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/helper/GeometryHelper.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/helper/GeometryHelper.java new file mode 100644 index 0000000000..da25fe4eda --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/helper/GeometryHelper.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.client.render.frapi.helper; + +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import org.joml.Vector3f; + +/** + * Static routines of general utility for renderer implementations. + * Renderers are not required to use these helpers, but they were + * designed to be usable without the default renderer. + */ +public abstract class GeometryHelper { + private GeometryHelper() { } + + /** + * Returns true if quad is parallel to the given face. + * Does not validate quad winding order. + * Expects convex quads with all points co-planar. + */ + public static boolean isQuadParallelToFace(Direction face, QuadView quad) { + int i = face.getAxis().ordinal(); + final float val = quad.posByIndex(0, i); + return Mth.equal(val, quad.posByIndex(1, i)) && Mth.equal(val, quad.posByIndex(2, i)) && Mth.equal(val, quad.posByIndex(3, i)); + } + + /** + * Identifies the face to which the quad is most closely aligned. + * This mimics the value that {@link BakedQuad#getDirection()} returns, and is + * used in the vanilla renderer for all diffuse lighting. + * + *

Derived from the quad face normal and expects convex quads with all points co-planar. + */ + public static Direction lightFace(QuadView quad) { + final Vector3f normal = quad.faceNormal(); + return switch (GeometryHelper.longestAxis(normal)) { + case X -> normal.x() > 0 ? Direction.EAST : Direction.WEST; + case Y -> normal.y() > 0 ? Direction.UP : Direction.DOWN; + case Z -> normal.z() > 0 ? Direction.SOUTH : Direction.NORTH; + default -> + // handle WTF case + Direction.UP; + }; + } + + /** + * @see #longestAxis(float, float, float) + */ + public static Direction.Axis longestAxis(Vector3f vec) { + return longestAxis(vec.x(), vec.y(), vec.z()); + } + + /** + * Identifies the largest (max absolute magnitude) component (X, Y, Z) in the given vector. + */ + public static Direction.Axis longestAxis(float normalX, float normalY, float normalZ) { + Direction.Axis result = Direction.Axis.Y; + float longest = Math.abs(normalY); + float a = Math.abs(normalX); + + if (a > longest) { + result = Direction.Axis.X; + longest = a; + } + + return Math.abs(normalZ) > longest + ? Direction.Axis.Z : result; + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/helper/NormalHelper.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/helper/NormalHelper.java new file mode 100644 index 0000000000..f2fd5a5486 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/helper/NormalHelper.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.client.render.frapi.helper; + +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; +import net.minecraft.core.Direction; +import net.minecraft.core.Vec3i; +import org.jetbrains.annotations.NotNull; +import org.joml.Vector3f; + +/** + * Static routines of general utility for renderer implementations. + * Renderers are not required to use these helpers, but they were + * designed to be usable without the default renderer. + */ +public abstract class NormalHelper { + private NormalHelper() { } + + /** + * Computes the face normal of the given quad and saves it in the provided non-null vector. + * If {@link QuadView#nominalFace()} is set will optimize by confirming quad is parallel to that + * face and, if so, use the standard normal for that face direction. + * + *

Will work with triangles also. Assumes counter-clockwise winding order, which is the norm. + * Expects convex quads with all points co-planar. + */ + public static void computeFaceNormal(@NotNull Vector3f saveTo, QuadView q) { + final Direction nominalFace = q.nominalFace(); + + if (nominalFace != null && GeometryHelper.isQuadParallelToFace(nominalFace, q)) { + Vec3i vec = nominalFace.getNormal(); + saveTo.set(vec.getX(), vec.getY(), vec.getZ()); + return; + } + + final float x0 = q.x(0); + final float y0 = q.y(0); + final float z0 = q.z(0); + final float x1 = q.x(1); + final float y1 = q.y(1); + final float z1 = q.z(1); + final float x2 = q.x(2); + final float y2 = q.y(2); + final float z2 = q.z(2); + final float x3 = q.x(3); + final float y3 = q.y(3); + final float z3 = q.z(3); + + final float dx0 = x2 - x0; + final float dy0 = y2 - y0; + final float dz0 = z2 - z0; + final float dx1 = x3 - x1; + final float dy1 = y3 - y1; + final float dz1 = z3 - z1; + + float normX = dy0 * dz1 - dz0 * dy1; + float normY = dz0 * dx1 - dx0 * dz1; + float normZ = dx0 * dy1 - dy0 * dx1; + + float l = (float) Math.sqrt(normX * normX + normY * normY + normZ * normZ); + + if (l != 0) { + normX /= l; + normY /= l; + normZ /= l; + } + + saveTo.set(normX, normY, normZ); + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/helper/TextureHelper.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/helper/TextureHelper.java new file mode 100644 index 0000000000..84e4e34327 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/helper/TextureHelper.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.client.render.frapi.helper; + +import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.Direction; + +/** + * Handles most texture-baking use cases for model loaders and model libraries + * via {@link #bakeSprite(MutableQuadView, TextureAtlasSprite, int)}. Also used by the API + * itself to implement automatic block-breaking models for enhanced models. + */ +public class TextureHelper { + private TextureHelper() { } + + private static final float NORMALIZER = 1f / 16f; + + /** + * Bakes textures in the provided vertex data, handling UV locking, + * rotation, interpolation, etc. Textures must not be already baked. + */ + public static void bakeSprite(MutableQuadView quad, TextureAtlasSprite sprite, int bakeFlags) { + if (quad.nominalFace() != null && (MutableQuadView.BAKE_LOCK_UV & bakeFlags) != 0) { + // Assigns normalized UV coordinates based on vertex positions + applyModifier(quad, UVLOCKERS[quad.nominalFace().get3DDataValue()]); + } else if ((MutableQuadView.BAKE_NORMALIZED & bakeFlags) == 0) { // flag is NOT set, UVs are assumed to not be normalized yet as is the default, normalize through dividing by 16 + // Scales from 0-16 to 0-1 + applyModifier(quad, (q, i) -> q.uv(i, q.u(i) * NORMALIZER, q.v(i) * NORMALIZER)); + } + + final int rotation = bakeFlags & 3; + + if (rotation != 0) { + // Rotates texture around the center of sprite. + // Assumes normalized coordinates. + applyModifier(quad, ROTATIONS[rotation]); + } + + if ((MutableQuadView.BAKE_FLIP_U & bakeFlags) != 0) { + // Inverts U coordinates. Assumes normalized (0-1) values. + applyModifier(quad, (q, i) -> q.uv(i, 1 - q.u(i), q.v(i))); + } + + if ((MutableQuadView.BAKE_FLIP_V & bakeFlags) != 0) { + // Inverts V coordinates. Assumes normalized (0-1) values. + applyModifier(quad, (q, i) -> q.uv(i, q.u(i), 1 - q.v(i))); + } + + interpolate(quad, sprite); + } + + /** + * Faster than sprite method. Sprite computes span and normalizes inputs each call, + * so we'd have to denormalize before we called, only to have the sprite renormalize immediately. + */ + private static void interpolate(MutableQuadView q, TextureAtlasSprite sprite) { + final float uMin = sprite.getU0(); + final float uSpan = sprite.getU1() - uMin; + final float vMin = sprite.getV0(); + final float vSpan = sprite.getV1() - vMin; + + for (int i = 0; i < 4; i++) { + q.uv(i, uMin + q.u(i) * uSpan, vMin + q.v(i) * vSpan); + } + } + + @FunctionalInterface + private interface VertexModifier { + void apply(MutableQuadView quad, int vertexIndex); + } + + private static void applyModifier(MutableQuadView quad, VertexModifier modifier) { + for (int i = 0; i < 4; i++) { + modifier.apply(quad, i); + } + } + + private static final VertexModifier[] ROTATIONS = new VertexModifier[] { + null, + (q, i) -> q.uv(i, q.v(i), 1 - q.u(i)), //90 + (q, i) -> q.uv(i, 1 - q.u(i), 1 - q.v(i)), //180 + (q, i) -> q.uv(i, 1 - q.v(i), q.u(i)) // 270 + }; + + private static final VertexModifier[] UVLOCKERS = new VertexModifier[6]; + + static { + UVLOCKERS[Direction.EAST.get3DDataValue()] = (q, i) -> q.uv(i, 1 - q.z(i), 1 - q.y(i)); + UVLOCKERS[Direction.WEST.get3DDataValue()] = (q, i) -> q.uv(i, q.z(i), 1 - q.y(i)); + UVLOCKERS[Direction.NORTH.get3DDataValue()] = (q, i) -> q.uv(i, 1 - q.x(i), 1 - q.y(i)); + UVLOCKERS[Direction.SOUTH.get3DDataValue()] = (q, i) -> q.uv(i, q.x(i), 1 - q.y(i)); + UVLOCKERS[Direction.DOWN.get3DDataValue()] = (q, i) -> q.uv(i, q.x(i), 1 - q.z(i)); + UVLOCKERS[Direction.UP.get3DDataValue()] = (q, i) -> q.uv(i, q.x(i), q.z(i)); + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/material/MaterialFinderImpl.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/material/MaterialFinderImpl.java new file mode 100644 index 0000000000..e5b204b32e --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/material/MaterialFinderImpl.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.client.render.frapi.material; + +import net.fabricmc.fabric.api.renderer.v1.material.BlendMode; +import net.fabricmc.fabric.api.renderer.v1.material.MaterialFinder; +import net.fabricmc.fabric.api.renderer.v1.material.MaterialView; +import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; +import net.fabricmc.fabric.api.util.TriState; + +import java.util.Objects; + +public class MaterialFinderImpl extends MaterialViewImpl implements MaterialFinder { + private static int defaultBits = 0; + + static { + MaterialFinderImpl finder = new MaterialFinderImpl(); + finder.ambientOcclusion(TriState.DEFAULT); + finder.glint(TriState.DEFAULT); + defaultBits = finder.bits; + + if (!areBitsValid(defaultBits)) { + throw new AssertionError("Default MaterialFinder bits are not valid!"); + } + } + + public MaterialFinderImpl() { + super(defaultBits); + } + + @Override + public MaterialFinder blendMode(BlendMode blendMode) { + Objects.requireNonNull(blendMode, "BlendMode may not be null"); + + bits = (bits & ~BLEND_MODE_MASK) | (blendMode.ordinal() << BLEND_MODE_BIT_OFFSET); + return this; + } + + @Override + public MaterialFinder disableColorIndex(boolean disable) { + bits = disable ? (bits | COLOR_DISABLE_FLAG) : (bits & ~COLOR_DISABLE_FLAG); + return this; + } + + @Override + public MaterialFinder emissive(boolean isEmissive) { + bits = isEmissive ? (bits | EMISSIVE_FLAG) : (bits & ~EMISSIVE_FLAG); + return this; + } + + @Override + public MaterialFinder disableDiffuse(boolean disable) { + bits = disable ? (bits | DIFFUSE_FLAG) : (bits & ~DIFFUSE_FLAG); + return this; + } + + @Override + public MaterialFinder ambientOcclusion(TriState mode) { + Objects.requireNonNull(mode, "ambient occlusion TriState may not be null"); + + bits = (bits & ~AO_MASK) | (mode.ordinal() << AO_BIT_OFFSET); + return this; + } + + @Override + public MaterialFinder glint(TriState mode) { + Objects.requireNonNull(mode, "glint TriState may not be null"); + + bits = (bits & ~GLINT_MASK) | (mode.ordinal() << GLINT_BIT_OFFSET); + return this; + } + + @Override + public MaterialFinder copyFrom(MaterialView material) { + bits = ((MaterialViewImpl) material).bits; + return this; + } + + @Override + public MaterialFinder clear() { + bits = defaultBits; + return this; + } + + @Override + public RenderMaterial find() { + return RenderMaterialImpl.byIndex(bits); + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/material/MaterialViewImpl.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/material/MaterialViewImpl.java new file mode 100644 index 0000000000..2cb8a4a8f9 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/material/MaterialViewImpl.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.client.render.frapi.material; + +import net.fabricmc.fabric.api.renderer.v1.material.BlendMode; +import net.fabricmc.fabric.api.renderer.v1.material.MaterialView; +import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.util.Mth; + +/** + * Default implementation of the standard render materials. + * The underlying representation is simply an int with bit-wise + * packing of the various material properties. This offers + * easy/fast interning via int/object hashmap. + */ +public class MaterialViewImpl implements MaterialView { + private static final BlendMode[] BLEND_MODES = BlendMode.values(); + private static final int BLEND_MODE_COUNT = BLEND_MODES.length; + private static final TriState[] TRI_STATES = TriState.values(); + private static final int TRI_STATE_COUNT = TRI_STATES.length; + + protected static final int BLEND_MODE_BIT_LENGTH = Mth.ceillog2(BLEND_MODE_COUNT); + protected static final int COLOR_DISABLE_BIT_LENGTH = 1; + protected static final int EMISSIVE_BIT_LENGTH = 1; + protected static final int DIFFUSE_BIT_LENGTH = 1; + protected static final int AO_BIT_LENGTH = Mth.ceillog2(TRI_STATE_COUNT); + protected static final int GLINT_BIT_LENGTH = Mth.ceillog2(TRI_STATE_COUNT); + + protected static final int BLEND_MODE_BIT_OFFSET = 0; + protected static final int COLOR_DISABLE_BIT_OFFSET = BLEND_MODE_BIT_OFFSET + BLEND_MODE_BIT_LENGTH; + protected static final int EMISSIVE_BIT_OFFSET = COLOR_DISABLE_BIT_OFFSET + COLOR_DISABLE_BIT_LENGTH; + protected static final int DIFFUSE_BIT_OFFSET = EMISSIVE_BIT_OFFSET + EMISSIVE_BIT_LENGTH; + protected static final int AO_BIT_OFFSET = DIFFUSE_BIT_OFFSET + DIFFUSE_BIT_LENGTH; + protected static final int GLINT_BIT_OFFSET = AO_BIT_OFFSET + AO_BIT_LENGTH; + protected static final int TOTAL_BIT_LENGTH = GLINT_BIT_OFFSET + GLINT_BIT_LENGTH; + + protected static final int BLEND_MODE_MASK = bitMask(BLEND_MODE_BIT_LENGTH, BLEND_MODE_BIT_OFFSET); + protected static final int COLOR_DISABLE_FLAG = bitMask(COLOR_DISABLE_BIT_LENGTH, COLOR_DISABLE_BIT_OFFSET); + protected static final int EMISSIVE_FLAG = bitMask(EMISSIVE_BIT_LENGTH, EMISSIVE_BIT_OFFSET); + protected static final int DIFFUSE_FLAG = bitMask(DIFFUSE_BIT_LENGTH, DIFFUSE_BIT_OFFSET); + protected static final int AO_MASK = bitMask(AO_BIT_LENGTH, AO_BIT_OFFSET); + protected static final int GLINT_MASK = bitMask(GLINT_BIT_LENGTH, GLINT_BIT_OFFSET); + + protected static int bitMask(int bitLength, int bitOffset) { + return ((1 << bitLength) - 1) << bitOffset; + } + + protected static boolean areBitsValid(int bits) { + int blendMode = (bits & BLEND_MODE_MASK) >>> BLEND_MODE_BIT_OFFSET; + int ao = (bits & AO_MASK) >>> AO_BIT_OFFSET; + int glint = (bits & GLINT_MASK) >>> GLINT_BIT_OFFSET; + + return blendMode < BLEND_MODE_COUNT + && ao < TRI_STATE_COUNT + && glint < TRI_STATE_COUNT; + } + + protected int bits; + + protected MaterialViewImpl(int bits) { + this.bits = bits; + } + + @Override + public BlendMode blendMode() { + return BLEND_MODES[(bits & BLEND_MODE_MASK) >>> BLEND_MODE_BIT_OFFSET]; + } + + @Override + public boolean disableColorIndex() { + return (bits & COLOR_DISABLE_FLAG) != 0; + } + + @Override + public boolean emissive() { + return (bits & EMISSIVE_FLAG) != 0; + } + + @Override + public boolean disableDiffuse() { + return (bits & DIFFUSE_FLAG) != 0; + } + + @Override + public TriState ambientOcclusion() { + return TRI_STATES[(bits & AO_MASK) >>> AO_BIT_OFFSET]; + } + + @Override + public TriState glint() { + return TRI_STATES[(bits & GLINT_MASK) >>> GLINT_BIT_OFFSET]; + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/material/RenderMaterialImpl.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/material/RenderMaterialImpl.java new file mode 100644 index 0000000000..760f8b4dac --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/material/RenderMaterialImpl.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.client.render.frapi.material; + +import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; + +public class RenderMaterialImpl extends MaterialViewImpl implements RenderMaterial { + public static final int VALUE_COUNT = 1 << TOTAL_BIT_LENGTH; + private static final RenderMaterialImpl[] BY_INDEX = new RenderMaterialImpl[VALUE_COUNT]; + + static { + for (int i = 0; i < VALUE_COUNT; i++) { + if (areBitsValid(i)) { + BY_INDEX[i] = new RenderMaterialImpl(i); + } + } + } + + private RenderMaterialImpl(int bits) { + super(bits); + } + + public int index() { + return bits; + } + + public static RenderMaterialImpl byIndex(int index) { + return BY_INDEX[index]; + } + + public static RenderMaterialImpl setDisableDiffuse(RenderMaterialImpl material, boolean disable) { + if (material.disableDiffuse() != disable) { + return byIndex(disable ? (material.bits | DIFFUSE_FLAG) : (material.bits & ~DIFFUSE_FLAG)); + } + + return material; + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/mesh/EncodingFormat.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/mesh/EncodingFormat.java new file mode 100644 index 0000000000..583867ec87 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/mesh/EncodingFormat.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.client.render.frapi.mesh; + +import com.google.common.base.Preconditions; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.VertexFormat; +import net.caffeinemc.mods.sodium.client.model.quad.properties.ModelQuadFacing; +import net.caffeinemc.mods.sodium.client.model.quad.properties.ModelQuadFlags; +import net.caffeinemc.mods.sodium.client.render.frapi.material.RenderMaterialImpl; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; +import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; + +/** + * Holds all the array offsets and bit-wise encoders/decoders for + * packing/unpacking quad data in an array of integers. + * All of this is implementation-specific - that's why it isn't a "helper" class. + */ +public abstract class EncodingFormat { + private EncodingFormat() { } + + static final int HEADER_BITS = 0; + static final int HEADER_FACE_NORMAL = 1; + static final int HEADER_COLOR_INDEX = 2; + static final int HEADER_TAG = 3; + public static final int HEADER_STRIDE = 4; + + static final int VERTEX_X; + static final int VERTEX_Y; + static final int VERTEX_Z; + static final int VERTEX_COLOR; + static final int VERTEX_U; + static final int VERTEX_V; + static final int VERTEX_LIGHTMAP; + static final int VERTEX_NORMAL; + public static final int VERTEX_STRIDE; + + public static final int QUAD_STRIDE; + public static final int QUAD_STRIDE_BYTES; + public static final int TOTAL_STRIDE; + + static { + final VertexFormat format = DefaultVertexFormat.BLOCK; + VERTEX_X = HEADER_STRIDE + 0; + VERTEX_Y = HEADER_STRIDE + 1; + VERTEX_Z = HEADER_STRIDE + 2; + VERTEX_COLOR = HEADER_STRIDE + 3; + VERTEX_U = HEADER_STRIDE + 4; + VERTEX_V = VERTEX_U + 1; + VERTEX_LIGHTMAP = HEADER_STRIDE + 6; + VERTEX_NORMAL = HEADER_STRIDE + 7; + VERTEX_STRIDE = format.getVertexSize() / 4; + QUAD_STRIDE = VERTEX_STRIDE * 4; + QUAD_STRIDE_BYTES = QUAD_STRIDE * 4; + TOTAL_STRIDE = HEADER_STRIDE + QUAD_STRIDE; + + Preconditions.checkState(VERTEX_STRIDE == QuadView.VANILLA_VERTEX_STRIDE, "Sodium FRAPI vertex stride (%s) mismatched with rendering API (%s)", VERTEX_STRIDE, QuadView.VANILLA_VERTEX_STRIDE); + Preconditions.checkState(QUAD_STRIDE == QuadView.VANILLA_QUAD_STRIDE, "Sodium FRAPI quad stride (%s) mismatched with rendering API (%s)", QUAD_STRIDE, QuadView.VANILLA_QUAD_STRIDE); + } + + /** used for quick clearing of quad buffers. */ + static final int[] EMPTY = new int[TOTAL_STRIDE]; + + private static final int DIRECTION_MASK = Mth.smallestEncompassingPowerOfTwo(ModelHelper.NULL_FACE_ID + 1) - 1; + private static final int DIRECTION_BIT_COUNT = Integer.bitCount(DIRECTION_MASK); + private static final int FACING_MASK = Mth.smallestEncompassingPowerOfTwo(ModelQuadFacing.COUNT) - 1; + private static final int FACING_BIT_COUNT = Integer.bitCount(FACING_MASK); + private static final int MATERIAL_MASK = Mth.smallestEncompassingPowerOfTwo(RenderMaterialImpl.VALUE_COUNT) - 1; + private static final int MATERIAL_BIT_COUNT = Integer.bitCount(MATERIAL_MASK); + + private static final int CULL_SHIFT = 0; + private static final int CULL_INVERSE_MASK = ~(DIRECTION_MASK << CULL_SHIFT); + private static final int LIGHT_SHIFT = CULL_SHIFT + DIRECTION_BIT_COUNT; + private static final int LIGHT_INVERSE_MASK = ~(DIRECTION_MASK << LIGHT_SHIFT); + private static final int NORMAL_FACE_SHIFT = LIGHT_SHIFT + DIRECTION_BIT_COUNT; + private static final int NORMAL_FACE_INVERSE_MASK = ~(FACING_MASK << NORMAL_FACE_SHIFT); + private static final int NORMALS_SHIFT = NORMAL_FACE_SHIFT + FACING_BIT_COUNT; + private static final int NORMALS_COUNT = 4; + private static final int NORMALS_MASK = (1 << NORMALS_COUNT) - 1; + private static final int NORMALS_INVERSE_MASK = ~(NORMALS_MASK << NORMALS_SHIFT); + private static final int GEOMETRY_SHIFT = NORMALS_SHIFT + NORMALS_COUNT; + private static final int GEOMETRY_MASK = (1 << ModelQuadFlags.FLAG_BIT_COUNT) - 1; + private static final int GEOMETRY_INVERSE_MASK = ~(GEOMETRY_MASK << GEOMETRY_SHIFT); + private static final int MATERIAL_SHIFT = GEOMETRY_SHIFT + ModelQuadFlags.FLAG_BIT_COUNT; + private static final int MATERIAL_INVERSE_MASK = ~(MATERIAL_MASK << MATERIAL_SHIFT); + + static { + Preconditions.checkArgument(MATERIAL_SHIFT + MATERIAL_BIT_COUNT <= 32, "Sodium FRAPI header encoding bit count (%s) exceeds integer bit length)", TOTAL_STRIDE); + } + + static Direction cullFace(int bits) { + return ModelHelper.faceFromIndex((bits >>> CULL_SHIFT) & DIRECTION_MASK); + } + + static int cullFace(int bits, Direction face) { + return (bits & CULL_INVERSE_MASK) | (ModelHelper.toFaceIndex(face) << CULL_SHIFT); + } + + static Direction lightFace(int bits) { + return ModelHelper.faceFromIndex((bits >>> LIGHT_SHIFT) & DIRECTION_MASK); + } + + static int lightFace(int bits, Direction face) { + return (bits & LIGHT_INVERSE_MASK) | (ModelHelper.toFaceIndex(face) << LIGHT_SHIFT); + } + + static ModelQuadFacing normalFace(int bits) { + return ModelQuadFacing.VALUES[(bits >>> NORMAL_FACE_SHIFT) & FACING_MASK]; + } + + static int normalFace(int bits, ModelQuadFacing face) { + return (bits & NORMAL_FACE_INVERSE_MASK) | (face.ordinal() << NORMAL_FACE_SHIFT); + } + + /** indicate if vertex normal has been set - bits correspond to vertex ordinals. */ + static int normalFlags(int bits) { + return (bits >>> NORMALS_SHIFT) & NORMALS_MASK; + } + + static int normalFlags(int bits, int normalFlags) { + return (bits & NORMALS_INVERSE_MASK) | ((normalFlags & NORMALS_MASK) << NORMALS_SHIFT); + } + + static int geometryFlags(int bits) { + return (bits >>> GEOMETRY_SHIFT) & GEOMETRY_MASK; + } + + static int geometryFlags(int bits, int geometryFlags) { + return (bits & GEOMETRY_INVERSE_MASK) | ((geometryFlags & GEOMETRY_MASK) << GEOMETRY_SHIFT); + } + + static RenderMaterialImpl material(int bits) { + return RenderMaterialImpl.byIndex((bits >>> MATERIAL_SHIFT) & MATERIAL_MASK); + } + + static int material(int bits, RenderMaterialImpl material) { + return (bits & MATERIAL_INVERSE_MASK) | (material.index() << MATERIAL_SHIFT); + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/mesh/MeshBuilderImpl.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/mesh/MeshBuilderImpl.java new file mode 100644 index 0000000000..34e69c8b1f --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/mesh/MeshBuilderImpl.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.client.render.frapi.mesh; + +import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh; +import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; + +/** + * Our implementation of {@link MeshBuilder}, used for static mesh creation and baking. + * Not much to it - mainly it just needs to grow the int[] array as quads are appended + * and maintain/provide a properly-configured {@link net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView} instance. + * All the encoding and other work is handled in the quad base classes. + * The one interesting bit is in {@link Maker#emitDirectly()}. + */ +public class MeshBuilderImpl implements MeshBuilder { + private int[] data = new int[256]; + private int index = 0; + private int limit = data.length; + private final Maker maker = new Maker(); + + public MeshBuilderImpl() { + ensureCapacity(EncodingFormat.TOTAL_STRIDE); + maker.data = data; + maker.baseIndex = index; + maker.clear(); + } + + protected void ensureCapacity(int stride) { + if (stride > limit - index) { + limit *= 2; + final int[] bigger = new int[limit]; + System.arraycopy(data, 0, bigger, 0, index); + data = bigger; + maker.data = data; + } + } + + @Override + public QuadEmitter getEmitter() { + maker.clear(); + return maker; + } + + @Override + public Mesh build() { + final int[] packed = new int[index]; + System.arraycopy(data, 0, packed, 0, index); + index = 0; + maker.baseIndex = index; + maker.clear(); + return new MeshImpl(packed); + } + + /** + * Our base classes are used differently so we define final + * encoding steps in subtypes. This will be a static mesh used + * at render time so we want to capture all geometry now and + * apply non-location-dependent lighting. + */ + private class Maker extends MutableQuadViewImpl { + @Override + public void emitDirectly() { + computeGeometry(); + index += EncodingFormat.TOTAL_STRIDE; + ensureCapacity(EncodingFormat.TOTAL_STRIDE); + baseIndex = index; + } + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/mesh/MeshImpl.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/mesh/MeshImpl.java new file mode 100644 index 0000000000..60fa624c90 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/mesh/MeshImpl.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.client.render.frapi.mesh; + +import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; + +import java.util.function.Consumer; + +/** + * Implementation of {@link Mesh}. + * The way we encode meshes makes it very simple. + */ +public class MeshImpl implements Mesh { + /** Used to satisfy external calls to {@link #forEach(Consumer)}. */ + private final ThreadLocal cursorPool = ThreadLocal.withInitial(QuadViewImpl::new); + + final int[] data; + + MeshImpl(int[] data) { + this.data = data; + } + + @Override + public void forEach(Consumer consumer) { + forEach(consumer, cursorPool.get()); + } + + /** + * The renderer can call this with its own cursor + * to avoid the performance hit of a thread-local lookup. + * Also means renderer can hold final references to quad buffers. + */ + void forEach(Consumer consumer, QuadViewImpl cursor) { + final int limit = data.length; + int index = 0; + cursor.data = this.data; + + while (index < limit) { + cursor.baseIndex = index; + cursor.load(); + consumer.accept(cursor); + index += EncodingFormat.TOTAL_STRIDE; + } + } + + @Override + public void outputTo(QuadEmitter emitter) { + MutableQuadViewImpl e = (MutableQuadViewImpl) emitter; + final int[] data = this.data; + final int limit = data.length; + int index = 0; + + while (index < limit) { + System.arraycopy(data, index, e.data, e.baseIndex, EncodingFormat.TOTAL_STRIDE); + e.load(); + e.emitDirectly(); + index += EncodingFormat.TOTAL_STRIDE; + } + + e.clear(); + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/mesh/MutableQuadViewImpl.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/mesh/MutableQuadViewImpl.java new file mode 100644 index 0000000000..3ab4bc208f --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/mesh/MutableQuadViewImpl.java @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.client.render.frapi.mesh; + +import net.caffeinemc.mods.sodium.api.util.NormI8; +import net.caffeinemc.mods.sodium.client.model.quad.BakedQuadView; +import net.caffeinemc.mods.sodium.client.render.frapi.SodiumRenderer; +import net.caffeinemc.mods.sodium.client.render.frapi.helper.ColorHelper; +import net.caffeinemc.mods.sodium.client.render.frapi.helper.TextureHelper; +import net.caffeinemc.mods.sodium.client.render.frapi.material.RenderMaterialImpl; +import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; +import net.fabricmc.fabric.api.renderer.v1.model.SpriteFinder; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.Direction; +import org.jetbrains.annotations.Nullable; + +import static net.caffeinemc.mods.sodium.client.render.frapi.mesh.EncodingFormat.*; + +/** + * Almost-concrete implementation of a mutable quad. The only missing part is {@link #emitDirectly()}, + * because that depends on where/how it is used. (Mesh encoding vs. render-time transformation). + * + *

In many cases an instance of this class is used as an "editor quad". The editor quad's + * {@link #emitDirectly()} method calls some other internal method that transforms the quad + * data and then buffers it. Transformations should be the same as they would be in a vanilla + * render - the editor is serving mainly as a way to access vertex data without magical + * numbers. It also allows for a consistent interface for those transformations. + */ +public abstract class MutableQuadViewImpl extends QuadViewImpl implements QuadEmitter { + @Nullable + private TextureAtlasSprite cachedSprite; + + @Nullable + public TextureAtlasSprite cachedSprite() { + return cachedSprite; + } + + public void cachedSprite(@Nullable TextureAtlasSprite sprite) { + cachedSprite = sprite; + } + + public TextureAtlasSprite sprite(SpriteFinder finder) { + TextureAtlasSprite sprite = cachedSprite; + + if (sprite == null) { + cachedSprite = sprite = finder.find(this); + } + + return sprite; + } + + public void clear() { + System.arraycopy(EMPTY, 0, data, baseIndex, EncodingFormat.TOTAL_STRIDE); + isGeometryInvalid = true; + nominalFace = null; + normalFlags(0); + tag(0); + colorIndex(-1); + cullFace(null); + material(SodiumRenderer.STANDARD_MATERIAL); + cachedSprite(null); + } + + @Override + public void load() { + super.load(); + cachedSprite(null); + } + + @Override + public MutableQuadViewImpl pos(int vertexIndex, float x, float y, float z) { + final int index = baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_X; + data[index] = Float.floatToRawIntBits(x); + data[index + 1] = Float.floatToRawIntBits(y); + data[index + 2] = Float.floatToRawIntBits(z); + isGeometryInvalid = true; + return this; + } + + @Override + public MutableQuadViewImpl color(int vertexIndex, int color) { + data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_COLOR] = color; + return this; + } + + @Override + public MutableQuadViewImpl uv(int vertexIndex, float u, float v) { + final int i = baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_U; + data[i] = Float.floatToRawIntBits(u); + data[i + 1] = Float.floatToRawIntBits(v); + cachedSprite(null); + return this; + } + + @Override + public MutableQuadViewImpl spriteBake(TextureAtlasSprite sprite, int bakeFlags) { + TextureHelper.bakeSprite(this, sprite, bakeFlags); + cachedSprite(sprite); + return this; + } + + @Override + public MutableQuadViewImpl lightmap(int vertexIndex, int lightmap) { + data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_LIGHTMAP] = lightmap; + return this; + } + + protected void normalFlags(int flags) { + data[baseIndex + HEADER_BITS] = EncodingFormat.normalFlags(data[baseIndex + HEADER_BITS], flags); + } + + @Override + public MutableQuadViewImpl normal(int vertexIndex, float x, float y, float z) { + normalFlags(normalFlags() | (1 << vertexIndex)); + data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_NORMAL] = NormI8.pack(x, y, z); + return this; + } + + /** + * Internal helper method. Copies face normals to vertex normals lacking one. + */ + public final void populateMissingNormals() { + final int normalFlags = this.normalFlags(); + + if (normalFlags == 0b1111) return; + + final int packedFaceNormal = packedFaceNormal(); + + for (int v = 0; v < 4; v++) { + if ((normalFlags & (1 << v)) == 0) { + data[baseIndex + v * VERTEX_STRIDE + VERTEX_NORMAL] = packedFaceNormal; + } + } + + normalFlags(0b1111); + } + + @Override + public final MutableQuadViewImpl cullFace(@Nullable Direction face) { + data[baseIndex + HEADER_BITS] = EncodingFormat.cullFace(data[baseIndex + HEADER_BITS], face); + nominalFace(face); + return this; + } + + @Override + public final MutableQuadViewImpl nominalFace(@Nullable Direction face) { + nominalFace = face; + return this; + } + + @Override + public final MutableQuadViewImpl material(RenderMaterial material) { + if (material == null) { + material = SodiumRenderer.STANDARD_MATERIAL; + } + + data[baseIndex + HEADER_BITS] = EncodingFormat.material(data[baseIndex + HEADER_BITS], (RenderMaterialImpl) material); + return this; + } + + @Override + public final MutableQuadViewImpl colorIndex(int colorIndex) { + data[baseIndex + HEADER_COLOR_INDEX] = colorIndex; + return this; + } + + @Override + public final MutableQuadViewImpl tag(int tag) { + data[baseIndex + HEADER_TAG] = tag; + return this; + } + + @Override + public MutableQuadViewImpl copyFrom(QuadView quad) { + final QuadViewImpl q = (QuadViewImpl) quad; + q.computeGeometry(); + + System.arraycopy(q.data, q.baseIndex, data, baseIndex, EncodingFormat.TOTAL_STRIDE); + faceNormal.set(q.faceNormal); + nominalFace = q.nominalFace; + isGeometryInvalid = false; + + if (quad instanceof MutableQuadViewImpl mutableQuad) { + cachedSprite(mutableQuad.cachedSprite()); + } else { + cachedSprite(null); + } + + return this; + } + + /** + * Does the same work as {@link #fromVanilla(int[], int)}, but does not mark the geometry as invalid + * and does not clear the cached sprite. + * Only use this if you are also setting the geometry and sprite. + */ + private void fromVanillaInternal(int[] quadData, int startIndex) { + System.arraycopy(quadData, startIndex, data, baseIndex + HEADER_STRIDE, QuadView.VANILLA_QUAD_STRIDE); + + int colorIndex = baseIndex + VERTEX_COLOR; + + for (int i = 0; i < 4; i++) { + data[colorIndex] = ColorHelper.fromVanillaColor(data[colorIndex]); + colorIndex += VERTEX_STRIDE; + } + } + + @Override + public final MutableQuadViewImpl fromVanilla(int[] quadData, int startIndex) { + fromVanillaInternal(quadData, startIndex); + isGeometryInvalid = true; + cachedSprite(null); + return this; + } + + @Override + public final MutableQuadViewImpl fromVanilla(BakedQuad quad, RenderMaterial material, @Nullable Direction cullFace) { + fromVanillaInternal(quad.getVertices(), 0); + data[baseIndex + HEADER_BITS] = EncodingFormat.cullFace(0, cullFace); + nominalFace(quad.getDirection()); + colorIndex(quad.getTintIndex()); + + // TODO: Is this the same as hasShade? + if (!((BakedQuadView) quad).hasShade()) { + material = RenderMaterialImpl.setDisableDiffuse((RenderMaterialImpl) material, true); + } + + material(material); + tag(0); + + // Copy geometry cached inside the quad + BakedQuadView bakedView = (BakedQuadView) quad; + NormI8.unpack(bakedView.getFaceNormal(), faceNormal); + data[baseIndex + HEADER_FACE_NORMAL] = bakedView.getFaceNormal(); + int headerBits = EncodingFormat.lightFace(data[baseIndex + HEADER_BITS], bakedView.getLightFace()); + headerBits = EncodingFormat.normalFace(headerBits, bakedView.getNormalFace()); + data[baseIndex + HEADER_BITS] = EncodingFormat.geometryFlags(headerBits, bakedView.getFlags()); + isGeometryInvalid = false; + + cachedSprite(quad.getSprite()); + return this; + } + + /** + * Emit the quad without clearing the underlying data. + * Geometry is not guaranteed to be valid when called, but can be computed by calling {@link #computeGeometry()}. + */ + public abstract void emitDirectly(); + + @Override + public final MutableQuadViewImpl emit() { + emitDirectly(); + clear(); + return this; + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/mesh/QuadViewImpl.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/mesh/QuadViewImpl.java new file mode 100644 index 0000000000..fce995a97b --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/mesh/QuadViewImpl.java @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.client.render.frapi.mesh; + + +import net.caffeinemc.mods.sodium.api.util.NormI8; +import net.caffeinemc.mods.sodium.client.model.quad.ModelQuadView; +import net.caffeinemc.mods.sodium.client.model.quad.properties.ModelQuadFacing; +import net.caffeinemc.mods.sodium.client.model.quad.properties.ModelQuadFlags; +import net.caffeinemc.mods.sodium.client.render.frapi.helper.ColorHelper; +import net.caffeinemc.mods.sodium.client.render.frapi.helper.GeometryHelper; +import net.caffeinemc.mods.sodium.client.render.frapi.helper.NormalHelper; +import net.caffeinemc.mods.sodium.client.render.frapi.material.RenderMaterialImpl; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.Direction; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.joml.Vector2f; +import org.joml.Vector3f; + +import static net.caffeinemc.mods.sodium.client.render.frapi.mesh.EncodingFormat.*; + +/** + * Base class for all quads / quad makers. Handles the ugly bits + * of maintaining and encoding the quad state. + */ +public class QuadViewImpl implements QuadView, ModelQuadView { + @Nullable + protected Direction nominalFace; + /** True when face normal, light face, normal face, or geometry flags may not match geometry. */ + protected boolean isGeometryInvalid = true; + protected final Vector3f faceNormal = new Vector3f(); + + /** Size and where it comes from will vary in subtypes. But in all cases quad is fully encoded to array. */ + protected int[] data; + + /** Beginning of the quad. Also the header index. */ + protected int baseIndex = 0; + + /** + * Decodes necessary state from the backing data array. + * The encoded data must contain valid computed geometry. + */ + public void load() { + isGeometryInvalid = false; + nominalFace = lightFace(); + NormI8.unpack(packedFaceNormal(), faceNormal); + } + + protected void computeGeometry() { + if (isGeometryInvalid) { + isGeometryInvalid = false; + + NormalHelper.computeFaceNormal(faceNormal, this); + int packedFaceNormal = NormI8.pack(faceNormal); + data[baseIndex + HEADER_FACE_NORMAL] = packedFaceNormal; + + // depends on face normal + Direction lightFace = GeometryHelper.lightFace(this); + data[baseIndex + HEADER_BITS] = EncodingFormat.lightFace(data[baseIndex + HEADER_BITS], lightFace); + + // depends on face normal + data[baseIndex + HEADER_BITS] = EncodingFormat.normalFace(data[baseIndex + HEADER_BITS], ModelQuadFacing.fromPackedNormal(packedFaceNormal)); + + // depends on light face + data[baseIndex + HEADER_BITS] = EncodingFormat.geometryFlags(data[baseIndex + HEADER_BITS], ModelQuadFlags.getQuadFlags(this, lightFace)); + } + } + + /** gets flags used for lighting - lazily computed via {@link ModelQuadFlags#getQuadFlags}. */ + public int geometryFlags() { + computeGeometry(); + return EncodingFormat.geometryFlags(data[baseIndex + HEADER_BITS]); + } + + public boolean hasShade() { + return !material().disableDiffuse(); + } + + @Override + public float x(int vertexIndex) { + return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_X]); + } + + @Override + public float y(int vertexIndex) { + return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_Y]); + } + + @Override + public float z(int vertexIndex) { + return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_Z]); + } + + @Override + public float posByIndex(int vertexIndex, int coordinateIndex) { + return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_X + coordinateIndex]); + } + + @Override + public Vector3f copyPos(int vertexIndex, @Nullable Vector3f target) { + if (target == null) { + target = new Vector3f(); + } + + final int index = baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_X; + target.set(Float.intBitsToFloat(data[index]), Float.intBitsToFloat(data[index + 1]), Float.intBitsToFloat(data[index + 2])); + return target; + } + + @Override + public int color(int vertexIndex) { + return data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_COLOR]; + } + + @Override + public float u(int vertexIndex) { + return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_U]); + } + + @Override + public float v(int vertexIndex) { + return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_V]); + } + + @Override + public Vector2f copyUv(int vertexIndex, @Nullable Vector2f target) { + if (target == null) { + target = new Vector2f(); + } + + final int index = baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_U; + target.set(Float.intBitsToFloat(data[index]), Float.intBitsToFloat(data[index + 1])); + return target; + } + + @Override + public int lightmap(int vertexIndex) { + return data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_LIGHTMAP]; + } + + public int normalFlags() { + return EncodingFormat.normalFlags(data[baseIndex + HEADER_BITS]); + } + + @Override + public boolean hasNormal(int vertexIndex) { + return (normalFlags() & (1 << vertexIndex)) != 0; + } + + /** True if any vertex normal has been set. */ + public boolean hasVertexNormals() { + return normalFlags() != 0; + } + + /** True if all vertex normals have been set. */ + public boolean hasAllVertexNormals() { + return (normalFlags() & 0b1111) == 0b1111; + } + + protected final int normalIndex(int vertexIndex) { + return baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_NORMAL; + } + + /** + * This method will only return a meaningful value if {@link #hasNormal} returns {@code true} for the same vertex index. + */ + public int packedNormal(int vertexIndex) { + return data[normalIndex(vertexIndex)]; + } + + @Override + public float normalX(int vertexIndex) { + return hasNormal(vertexIndex) ? NormI8.unpackX(data[normalIndex(vertexIndex)]) : Float.NaN; + } + + @Override + public float normalY(int vertexIndex) { + return hasNormal(vertexIndex) ? NormI8.unpackY(data[normalIndex(vertexIndex)]) : Float.NaN; + } + + @Override + public float normalZ(int vertexIndex) { + return hasNormal(vertexIndex) ? NormI8.unpackZ(data[normalIndex(vertexIndex)]) : Float.NaN; + } + + @Override + @Nullable + public Vector3f copyNormal(int vertexIndex, @Nullable Vector3f target) { + if (hasNormal(vertexIndex)) { + if (target == null) { + target = new Vector3f(); + } + + final int normal = data[normalIndex(vertexIndex)]; + NormI8.unpack(normal, target); + return target; + } else { + return null; + } + } + + @Override + @Nullable + public final Direction cullFace() { + return EncodingFormat.cullFace(data[baseIndex + HEADER_BITS]); + } + + @Override + @NotNull + public final Direction lightFace() { + computeGeometry(); + return EncodingFormat.lightFace(data[baseIndex + HEADER_BITS]); + } + + public final ModelQuadFacing normalFace() { + computeGeometry(); + return EncodingFormat.normalFace(data[baseIndex + HEADER_BITS]); + } + + @Override + @Nullable + public final Direction nominalFace() { + return nominalFace; + } + + public final int packedFaceNormal() { + computeGeometry(); + return data[baseIndex + HEADER_FACE_NORMAL]; + } + + @Override + public final Vector3f faceNormal() { + computeGeometry(); + return faceNormal; + } + + @Override + public final RenderMaterialImpl material() { + return EncodingFormat.material(data[baseIndex + HEADER_BITS]); + } + + @Override + public final int colorIndex() { + return data[baseIndex + HEADER_COLOR_INDEX]; + } + + @Override + public final int tag() { + return data[baseIndex + HEADER_TAG]; + } + + @Override + public final void toVanilla(int[] target, int targetIndex) { + System.arraycopy(data, baseIndex + HEADER_STRIDE, target, targetIndex, QUAD_STRIDE); + + // The color is the fourth integer in each vertex. + // EncodingFormat.VERTEX_COLOR is not used because it also + // contains the header size; vanilla quads do not have a header. + int colorIndex = targetIndex + 3; + + for (int i = 0; i < 4; i++) { + target[colorIndex] = ColorHelper.toVanillaColor(target[colorIndex]); + colorIndex += QuadView.VANILLA_VERTEX_STRIDE; + } + } + + // ModelQuadView method implementations below + + @Override + public float getX(int idx) { + return x(idx); + } + + @Override + public float getY(int idx) { + return y(idx); + } + + @Override + public float getZ(int idx) { + return z(idx); + } + + @Override + public int getColor(int idx) { + return ColorHelper.toVanillaColor(color(idx)); + } + + @Override + public float getTexU(int idx) { + return u(idx); + } + + @Override + public float getTexV(int idx) { + return v(idx); + } + + @Override + public int getVertexNormal(int idx) { + return data[normalIndex(idx)]; + } + + @Override + public int getFaceNormal() { + return packedFaceNormal(); + } + + @Override + public int getLight(int idx) { + return lightmap(idx); + } + + @Override + public int getColorIndex() { + return material().disableColorIndex() ? -1 : colorIndex(); + } + + @Override + public TextureAtlasSprite getSprite() { + throw new UnsupportedOperationException("Not available for QuadViewImpl."); + } + + @Override + public Direction getLightFace() { + return lightFace(); + } + + @Override + public int getFlags() { + return geometryFlags(); + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/render/AbstractBlockRenderContext.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/render/AbstractBlockRenderContext.java new file mode 100644 index 0000000000..66b5252db4 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/render/AbstractBlockRenderContext.java @@ -0,0 +1,274 @@ +package net.caffeinemc.mods.sodium.client.render.frapi.render; + +import net.caffeinemc.mods.sodium.client.model.light.LightMode; +import net.caffeinemc.mods.sodium.client.model.light.LightPipeline; +import net.caffeinemc.mods.sodium.client.model.light.LightPipelineProvider; +import net.caffeinemc.mods.sodium.client.model.light.data.QuadLightData; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.BlockOcclusionCache; +import net.caffeinemc.mods.sodium.client.render.frapi.SodiumRenderer; +import net.caffeinemc.mods.sodium.client.render.frapi.helper.ColorHelper; +import net.caffeinemc.mods.sodium.client.render.frapi.mesh.EncodingFormat; +import net.caffeinemc.mods.sodium.client.render.frapi.mesh.MutableQuadViewImpl; +import net.caffeinemc.mods.sodium.client.services.PlatformBlockAccess; +import net.caffeinemc.mods.sodium.client.services.PlatformLevelAccess; +import net.caffeinemc.mods.sodium.client.services.PlatformModelAccess; +import net.caffeinemc.mods.sodium.client.services.SodiumModelData; +import net.caffeinemc.mods.sodium.client.world.LevelSlice; +import net.fabricmc.fabric.api.renderer.v1.material.BlendMode; +import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; +import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper; +import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.function.Supplier; + +/** + * Base class for the functions that can be shared between the terrain and non-terrain pipelines. + * + *

Make sure to set the {@link #lighters} in the subclass constructor. + */ +public abstract class AbstractBlockRenderContext extends AbstractRenderContext { + private static final RenderMaterial[] STANDARD_MATERIALS; + private static final RenderMaterial TRANSLUCENT_MATERIAL = SodiumRenderer.INSTANCE.materialFinder().blendMode(BlendMode.TRANSLUCENT).find(); + + static { + STANDARD_MATERIALS = new RenderMaterial[TriState.values().length]; + + TriState[] values = TriState.values(); + for (int i = 0; i < values.length; i++) { + TriState state = values[i]; + STANDARD_MATERIALS[i] = SodiumRenderer.INSTANCE.materialFinder().ambientOcclusion(state).find(); + } + } + private final MutableQuadViewImpl editorQuad = new MutableQuadViewImpl() { + { + data = new int[EncodingFormat.TOTAL_STRIDE]; + clear(); + } + + @Override + public void emitDirectly() { + if (type == null) { + throw new IllegalStateException("No render type is set but an FRAPI object was asked to render!"); + } + renderQuad(this); + } + }; + + @Deprecated + private final BakedModelConsumerImpl vanillaModelConsumer = new BakedModelConsumerImpl(); + + /** + * The world which the block is being rendered in. + */ + protected BlockAndTintGetter level; + /** + * The level slice used for rendering + */ + protected LevelSlice slice; + /** + * The state of the block being rendered. + */ + protected BlockState state; + /** + * The position (in world space) of the block being rendered. + */ + protected BlockPos pos; + + /** + * The current render type being rendered. + */ + protected RenderType type; + + /** + * The current model's model data. + */ + protected SodiumModelData modelData; + + private final BlockOcclusionCache occlusionCache = new BlockOcclusionCache(); + private boolean enableCulling = true; + // Cull cache (as it's checked per-quad instead of once per side like in vanilla) + private int cullCompletionFlags; + private int cullResultFlags; + + protected RandomSource random; + protected long randomSeed; + protected final Supplier randomSupplier = () -> { + random.setSeed(randomSeed); + return random; + }; + + /** + * Must be set by the subclass constructor. + */ + protected LightPipelineProvider lighters; + protected final QuadLightData quadLightData = new QuadLightData(); + protected boolean useAmbientOcclusion; + // Default AO mode for model (can be overridden by material property) + protected LightMode defaultLightMode; + + @Override + public QuadEmitter getEmitter() { + this.editorQuad.clear(); + return this.editorQuad; + } + + @Override + public boolean isFaceCulled(@Nullable Direction face) { + if (face == null || !this.enableCulling) { + return false; + } + + final int mask = 1 << face.get3DDataValue(); + + if ((this.cullCompletionFlags & mask) == 0) { + this.cullCompletionFlags |= mask; + + if (this.occlusionCache.shouldDrawSide(this.state, this.level, this.pos, face)) { + this.cullResultFlags |= mask; + return false; + } else { + return true; + } + } else { + return (this.cullResultFlags & mask) == 0; + } + } + + @Override + public ItemDisplayContext itemTransformationMode() { + throw new UnsupportedOperationException("itemTransformationMode can only be called on an item render context."); + } + + @SuppressWarnings("removal") + @Deprecated + @Override + public BakedModelConsumer bakedModelConsumer() { + return this.vanillaModelConsumer; + } + + /** + * Pipeline entrypoint - handles transform and culling checks. + */ + private void renderQuad(MutableQuadViewImpl quad) { + if (!this.transform(quad)) { + return; + } + + if (this.isFaceCulled(quad.cullFace())) { + return; + } + + this.processQuad(quad); + } + + /** + * Quad pipeline function - after transform and culling checks. + * Can also be used as entrypoint to skip some logic if the transform and culling checks have already been performed. + */ + protected abstract void processQuad(MutableQuadViewImpl quad); + + protected void prepareCulling(boolean enableCulling) { + this.enableCulling = enableCulling; + this.cullCompletionFlags = 0; + this.cullResultFlags = 0; + } + + protected void prepareAoInfo(boolean modelAo) { + this.useAmbientOcclusion = Minecraft.useAmbientOcclusion(); + // Ignore the incorrect IDEA warning here. + this.defaultLightMode = this.useAmbientOcclusion && modelAo && PlatformBlockAccess.getInstance().getLightEmission(state, level, pos) == 0 ? LightMode.SMOOTH : LightMode.FLAT; + } + + // TODO: normal-based (enhanced) AO for smooth lighting pipeline + // TODO: normal-based diffuse for both lighting pipelines + protected void shadeQuad(MutableQuadViewImpl quad, LightMode lightMode, boolean emissive) { + LightPipeline lighter = this.lighters.getLighter(lightMode); + QuadLightData data = this.quadLightData; + lighter.calculate(quad, this.pos, data, quad.cullFace(), quad.lightFace(), quad.hasShade(), false); + + if (emissive) { + for (int i = 0; i < 4; i++) { + quad.lightmap(i, LightTexture.FULL_BRIGHT); + } + } else { + int[] lightmaps = data.lm; + + for (int i = 0; i < 4; i++) { + quad.lightmap(i, ColorHelper.maxBrightness(quad.lightmap(i), lightmaps[i])); + } + } + } + + /* Handling of vanilla models - this is the hot path for non-modded models */ + public void bufferDefaultModel(BakedModel model, @Nullable BlockState state) { + MutableQuadViewImpl editorQuad = this.editorQuad; + + + // If there is no transform, we can check the culling face once for all the quads, + // and we don't need to check for transforms per-quad. + boolean noTransform = !this.hasTransform(); + + for (int i = 0; i <= ModelHelper.NULL_FACE_ID; i++) { + final Direction cullFace = ModelHelper.faceFromIndex(i); + + RandomSource random = this.randomSupplier.get(); + TriState ao = PlatformBlockAccess.getInstance().usesAmbientOcclusion(model, state, modelData, type, slice, pos); + if (noTransform) { + if (!this.isFaceCulled(cullFace)) { + final List quads = PlatformModelAccess.getInstance().getQuads(level, pos, model, state, cullFace, random, type, modelData); + final int count = quads.size(); + + for (int j = 0; j < count; j++) { + final BakedQuad q = quads.get(j); + editorQuad.fromVanilla(q, (type == RenderType.tripwire() || type == RenderType.translucent()) ? TRANSLUCENT_MATERIAL : STANDARD_MATERIALS[ao.ordinal()], cullFace); + // Call processQuad instead of emit for efficiency + // (avoid unnecessarily clearing data, trying to apply transforms, and performing cull check again) + + this.processQuad(editorQuad); + } + } + } else { + final List quads = PlatformModelAccess.getInstance().getQuads(level, pos, model, state, cullFace, random, type, modelData); + final int count = quads.size(); + + for (int j = 0; j < count; j++) { + final BakedQuad q = quads.get(j); + editorQuad.fromVanilla(q, (type == RenderType.tripwire() || type == RenderType.translucent()) ? TRANSLUCENT_MATERIAL : STANDARD_MATERIALS[ao.ordinal()], cullFace); + // Call renderQuad instead of emit for efficiency + // (avoid unnecessarily clearing data) + this.renderQuad(editorQuad); + } + } + } + + editorQuad.clear(); + } + + @SuppressWarnings("removal") + @Deprecated + private class BakedModelConsumerImpl implements BakedModelConsumer { + @Override + public void accept(BakedModel model) { + accept(model, AbstractBlockRenderContext.this.state); + } + + @Override + public void accept(BakedModel model, @Nullable BlockState state) { + AbstractBlockRenderContext.this.bufferDefaultModel(model, state); + } + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/render/AbstractRenderContext.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/render/AbstractRenderContext.java new file mode 100644 index 0000000000..6074c497cf --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/render/AbstractRenderContext.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.client.render.frapi.render; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh; +import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; +import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; + +import java.util.function.Consumer; + +public abstract class AbstractRenderContext implements RenderContext { + private static final QuadTransform NO_TRANSFORM = q -> true; + + private QuadTransform activeTransform = NO_TRANSFORM; + private final ObjectArrayList transformStack = new ObjectArrayList<>(); + private final QuadTransform stackTransform = q -> { + int i = transformStack.size() - 1; + + while (i >= 0) { + if (!transformStack.get(i--).transform(q)) { + return false; + } + } + + return true; + }; + + @Deprecated + private final Consumer meshConsumer = mesh -> mesh.outputTo(getEmitter()); + + protected final boolean transform(MutableQuadView q) { + return activeTransform.transform(q); + } + + @Override + public boolean hasTransform() { + return activeTransform != NO_TRANSFORM; + } + + @Override + public void pushTransform(QuadTransform transform) { + if (transform == null) { + throw new NullPointerException("Renderer received null QuadTransform."); + } + + transformStack.push(transform); + + if (transformStack.size() == 1) { + activeTransform = transform; + } else if (transformStack.size() == 2) { + activeTransform = stackTransform; + } + } + + @Override + public void popTransform() { + transformStack.pop(); + + if (transformStack.isEmpty()) { + activeTransform = NO_TRANSFORM; + } else if (transformStack.size() == 1) { + activeTransform = transformStack.get(0); + } + } + + // Overridden to prevent allocating a lambda every time this method is called. + @Deprecated + @Override + public Consumer meshConsumer() { + return meshConsumer; + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/render/ItemRenderContext.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/render/ItemRenderContext.java new file mode 100644 index 0000000000..7b359df853 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/render/ItemRenderContext.java @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.client.render.frapi.render; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.MatrixUtil; +import net.caffeinemc.mods.sodium.client.render.frapi.helper.ColorHelper; +import net.caffeinemc.mods.sodium.client.render.frapi.mesh.EncodingFormat; +import net.caffeinemc.mods.sodium.client.render.frapi.mesh.MutableQuadViewImpl; +import net.caffeinemc.mods.sodium.client.render.texture.SpriteUtil; +import net.caffeinemc.mods.sodium.mixin.features.render.frapi.ItemRendererAccessor; +import net.caffeinemc.mods.sodium.client.services.PlatformTextureAccess; +import net.fabricmc.fabric.api.renderer.v1.material.BlendMode; +import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; +import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; +import net.fabricmc.fabric.api.util.TriState; +import net.fabricmc.fabric.impl.renderer.VanillaModelEncoder; +import net.minecraft.client.Minecraft; +import net.minecraft.client.color.item.ItemColors; +import net.minecraft.client.renderer.*; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.SingleThreadedRandomSource; +import org.jetbrains.annotations.Nullable; +import org.joml.Matrix3f; +import org.joml.Matrix4f; + +import java.util.function.Supplier; + +/** + * The render context used for item rendering. + */ +public class ItemRenderContext extends AbstractRenderContext { + /** Value vanilla uses for item rendering. The only sensible choice, of course. */ + private static final long ITEM_RANDOM_SEED = 42L; + + private final MutableQuadViewImpl editorQuad = new MutableQuadViewImpl() { + { + data = new int[EncodingFormat.TOTAL_STRIDE]; + clear(); + } + + @Override + public void emitDirectly() { + renderQuad(this); + } + }; + + @Deprecated + private final BakedModelConsumerImpl vanillaModelConsumer = new BakedModelConsumerImpl(); + + private final ItemColors colorMap; + private final VanillaModelBufferer vanillaBufferer; + + private final RandomSource random = new SingleThreadedRandomSource(ITEM_RANDOM_SEED); + private final Supplier randomSupplier = () -> { + random.setSeed(ITEM_RANDOM_SEED); + return random; + }; + + private ItemStack itemStack; + private ItemDisplayContext transformMode; + private PoseStack poseStack; + private Matrix4f matPosition; + private boolean trustedNormals; + private Matrix3f matNormal; + private MultiBufferSource bufferSource; + private int lightmap; + private int overlay; + + private boolean isDefaultTranslucent; + private boolean isTranslucentDirect; + private boolean isDefaultGlint; + private boolean isGlintDynamicDisplay; + + private PoseStack.Pose dynamicDisplayGlintEntry; + private VertexConsumer translucentVertexConsumer; + private VertexConsumer cutoutVertexConsumer; + private VertexConsumer translucentGlintVertexConsumer; + private VertexConsumer cutoutGlintVertexConsumer; + private VertexConsumer defaultVertexConsumer; + + public ItemRenderContext(ItemColors colorMap, VanillaModelBufferer vanillaBufferer) { + this.colorMap = colorMap; + this.vanillaBufferer = vanillaBufferer; + } + + @Override + public QuadEmitter getEmitter() { + editorQuad.clear(); + return editorQuad; + } + + @Override + public boolean isFaceCulled(@Nullable Direction face) { + throw new UnsupportedOperationException("isFaceCulled can only be called on a block render context."); + } + + @Override + public ItemDisplayContext itemTransformationMode() { + return transformMode; + } + + @SuppressWarnings("removal") + @Deprecated + @Override + public BakedModelConsumer bakedModelConsumer() { + return vanillaModelConsumer; + } + + public void renderModel(ItemStack itemStack, ItemDisplayContext transformMode, boolean invert, PoseStack poseStack, MultiBufferSource bufferSource, int lightmap, int overlay, BakedModel model) { + this.itemStack = itemStack; + this.transformMode = transformMode; + this.poseStack = poseStack; + matPosition = poseStack.last().pose(); + trustedNormals = poseStack.last().trustedNormals; + matNormal = poseStack.last().normal(); + this.bufferSource = bufferSource; + this.lightmap = lightmap; + this.overlay = overlay; + computeOutputInfo(); + + ((FabricBakedModel) model).emitItemQuads(itemStack, randomSupplier, this); + + this.itemStack = null; + this.poseStack = null; + this.bufferSource = null; + + dynamicDisplayGlintEntry = null; + translucentVertexConsumer = null; + cutoutVertexConsumer = null; + translucentGlintVertexConsumer = null; + cutoutGlintVertexConsumer = null; + defaultVertexConsumer = null; + } + + private void computeOutputInfo() { + isDefaultTranslucent = true; + isTranslucentDirect = true; + + Item item = itemStack.getItem(); + + if (item instanceof BlockItem blockItem) { + BlockState state = blockItem.getBlock().defaultBlockState(); + RenderType renderType = ItemBlockRenderTypes.getChunkRenderType(state); + + if (renderType != RenderType.translucent()) { + isDefaultTranslucent = false; + } + + if (transformMode != ItemDisplayContext.GUI && !transformMode.firstPerson()) { + isTranslucentDirect = false; + } + } + + isDefaultGlint = itemStack.hasFoil(); + isGlintDynamicDisplay = ItemRendererAccessor.sodium$hasAnimatedTexture(itemStack); + + defaultVertexConsumer = getVertexConsumer(BlendMode.DEFAULT, TriState.DEFAULT); + } + + private void renderQuad(MutableQuadViewImpl quad) { + if (!transform(quad)) { + return; + } + + final RenderMaterial mat = quad.material(); + final int colorIndex = mat.disableColorIndex() ? -1 : quad.colorIndex(); + final boolean emissive = mat.emissive(); + final VertexConsumer vertexConsumer = getVertexConsumer(mat.blendMode(), mat.glint()); + + colorizeQuad(quad, colorIndex); + shadeQuad(quad, emissive); + bufferQuad(quad, vertexConsumer); + } + + private void colorizeQuad(MutableQuadViewImpl quad, int colorIndex) { + if (colorIndex != -1) { + final int itemColor = colorMap.getColor(itemStack, colorIndex); + + for (int i = 0; i < 4; i++) { + quad.color(i, ColorHelper.multiplyColor(itemColor, quad.color(i))); + } + } + } + + private void shadeQuad(MutableQuadViewImpl quad, boolean emissive) { + if (emissive) { + for (int i = 0; i < 4; i++) { + quad.lightmap(i, LightTexture.FULL_BRIGHT); + } + } else { + final int lightmap = this.lightmap; + + for (int i = 0; i < 4; i++) { + quad.lightmap(i, ColorHelper.maxBrightness(quad.lightmap(i), lightmap)); + } + } + } + + private void bufferQuad(MutableQuadViewImpl quad, VertexConsumer vertexConsumer) { + QuadEncoder.writeQuadVertices(quad, vertexConsumer, overlay, matPosition, trustedNormals, matNormal); + SpriteUtil.markSpriteActive(PlatformTextureAccess.getInstance().findInBlockAtlas(quad.getTexU(0), quad.getTexV(0))); + } + + /** + * Caches custom blend mode / vertex consumers and mimics the logic + * in {@code RenderLayers.getEntityBlockLayer}. Layers other than + * translucent are mapped to cutout. + */ + private VertexConsumer getVertexConsumer(BlendMode blendMode, TriState glintMode) { + boolean translucent; + boolean glint; + + if (blendMode == BlendMode.DEFAULT) { + translucent = isDefaultTranslucent; + } else { + translucent = blendMode == BlendMode.TRANSLUCENT; + } + + if (glintMode == TriState.DEFAULT) { + glint = isDefaultGlint; + } else { + glint = glintMode == TriState.TRUE; + } + + if (translucent) { + if (glint) { + if (translucentGlintVertexConsumer == null) { + translucentGlintVertexConsumer = createTranslucentVertexConsumer(true); + } + + return translucentGlintVertexConsumer; + } else { + if (translucentVertexConsumer == null) { + translucentVertexConsumer = createTranslucentVertexConsumer(false); + } + + return translucentVertexConsumer; + } + } else { + if (glint) { + if (cutoutGlintVertexConsumer == null) { + cutoutGlintVertexConsumer = createCutoutVertexConsumer(true); + } + + return cutoutGlintVertexConsumer; + } else { + if (cutoutVertexConsumer == null) { + cutoutVertexConsumer = createCutoutVertexConsumer(false); + } + + return cutoutVertexConsumer; + } + } + } + + private VertexConsumer createTranslucentVertexConsumer(boolean glint) { + if (glint && isGlintDynamicDisplay) { + return createDynamicDisplayGlintVertexConsumer(Minecraft.useShaderTransparency() && !isTranslucentDirect ? Sheets.translucentItemSheet() : Sheets.translucentCullBlockSheet()); + } + + if (isTranslucentDirect) { + return ItemRenderer.getFoilBufferDirect(bufferSource, Sheets.translucentCullBlockSheet(), true, glint); + } else if (Minecraft.useShaderTransparency()) { + return ItemRenderer.getFoilBuffer(bufferSource, Sheets.translucentItemSheet(), true, glint); + } else { + return ItemRenderer.getFoilBuffer(bufferSource, Sheets.translucentItemSheet(), true, glint); + } + } + + private VertexConsumer createCutoutVertexConsumer(boolean glint) { + if (glint && isGlintDynamicDisplay) { + return createDynamicDisplayGlintVertexConsumer(Sheets.cutoutBlockSheet()); + } + + return ItemRenderer.getFoilBufferDirect(bufferSource, Sheets.cutoutBlockSheet(), true, glint); + } + + private VertexConsumer createDynamicDisplayGlintVertexConsumer(RenderType type) { + if (dynamicDisplayGlintEntry == null) { + dynamicDisplayGlintEntry = poseStack.last().copy(); + + if (transformMode == ItemDisplayContext.GUI) { + MatrixUtil.mulComponentWise(dynamicDisplayGlintEntry.pose(), 0.5F); + } else if (transformMode.firstPerson()) { + MatrixUtil.mulComponentWise(dynamicDisplayGlintEntry.pose(), 0.75F); + } + } + + return ItemRenderer.getCompassFoilBuffer(bufferSource, type, dynamicDisplayGlintEntry); + } + + public void bufferDefaultModel(BakedModel model, @Nullable BlockState state) { + if (hasTransform() || vanillaBufferer == null) { + VanillaModelEncoder.emitItemQuads(model, state, randomSupplier, ItemRenderContext.this); + } else { + vanillaBufferer.accept(model, itemStack, lightmap, overlay, poseStack, defaultVertexConsumer); + } + } + + @SuppressWarnings("removal") + @Deprecated + private class BakedModelConsumerImpl implements BakedModelConsumer { + @Override + public void accept(BakedModel model) { + accept(model, null); + } + + @Override + public void accept(BakedModel model, @Nullable BlockState state) { + bufferDefaultModel(model, state); + } + } + + /** used to accept a method reference from the ItemRenderer. */ + @FunctionalInterface + public interface VanillaModelBufferer { + void accept(BakedModel model, ItemStack stack, int color, int overlay, PoseStack matrixStack, VertexConsumer buffer); + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/render/NonTerrainBlockRenderContext.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/render/NonTerrainBlockRenderContext.java new file mode 100644 index 0000000000..ae8eab1bbf --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/render/NonTerrainBlockRenderContext.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.client.render.frapi.render; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.caffeinemc.mods.sodium.client.model.light.LightMode; +import net.caffeinemc.mods.sodium.client.model.light.LightPipelineProvider; +import net.caffeinemc.mods.sodium.client.model.light.data.SingleBlockLightDataCache; +import net.caffeinemc.mods.sodium.client.render.frapi.helper.ColorHelper; +import net.caffeinemc.mods.sodium.client.render.frapi.mesh.MutableQuadViewImpl; +import net.caffeinemc.mods.sodium.client.render.texture.SpriteUtil; +import net.caffeinemc.mods.sodium.client.services.PlatformTextureAccess; +import net.caffeinemc.mods.sodium.client.services.SodiumModelData; +import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; +import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; +import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.client.color.block.BlockColors; +import net.minecraft.client.renderer.ItemBlockRenderTypes; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; +import org.joml.Matrix3f; +import org.joml.Matrix4f; + +public class NonTerrainBlockRenderContext extends AbstractBlockRenderContext { + private final BlockColors colorMap; + private final SingleBlockLightDataCache lightDataCache = new SingleBlockLightDataCache(); + + private VertexConsumer vertexConsumer; + private Matrix4f matPosition; + private boolean trustedNormals; + private Matrix3f matNormal; + private int overlay; + + public NonTerrainBlockRenderContext(BlockColors colorMap) { + this.colorMap = colorMap; + this.lighters = new LightPipelineProvider(this.lightDataCache); + } + + public void renderModel(BlockAndTintGetter blockView, BakedModel model, BlockState state, BlockPos pos, PoseStack poseStack, VertexConsumer buffer, boolean cull, RandomSource random, long seed, int overlay) { + this.level = blockView; + this.state = state; + this.pos = pos; + + this.random = random; + this.randomSeed = seed; + + this.vertexConsumer = buffer; + this.matPosition = poseStack.last().pose(); + this.trustedNormals = poseStack.last().trustedNormals; + this.matNormal = poseStack.last().normal(); + this.overlay = overlay; + this.type = ItemBlockRenderTypes.getChunkRenderType(state); + this.modelData = SodiumModelData.EMPTY; + + this.lightDataCache.reset(pos, blockView); + this.prepareCulling(cull); + this.prepareAoInfo(model.useAmbientOcclusion()); + + ((FabricBakedModel) model).emitBlockQuads(blockView, state, pos, this.randomSupplier, this); + + this.level = null; + this.type = null; + this.modelData = null; + this.lightDataCache.release(); + this.random = null; + this.vertexConsumer = null; + } + + @Override + protected void processQuad(MutableQuadViewImpl quad) { + final RenderMaterial mat = quad.material(); + final int colorIndex = mat.disableColorIndex() ? -1 : quad.colorIndex(); + final TriState aoMode = mat.ambientOcclusion(); + final LightMode lightMode; + if (aoMode == TriState.DEFAULT) { + lightMode = this.defaultLightMode; + } else { + lightMode = this.useAmbientOcclusion && aoMode.get() ? LightMode.SMOOTH : LightMode.FLAT; + } + final boolean emissive = mat.emissive(); + + colorizeQuad(quad, colorIndex); + shadeQuad(quad, lightMode, emissive); + bufferQuad(quad); + } + + private void colorizeQuad(MutableQuadViewImpl quad, int colorIndex) { + if (colorIndex != -1) { + final int blockColor = 0xFF000000 | this.colorMap.getColor(this.state, this.level, this.pos, colorIndex); + + for (int i = 0; i < 4; i++) { + quad.color(i, ColorHelper.multiplyColor(blockColor, quad.color(i))); + } + } + } + + @Override + protected void shadeQuad(MutableQuadViewImpl quad, LightMode lightMode, boolean emissive) { + super.shadeQuad(quad, lightMode, emissive); + + float[] brightnesses = this.quadLightData.br; + + for (int i = 0; i < 4; i++) { + quad.color(i, ColorHelper.multiplyRGB(quad.color(i), brightnesses[i])); + } + } + + private void bufferQuad(MutableQuadViewImpl quad) { + QuadEncoder.writeQuadVertices(quad, vertexConsumer, overlay, matPosition, trustedNormals, matNormal); + SpriteUtil.markSpriteActive(PlatformTextureAccess.getInstance().findInBlockAtlas(quad.getTexU(0), quad.getTexV(0))); + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/render/QuadEncoder.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/render/QuadEncoder.java new file mode 100644 index 0000000000..b9fe658704 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/render/QuadEncoder.java @@ -0,0 +1,140 @@ +package net.caffeinemc.mods.sodium.client.render.frapi.render; + +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.caffeinemc.mods.sodium.client.render.frapi.mesh.MutableQuadViewImpl; +import net.caffeinemc.mods.sodium.client.render.vertex.VertexConsumerUtils; +import net.caffeinemc.mods.sodium.api.math.MatrixHelper; +import net.caffeinemc.mods.sodium.api.util.ColorARGB; +import net.caffeinemc.mods.sodium.api.util.NormI8; +import net.caffeinemc.mods.sodium.api.vertex.buffer.VertexBufferWriter; +import net.caffeinemc.mods.sodium.api.vertex.format.common.ModelVertex; +import org.joml.Math; +import org.joml.Matrix3f; +import org.joml.Matrix4f; +import org.joml.Vector3f; +import org.lwjgl.system.MemoryStack; + +public class QuadEncoder { + public static void writeQuadVertices(MutableQuadViewImpl quad, VertexConsumer vertexConsumer, int overlay, Matrix4f matPosition, boolean trustedNormals, Matrix3f matNormal) { + VertexBufferWriter writer = VertexConsumerUtils.convertOrLog(vertexConsumer); + + if (writer != null) { + writeQuadVertices(quad, writer, overlay, matPosition, trustedNormals, matNormal); + } else { + writeQuadVerticesSlow(quad, vertexConsumer, overlay, matPosition, trustedNormals, matNormal); + } + } + + public static void writeQuadVertices(MutableQuadViewImpl quad, VertexBufferWriter writer, int overlay, Matrix4f matPosition, boolean trustedNormals, Matrix3f matNormal) { + try (MemoryStack stack = MemoryStack.stackPush()) { + long buffer = stack.nmalloc(4 * ModelVertex.STRIDE); + long ptr = buffer; + + final boolean useNormals = quad.hasVertexNormals(); + + // The packed transformed normal vector + int normal = 0; + + if (useNormals) { + quad.populateMissingNormals(); + } else { + normal = MatrixHelper.transformNormal(matNormal, trustedNormals, quad.packedFaceNormal()); + } + + for (int i = 0; i < 4; i++) { + // The position vector + float x = quad.x(i); + float y = quad.y(i); + float z = quad.z(i); + + // The transformed position vector + float xt = MatrixHelper.transformPositionX(matPosition, x, y, z); + float yt = MatrixHelper.transformPositionY(matPosition, x, y, z); + float zt = MatrixHelper.transformPositionZ(matPosition, x, y, z); + + if (useNormals) { + normal = MatrixHelper.transformNormal(matNormal, trustedNormals, quad.packedNormal(i)); + } + + ModelVertex.write(ptr, xt, yt, zt, ColorARGB.toABGR(quad.color(i)), quad.u(i), quad.v(i), overlay, quad.lightmap(i), normal); + ptr += ModelVertex.STRIDE; + } + + writer.push(stack, buffer, 4, ModelVertex.FORMAT); + } + } + + private static void writeQuadVerticesSlow(MutableQuadViewImpl quad, VertexConsumer vertexConsumer, int overlay, Matrix4f matPosition, boolean trustedNormals, Matrix3f matNormal) { + final boolean useNormals = quad.hasVertexNormals(); + + // The transformed normal vector + float nxt = 0; + float nyt = 0; + float nzt = 0; + + if (useNormals) { + quad.populateMissingNormals(); + } else { + Vector3f faceNormal = quad.faceNormal(); + + // The normal vector + float nx = faceNormal.x; + float ny = faceNormal.y; + float nz = faceNormal.z; + + nxt = MatrixHelper.transformNormalX(matNormal, nx, ny, nz); + nyt = MatrixHelper.transformNormalY(matNormal, nx, ny, nz); + nzt = MatrixHelper.transformNormalZ(matNormal, nx, ny, nz); + + if (!trustedNormals) { + float scalar = Math.invsqrt(Math.fma(nxt, nxt, Math.fma(nyt, nyt, nzt * nzt))); + + nxt *= scalar; + nyt *= scalar; + nzt *= scalar; + } + } + + for (int i = 0; i < 4; i++) { + // The position vector + float x = quad.x(i); + float y = quad.y(i); + float z = quad.z(i); + + // The transformed position vector + float xt = MatrixHelper.transformPositionX(matPosition, x, y, z); + float yt = MatrixHelper.transformPositionY(matPosition, x, y, z); + float zt = MatrixHelper.transformPositionZ(matPosition, x, y, z); + + vertexConsumer.addVertex(xt, yt, zt); + + vertexConsumer.setColor(quad.color(i)); + vertexConsumer.setUv(quad.u(i), quad.v(i)); + vertexConsumer.setOverlay(overlay); + vertexConsumer.setLight(quad.lightmap(i)); + + if (useNormals) { + int packedNormal = quad.packedNormal(i); + + // The normal vector + float nx = NormI8.unpackX(packedNormal); + float ny = NormI8.unpackY(packedNormal); + float nz = NormI8.unpackZ(packedNormal); + + nxt = MatrixHelper.transformNormalX(matNormal, nx, ny, nz); + nyt = MatrixHelper.transformNormalY(matNormal, nx, ny, nz); + nzt = MatrixHelper.transformNormalZ(matNormal, nx, ny, nz); + + if (!trustedNormals) { + float scalar = Math.invsqrt(Math.fma(nxt, nxt, Math.fma(nyt, nyt, nzt * nzt))); + + nxt *= scalar; + nyt *= scalar; + nzt *= scalar; + } + } + + vertexConsumer.setNormal(nxt, nyt, nzt); + } + } +} diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/CloudRenderer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/CloudRenderer.java similarity index 95% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/CloudRenderer.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/CloudRenderer.java index ab9c3c8fec..cb92773cd7 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/CloudRenderer.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/CloudRenderer.java @@ -201,7 +201,7 @@ public void render(Camera camera, } } - MeshData meshData = bufferBuilder.build(); + MeshData builtBuffer = bufferBuilder.buildOrThrow(); VertexBuffer vertexBuffer; @@ -211,9 +211,7 @@ public void render(Camera camera, vertexBuffer = new VertexBuffer(VertexBuffer.Usage.DYNAMIC); } - if (meshData != null) { - uploadToVertexBuffer(vertexBuffer, meshData); - } + uploadToVertexBuffer(vertexBuffer, builtBuffer); Tesselator.getInstance().clear(); @@ -337,23 +335,15 @@ private static void emitCellGeometry2D(VertexBufferWriter writer, int faces, int final long buffer = stack.nmalloc(4 * ColorVertex.STRIDE); long ptr = buffer; - int count = 0; - // -Y - if (CloudFaceSet.contains(faces, CloudFace.NEG_Y)) { - int mixedColor = ColorMixer.mul(color, CloudFace.POS_Y.getColor()); + int mixedColor = ColorMixer.mul(color, CloudFace.POS_Y.getColor()); - ptr = writeVertex(ptr, x + 12.0f, 0.0f, z + 12.0f, mixedColor); - ptr = writeVertex(ptr, x + 0.0f, 0.0f, z + 12.0f, mixedColor); - ptr = writeVertex(ptr, x + 0.0f, 0.0f, z + 0.0f, mixedColor); - ptr = writeVertex(ptr, x + 12.0f, 0.0f, z + 0.0f, mixedColor); - - count += 4; - } + ptr = writeVertex(ptr, x + 12.0f, 0.0f, z + 12.0f, mixedColor); + ptr = writeVertex(ptr, x + 0.0f, 0.0f, z + 12.0f, mixedColor); + ptr = writeVertex(ptr, x + 0.0f, 0.0f, z + 0.0f, mixedColor); + ptr = writeVertex(ptr, x + 12.0f, 0.0f, z + 0.0f, mixedColor); - if (count > 0) { - writer.push(stack, buffer, count, ColorVertex.FORMAT); - } + writer.push(stack, buffer, 4, ColorVertex.FORMAT); } } @@ -396,9 +386,9 @@ private static long writeVertex(long buffer, float x, float y, float z, int colo return buffer + ColorVertex.STRIDE; } - private static void uploadToVertexBuffer(VertexBuffer vertexBuffer, MeshData meshData) { + private static void uploadToVertexBuffer(VertexBuffer vertexBuffer, MeshData builtBuffer) { vertexBuffer.bind(); - vertexBuffer.upload(meshData); + vertexBuffer.upload(builtBuffer); VertexBuffer.unbind(); } @@ -623,11 +613,11 @@ private int getCellIndex(int x, int z) { } } - private record CloudGeometry(VertexBuffer vertexBuffer, CloudGeometryParameters params) { + public record CloudGeometry(VertexBuffer vertexBuffer, CloudGeometryParameters params) { } - private record CloudGeometryParameters(int originX, int originZ, int radius, int orientation, CloudStatus renderMode) { + public record CloudGeometryParameters(int originX, int originZ, int radius, int orientation, CloudStatus renderMode) { } } diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/BakedModelEncoder.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/BakedModelEncoder.java similarity index 79% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/BakedModelEncoder.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/BakedModelEncoder.java index fe9a6204fa..539e8ad3a6 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/BakedModelEncoder.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/BakedModelEncoder.java @@ -7,11 +7,20 @@ import net.caffeinemc.mods.sodium.api.util.ColorU8; import net.caffeinemc.mods.sodium.api.vertex.buffer.VertexBufferWriter; import net.caffeinemc.mods.sodium.api.vertex.format.common.ModelVertex; +import net.caffeinemc.mods.sodium.client.render.frapi.helper.ColorHelper; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.lwjgl.system.MemoryStack; public class BakedModelEncoder { + private static int mergeLighting(int stored, int calculated) { + if (stored == 0) return calculated; + + int blockLight = Math.max(stored & 0xFFFF, calculated & 0xFFFF); + int skyLight = Math.max((stored >> 16) & 0xFFFF, (calculated >> 16) & 0xFFFF); + return blockLight | (skyLight << 16); + } + public static void writeQuadVertices(VertexBufferWriter writer, PoseStack.Pose matrices, ModelQuadView quad, int color, int light, int overlay) { Matrix3f matNormal = matrices.normal(); Matrix4f matPosition = matrices.pose(); @@ -20,21 +29,23 @@ public static void writeQuadVertices(VertexBufferWriter writer, PoseStack.Pose m long buffer = stack.nmalloc(4 * ModelVertex.STRIDE); long ptr = buffer; - // The packed transformed normal vector - var normal = MatrixHelper.transformNormal(matNormal, matrices.trustedNormals, quad.getLightFace()); - for (int i = 0; i < 4; i++) { // The position vector float x = quad.getX(i); float y = quad.getY(i); float z = quad.getZ(i); + int newLight = mergeLighting(quad.getLight(i), light); + + // The packed transformed normal vector + int normal = MatrixHelper.transformNormal(matNormal, matrices.trustedNormals, quad.getAccurateNormal(i)); + // The transformed position vector float xt = MatrixHelper.transformPositionX(matPosition, x, y, z); float yt = MatrixHelper.transformPositionY(matPosition, x, y, z); float zt = MatrixHelper.transformPositionZ(matPosition, x, y, z); - ModelVertex.write(ptr, xt, yt, zt, color, quad.getTexU(i), quad.getTexV(i), overlay, light, normal); + ModelVertex.write(ptr, xt, yt, zt, ColorHelper.multiplyColor(color, quad.getColor(i)), quad.getTexU(i), quad.getTexV(i), overlay, newLight, normal); ptr += ModelVertex.STRIDE; } @@ -50,9 +61,6 @@ public static void writeQuadVertices(VertexBufferWriter writer, PoseStack.Pose m long buffer = stack.nmalloc(4 * ModelVertex.STRIDE); long ptr = buffer; - // The packed transformed normal vector - var normal = MatrixHelper.transformNormal(matNormal, matrices.trustedNormals, quad.getLightFace()); - for (int i = 0; i < 4; i++) { // The position vector float x = quad.getX(i); @@ -68,6 +76,8 @@ public static void writeQuadVertices(VertexBufferWriter writer, PoseStack.Pose m float fG; float fB; + var normal = MatrixHelper.transformNormal(matNormal, matrices.trustedNormals, quad.getAccurateNormal(i)); + float brightness = brightnessTable[i]; if (colorize) { diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/EntityRenderer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/EntityRenderer.java similarity index 70% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/EntityRenderer.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/EntityRenderer.java index 8dffd7ef4f..434d2dc7c6 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/EntityRenderer.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/EntityRenderer.java @@ -4,9 +4,8 @@ import net.caffeinemc.mods.sodium.api.math.MatrixHelper; import net.caffeinemc.mods.sodium.api.vertex.buffer.VertexBufferWriter; import net.caffeinemc.mods.sodium.api.vertex.format.common.ModelVertex; -import net.minecraft.client.model.geom.ModelPart; import net.minecraft.core.Direction; -import org.apache.commons.lang3.ArrayUtils; +import org.joml.Matrix3f; import org.joml.Matrix4f; import org.joml.Vector2f; import org.joml.Vector3f; @@ -37,6 +36,7 @@ public class EntityRenderer { VERTEX_X2_Y2_Z2 = 6, VERTEX_X1_Y2_Z2 = 7; + private static final Matrix3f lastMatrix = new Matrix3f(); private static final long SCRATCH_BUFFER = MemoryUtil.nmemAlignedAlloc(64, NUM_CUBE_FACES * NUM_FACE_VERTICES * ModelVertex.STRIDE); @@ -79,50 +79,15 @@ public class EntityRenderer { } } - public static void render(PoseStack poseStack, VertexBufferWriter writer, ModelPart part, int light, int overlay, int color) { - ModelPartData accessor = ModelPartData.from(part); - - if (!accessor.isVisible()) { - return; - } - - var cuboids = accessor.getCuboids(); - var children = accessor.getChildren(); - - if (ArrayUtils.isEmpty(cuboids) && ArrayUtils.isEmpty(children)) { - return; - } - - poseStack.pushPose(); + public static void renderCuboid(PoseStack.Pose matrices, VertexBufferWriter writer, ModelCuboid cuboid, int light, int overlay, int color) { + prepareNormalsIfChanged(matrices); - part.translateAndRotate(poseStack); + prepareVertices(matrices, cuboid); - if (!accessor.isHidden()) { - renderCuboids(poseStack.last(), writer, cuboids, light, overlay, color); - } - - renderChildren(poseStack, writer, light, overlay, color, children); - - poseStack.popPose(); - } + var vertexCount = emitQuads(cuboid, color, overlay, light); - private static void renderChildren(PoseStack poseStack, VertexBufferWriter writer, int light, int overlay, int color, ModelPart[] children) { - for (ModelPart part : children) { - render(poseStack, writer, part, light, overlay, color); - } - } - - private static void renderCuboids(PoseStack.Pose matrices, VertexBufferWriter writer, ModelCuboid[] cuboids, int light, int overlay, int color) { - prepareNormals(matrices); - - for (ModelCuboid cuboid : cuboids) { - prepareVertices(matrices, cuboid); - - var vertexCount = emitQuads(cuboid, color, overlay, light); - - try (MemoryStack stack = MemoryStack.stackPush()) { - writer.push(stack, SCRATCH_BUFFER, vertexCount, ModelVertex.FORMAT); - } + try (MemoryStack stack = MemoryStack.stackPush()) { + writer.push(stack, SCRATCH_BUFFER, vertexCount, ModelVertex.FORMAT); } } @@ -180,21 +145,25 @@ private static void prepareVertices(PoseStack.Pose matrices, ModelCuboid cuboid) buildVertexTexCoord(VERTEX_TEXTURES[FACE_POS_X], cuboid.u0, cuboid.v1, cuboid.u1, cuboid.v2); } - private static void prepareNormals(PoseStack.Pose matrices) { - CUBE_NORMALS[FACE_NEG_Y] = MatrixHelper.transformNormal(matrices.normal(), matrices.trustedNormals, Direction.DOWN); - CUBE_NORMALS[FACE_POS_Y] = MatrixHelper.transformNormal(matrices.normal(), matrices.trustedNormals, Direction.UP); - CUBE_NORMALS[FACE_NEG_Z] = MatrixHelper.transformNormal(matrices.normal(), matrices.trustedNormals, Direction.NORTH); - CUBE_NORMALS[FACE_POS_Z] = MatrixHelper.transformNormal(matrices.normal(), matrices.trustedNormals, Direction.SOUTH); - CUBE_NORMALS[FACE_POS_X] = MatrixHelper.transformNormal(matrices.normal(), matrices.trustedNormals, Direction.WEST); - CUBE_NORMALS[FACE_NEG_X] = MatrixHelper.transformNormal(matrices.normal(), matrices.trustedNormals, Direction.EAST); - - // When mirroring is used, the normals for EAST and WEST are swapped. - CUBE_NORMALS_MIRRORED[FACE_NEG_Y] = CUBE_NORMALS[FACE_NEG_Y]; - CUBE_NORMALS_MIRRORED[FACE_POS_Y] = CUBE_NORMALS[FACE_POS_Y]; - CUBE_NORMALS_MIRRORED[FACE_NEG_Z] = CUBE_NORMALS[FACE_NEG_Z]; - CUBE_NORMALS_MIRRORED[FACE_POS_Z] = CUBE_NORMALS[FACE_POS_Z]; - CUBE_NORMALS_MIRRORED[FACE_POS_X] = CUBE_NORMALS[FACE_NEG_X]; // mirrored - CUBE_NORMALS_MIRRORED[FACE_NEG_X] = CUBE_NORMALS[FACE_POS_X]; // mirrored + public static void prepareNormalsIfChanged(PoseStack.Pose matrices) { + if (!matrices.normal().equals(lastMatrix)) { + lastMatrix.set(matrices.normal()); + + CUBE_NORMALS[FACE_NEG_Y] = MatrixHelper.transformNormal(matrices.normal(), matrices.trustedNormals, Direction.DOWN); + CUBE_NORMALS[FACE_POS_Y] = MatrixHelper.transformNormal(matrices.normal(), matrices.trustedNormals, Direction.UP); + CUBE_NORMALS[FACE_NEG_Z] = MatrixHelper.transformNormal(matrices.normal(), matrices.trustedNormals, Direction.NORTH); + CUBE_NORMALS[FACE_POS_Z] = MatrixHelper.transformNormal(matrices.normal(), matrices.trustedNormals, Direction.SOUTH); + CUBE_NORMALS[FACE_POS_X] = MatrixHelper.transformNormal(matrices.normal(), matrices.trustedNormals, Direction.WEST); + CUBE_NORMALS[FACE_NEG_X] = MatrixHelper.transformNormal(matrices.normal(), matrices.trustedNormals, Direction.EAST); + + // When mirroring is used, the normals for EAST and WEST are swapped. + CUBE_NORMALS_MIRRORED[FACE_NEG_Y] = CUBE_NORMALS[FACE_NEG_Y]; + CUBE_NORMALS_MIRRORED[FACE_POS_Y] = CUBE_NORMALS[FACE_POS_Y]; + CUBE_NORMALS_MIRRORED[FACE_NEG_Z] = CUBE_NORMALS[FACE_NEG_Z]; + CUBE_NORMALS_MIRRORED[FACE_POS_Z] = CUBE_NORMALS[FACE_POS_Z]; + CUBE_NORMALS_MIRRORED[FACE_POS_X] = CUBE_NORMALS[FACE_NEG_X]; // mirrored + CUBE_NORMALS_MIRRORED[FACE_NEG_X] = CUBE_NORMALS[FACE_POS_X]; // mirrored + } } private static void buildVertexPosition(Vector3f vector, float x, float y, float z, Matrix4f matrix) { diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/ModelCuboid.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/ModelCuboid.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/ModelCuboid.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/ModelCuboid.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/texture/SpriteContentsExtension.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/texture/SpriteContentsExtension.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/texture/SpriteContentsExtension.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/texture/SpriteContentsExtension.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/texture/SpriteUtil.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/texture/SpriteUtil.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/texture/SpriteUtil.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/texture/SpriteUtil.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/util/DeferredRenderTask.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/util/DeferredRenderTask.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/util/DeferredRenderTask.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/util/DeferredRenderTask.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/util/RenderAsserts.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/util/RenderAsserts.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/util/RenderAsserts.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/util/RenderAsserts.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/VertexConsumerTracker.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/VertexConsumerTracker.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/VertexConsumerTracker.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/VertexConsumerTracker.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/VertexConsumerUtils.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/VertexConsumerUtils.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/VertexConsumerUtils.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/VertexConsumerUtils.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/VertexFormatDescriptionImpl.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/VertexFormatDescriptionImpl.java similarity index 97% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/VertexFormatDescriptionImpl.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/VertexFormatDescriptionImpl.java index 1709326113..1cea64380b 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/VertexFormatDescriptionImpl.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/VertexFormatDescriptionImpl.java @@ -32,7 +32,7 @@ private static boolean checkSimple(VertexFormat format) { for (int elementIndex = 0; elementIndex < elementList.size(); elementIndex++) { var element = elementList.get(elementIndex); var commonType = CommonVertexAttribute.getCommonType(element); - if (commonType == null || !attributeSet.add(commonType)) { + if ((commonType == null || !attributeSet.add(commonType))) { return false; } } diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/VertexFormatRegistryImpl.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/VertexFormatRegistryImpl.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/VertexFormatRegistryImpl.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/VertexFormatRegistryImpl.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/buffer/BufferBuilderExtension.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/buffer/BufferBuilderExtension.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/buffer/BufferBuilderExtension.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/buffer/BufferBuilderExtension.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/serializers/VertexSerializerRegistryImpl.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/serializers/VertexSerializerRegistryImpl.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/serializers/VertexSerializerRegistryImpl.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/serializers/VertexSerializerRegistryImpl.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/serializers/generated/VertexSerializerFactory.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/serializers/generated/VertexSerializerFactory.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/serializers/generated/VertexSerializerFactory.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/vertex/serializers/generated/VertexSerializerFactory.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/CameraTransform.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/CameraTransform.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/CameraTransform.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/CameraTransform.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/Viewport.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/Viewport.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/Viewport.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/Viewport.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/ViewportProvider.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/ViewportProvider.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/ViewportProvider.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/ViewportProvider.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/frustum/Frustum.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/frustum/Frustum.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/frustum/Frustum.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/frustum/Frustum.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/frustum/SimpleFrustum.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/frustum/SimpleFrustum.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/frustum/SimpleFrustum.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/render/viewport/frustum/SimpleFrustum.java diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/services/PlatformBlockAccess.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/services/PlatformBlockAccess.java new file mode 100644 index 0000000000..18aa1346cf --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/services/PlatformBlockAccess.java @@ -0,0 +1,91 @@ +package net.caffeinemc.mods.sodium.client.services; + +import net.caffeinemc.mods.sodium.client.model.color.ColorProviderRegistry; +import net.caffeinemc.mods.sodium.client.model.light.LightPipelineProvider; +import net.caffeinemc.mods.sodium.client.model.quad.ModelQuadView; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.FluidRenderer; +import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +public interface PlatformBlockAccess { + PlatformBlockAccess INSTANCE = Services.load(PlatformBlockAccess.class); + + static PlatformBlockAccess getInstance() { + return INSTANCE; + } + + /** + * Gets the light emission of the current block. + * @param state The current block + * @param level The current level slice + * @param pos The block position + * @return The light emission of the current block (default 0) + */ + int getLightEmission(BlockState state, BlockAndTintGetter level, BlockPos pos); + + /** + * Checks if the block should stop drawing a specific side based on the adjacent block. + * @param level The level slice. + * @param selfState The block currently being drawn. + * @param otherState The adjacent block. + * @param selfPos The current block position. + * @param otherPos The other block position. + * @param facing The direction between the two blocks. + * @return If the block's face should be skipped. + */ + boolean shouldSkipRender(BlockGetter level, BlockState selfState, BlockState otherState, BlockPos selfPos, BlockPos otherPos, Direction facing); + + /** + * Returns if the fluid should render fluid overlays if a block is adjacent to it. + * @param block The block adjacent to the fluid being rendered + * @param level The level slice + * @param pos The position of the adjacent block + * @param fluidState The fluid + * @return True if the fluid should render an overlay. + */ + boolean shouldShowFluidOverlay(BlockState block, BlockAndTintGetter level, BlockPos pos, FluidState fluidState); + + /** + * Gets the specialized render data for this block entity. + * @param blockEntity The block entity to get the render data of. + * @return The specialized render data for this block entity. If the platform does not support it or there is no data, null. + */ + @Nullable + Object getBlockEntityData(BlockEntity blockEntity); + + /** + * @return If the platform can return block entity data + */ + boolean platformHasBlockData(); + + /** + * Gets the block shade. + * @param quad The quad being rendered. + * @param level The level. + * @param shade If directional lighting should be added. + * @return the block shade + */ + float getAccurateBlockShade(ModelQuadView quad, BlockAndTintGetter level, boolean shade); + + /** + * If the block contains forced ambient occlusion. + * @param model The model being rendered + * @param state The current block + * @param data Any model data + * @param renderType The current render type being drawn + * @param level The level slice + * @param pos The current position + * @return If ambient occlusion is forced, or {@code DEFAULT} + */ + TriState usesAmbientOcclusion(BakedModel model, BlockState state, SodiumModelData data, RenderType renderType, BlockAndTintGetter level, BlockPos pos); +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/services/PlatformInfoAccess.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/services/PlatformInfoAccess.java new file mode 100644 index 0000000000..9945809e94 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/services/PlatformInfoAccess.java @@ -0,0 +1,46 @@ +package net.caffeinemc.mods.sodium.client.services; + +import java.nio.file.Path; + +public interface PlatformInfoAccess { + PlatformInfoAccess INSTANCE = Services.load(PlatformInfoAccess.class); + + static PlatformInfoAccess getInstance() { + return INSTANCE; + } + + /** + * Returns if the user is running in a development environment. + */ + boolean isDevelopmentEnvironment(); + + /** + * Returns the current game directory the user is running in. + */ + Path getGameDirectory(); + + /** + * Returns the current configuration directory for the platform. + */ + Path getConfigDirectory(); + + /** + * Returns if the FREX Flawless Frames API has been requested by a mod. + */ + boolean isFlawlessFramesActive(); + + /** + * Returns if the platform has a early loading screen. + */ + boolean platformHasEarlyLoadingScreen(); + + /** + * Returns if the platform uses refmaps. + */ + boolean platformUsesRefmap(); + + /** + * Returns if a mod is in the mods folder during loading. + */ + boolean isModInLoadingList(String modId); +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/services/PlatformLevelAccess.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/services/PlatformLevelAccess.java new file mode 100644 index 0000000000..bcc2b66ddd --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/services/PlatformLevelAccess.java @@ -0,0 +1,79 @@ +package net.caffeinemc.mods.sodium.client.services; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.caffeinemc.mods.sodium.client.model.color.ColorProviderRegistry; +import net.caffeinemc.mods.sodium.client.model.light.LightPipelineProvider; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.FluidRenderer; +import net.caffeinemc.mods.sodium.client.world.LevelSlice; +import net.minecraft.client.Camera; +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.culling.Frustum; +import net.minecraft.core.BlockPos; +import net.minecraft.core.SectionPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.chunk.LevelChunk; +import org.jetbrains.annotations.Nullable; +import org.joml.Matrix4f; + +import java.util.List; +import java.util.function.Function; + +public interface PlatformLevelAccess { + PlatformLevelAccess INSTANCE = Services.load(PlatformLevelAccess.class); + + static PlatformLevelAccess getInstance() { + return INSTANCE; + } + + /** + * Creates a new platform dependent fluid renderer. + * @param colorRegistry The current color registry. + * @param lightPipelineProvider The current {@code LightPipelineProvider}. + * @return A new fluid renderer. + */ + FluidRenderer createPlatformFluidRenderer(ColorProviderRegistry colorRegistry, LightPipelineProvider lightPipelineProvider); + + /** + * Should be run in the top of the Vanilla fluid renderer. If true, cancel the Vanilla render. + * @return if the vanilla rendering should be cancelled. + */ + boolean tryRenderFluid(); + + /** + * Runs any events after drawing a chunk layer. + * @param renderLayer The current chunk layer that was drawn + * @param levelRenderer The level renderer + * @param modelMatrix The current modelview matrix + * @param projectionMatrix The current projection matrix + * @param ticks The current tick count + * @param mainCamera The current camera + * @param cullingFrustum The current frustum + */ + void runChunkLayerEvents(RenderType renderLayer, LevelRenderer levelRenderer, Matrix4f modelMatrix, Matrix4f projectionMatrix, int ticks, Camera mainCamera, Frustum cullingFrustum); + + /** + * Returns any NeoForge chunk renderers to run. This is not thread safe. + * @param level The current level + * @param origin The origin of the current chunk + * @return Any NeoForge chunk renderers to run + */ + List getExtraRenderers(Level level, BlockPos origin); + + /** + * Runs any NeoForge chunk renderers. + * @param renderers The list of chunk renderers to run. + * @param typeToConsumer A consumer that converts render types to vertex consumers + * @param slice The current level slice + */ + void renderAdditionalRenderers(List renderers, Function typeToConsumer, LevelSlice slice); + + /** + * Gets the current light manager for the chunk section. + * @param chunk The current chunk. + * @param pos The section within that chunk being drawn. + * @return The current light manager, or null + */ + @Nullable Object getLightManager(LevelChunk chunk, SectionPos pos); +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/services/PlatformModelAccess.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/services/PlatformModelAccess.java new file mode 100644 index 0000000000..efca9b4d44 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/services/PlatformModelAccess.java @@ -0,0 +1,77 @@ +package net.caffeinemc.mods.sodium.client.services; + +import net.caffeinemc.mods.sodium.client.world.LevelSlice; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.SectionPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.ApiStatus; + +import java.util.List; + +public interface PlatformModelAccess { + PlatformModelAccess INSTANCE = Services.load(PlatformModelAccess.class); + + static PlatformModelAccess getInstance() { + return INSTANCE; + } + + /** + * Returns all the render types used by this model. + * @param level The level slice. + * @param model The {@code BakedModel} currently being drawn. + * @param state The block state of the current block. + * @param pos The position of the block being rendered. + * @param random The random source used by the current block renderer. + * @param modelData The platform specific model data. + * @return A list of render types used by this model. + */ + Iterable getModelRenderTypes(BlockAndTintGetter level, BakedModel model, BlockState state, BlockPos pos, RandomSource random, SodiumModelData modelData); + + /** + * Returns a list of quads used by this model. + * @param level The level slice. + * @param pos The position of the block being rendered. + * @param model The {@code BakedModel} currently being drawn. + * @param state The block state of the current block. + * @param face The current face of the block being rendered, or null if rendering unassigned quads. + * @param random The random source used by the current block renderer. + * @param renderType The current render type being drawn. + * @param modelData The platform specific model data. + * @return The list of quads used by the model. + */ + List getQuads(BlockAndTintGetter level, BlockPos pos, BakedModel model, BlockState state, Direction face, RandomSource random, RenderType renderType, SodiumModelData modelData); + + /** + * Gets the container holding model data for this chunk. This operation is not thread safe. + * @param level The current vanilla Level. + * @param sectionPos The current chunk position. + * @return The model data container for this section + */ + SodiumModelDataContainer getModelDataContainer(Level level, SectionPos sectionPos); + + /** + * Gets the true model data from the block data in the container. + * @param slice The current world slice. + * @param model The current model. + * @param state The current block. + * @param pos The current block position. + * @param originalData The model data, as retrieved by {@code getModelDataContainer()}. + * @return The true model data, to render with. + */ + SodiumModelData getModelData(LevelSlice slice, BakedModel model, BlockState state, BlockPos pos, SodiumModelData originalData); + + /** + * Should not use. Use {@code SodiumModelData.EMPTY} instead. + * @return The empty model data for this platform. + */ + @ApiStatus.Internal + SodiumModelData getEmptyModelData(); +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/services/PlatformTextureAccess.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/services/PlatformTextureAccess.java new file mode 100644 index 0000000000..b6f0444860 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/services/PlatformTextureAccess.java @@ -0,0 +1,19 @@ +package net.caffeinemc.mods.sodium.client.services; + +import net.minecraft.client.renderer.texture.TextureAtlasSprite; + +public interface PlatformTextureAccess { + PlatformTextureAccess INSTANCE = Services.load(PlatformTextureAccess.class); + + static PlatformTextureAccess getInstance() { + return INSTANCE; + } + + /** + * Finds the current sprite in the block atlas ({@code TextureAtlas.LOCATION_BLOCKS}) + * @param texU The U coordinate of the texture. + * @param texV The V coordinate of the texture. + * @return The sprite in the location in the block atlas. + */ + TextureAtlasSprite findInBlockAtlas(float texU, float texV); +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/services/Services.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/services/Services.java new file mode 100644 index 0000000000..eaf6fb20e8 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/services/Services.java @@ -0,0 +1,18 @@ +package net.caffeinemc.mods.sodium.client.services; + +import net.caffeinemc.mods.sodium.client.SodiumClientMod; + +import java.util.ServiceLoader; + +public class Services { + // This code is used to load a service for the current environment. Your implementation of the service must be defined + // manually by including a text file in META-INF/services named with the fully qualified class name of the service. + // Inside the file you should write the fully qualified class name of the implementation to load for the platform. + public static T load(Class clazz) { + final T loadedService = ServiceLoader.load(clazz) + .findFirst() + .orElseThrow(() -> new NullPointerException("Failed to load service for " + clazz.getName())); + SodiumClientMod.logger().debug("Loaded {} for service {}", loadedService, clazz); + return loadedService; + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/services/SodiumModelData.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/services/SodiumModelData.java new file mode 100644 index 0000000000..2879d45872 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/services/SodiumModelData.java @@ -0,0 +1,8 @@ +package net.caffeinemc.mods.sodium.client.services; + +/** + * Template class for the platform's model data. + */ +public interface SodiumModelData { + SodiumModelData EMPTY = PlatformModelAccess.getInstance().getEmptyModelData(); +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/services/SodiumModelDataContainer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/services/SodiumModelDataContainer.java new file mode 100644 index 0000000000..acd20d8f67 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/services/SodiumModelDataContainer.java @@ -0,0 +1,27 @@ +package net.caffeinemc.mods.sodium.client.services; + +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import net.minecraft.core.BlockPos; + +import java.util.Map; + +/** + * A container that holds the platform's model data. + */ +public class SodiumModelDataContainer { + private final Long2ObjectMap modelDataMap; + private final boolean isEmpty; + + public SodiumModelDataContainer(Long2ObjectMap modelDataMap) { + this.modelDataMap = modelDataMap; + this.isEmpty = modelDataMap.isEmpty(); + } + + public SodiumModelData getModelData(BlockPos pos) { + return modelDataMap.getOrDefault(pos.asLong(), SodiumModelData.EMPTY); + } + + public boolean isEmpty() { + return isEmpty; + } +} diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/BitwiseMath.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/BitwiseMath.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/BitwiseMath.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/BitwiseMath.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/Dim2i.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/Dim2i.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/Dim2i.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/Dim2i.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/DirectionUtil.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/DirectionUtil.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/DirectionUtil.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/DirectionUtil.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/FileUtil.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/FileUtil.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/FileUtil.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/FileUtil.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/ListUtil.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/ListUtil.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/ListUtil.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/ListUtil.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/MathUtil.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/MathUtil.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/MathUtil.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/MathUtil.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/ModelQuadUtil.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/ModelQuadUtil.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/ModelQuadUtil.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/ModelQuadUtil.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/NativeBuffer.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/NativeBuffer.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/NativeBuffer.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/NativeBuffer.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/NativeImageHelper.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/NativeImageHelper.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/NativeImageHelper.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/NativeImageHelper.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/TextureUtil.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/TextureUtil.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/TextureUtil.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/TextureUtil.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/collections/BitArray.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/collections/BitArray.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/collections/BitArray.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/collections/BitArray.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/collections/DoubleBufferedQueue.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/collections/DoubleBufferedQueue.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/collections/DoubleBufferedQueue.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/collections/DoubleBufferedQueue.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/collections/ReadQueue.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/collections/ReadQueue.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/collections/ReadQueue.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/collections/ReadQueue.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/collections/WriteQueue.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/collections/WriteQueue.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/collections/WriteQueue.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/collections/WriteQueue.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/color/BoxBlur.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/color/BoxBlur.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/color/BoxBlur.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/color/BoxBlur.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/color/ColorSRGB.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/color/ColorSRGB.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/color/ColorSRGB.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/color/ColorSRGB.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/color/FastCubicSampler.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/color/FastCubicSampler.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/color/FastCubicSampler.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/color/FastCubicSampler.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/iterator/ByteArrayIterator.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/iterator/ByteArrayIterator.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/iterator/ByteArrayIterator.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/iterator/ByteArrayIterator.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/iterator/ByteIterator.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/iterator/ByteIterator.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/iterator/ByteIterator.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/iterator/ByteIterator.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/iterator/ReversibleByteArrayIterator.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/iterator/ReversibleByteArrayIterator.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/iterator/ReversibleByteArrayIterator.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/iterator/ReversibleByteArrayIterator.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/iterator/ReversibleObjectArrayIterator.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/iterator/ReversibleObjectArrayIterator.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/iterator/ReversibleObjectArrayIterator.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/iterator/ReversibleObjectArrayIterator.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/AbstractSort.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/AbstractSort.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/AbstractSort.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/AbstractSort.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/InsertionSort.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/InsertionSort.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/InsertionSort.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/InsertionSort.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/MergeSort.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/MergeSort.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/MergeSort.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/MergeSort.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/RadixSort.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/RadixSort.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/RadixSort.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/RadixSort.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/VertexSorters.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/VertexSorters.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/VertexSorters.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/sorting/VertexSorters.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/task/CancellationToken.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/util/task/CancellationToken.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/task/CancellationToken.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/util/task/CancellationToken.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/world/BiomeSeedProvider.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/world/BiomeSeedProvider.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/world/BiomeSeedProvider.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/world/BiomeSeedProvider.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/world/BitStorageExtension.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/world/BitStorageExtension.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/world/BitStorageExtension.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/world/BitStorageExtension.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/world/LevelRendererExtension.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/world/LevelRendererExtension.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/world/LevelRendererExtension.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/world/LevelRendererExtension.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/world/LevelSlice.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/world/LevelSlice.java similarity index 86% rename from src/main/java/net/caffeinemc/mods/sodium/client/world/LevelSlice.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/world/LevelSlice.java index 5dc82d4c8c..500c728de2 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/world/LevelSlice.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/world/LevelSlice.java @@ -1,9 +1,11 @@ package net.caffeinemc.mods.sodium.client.world; import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; +import net.caffeinemc.mods.sodium.client.services.PlatformLevelAccess; +import net.caffeinemc.mods.sodium.client.services.PlatformModelAccess; +import net.caffeinemc.mods.sodium.client.services.SodiumModelData; +import net.caffeinemc.mods.sodium.client.services.SodiumModelDataContainer; import net.caffeinemc.mods.sodium.client.world.biome.LevelColorCache; -import net.caffeinemc.mods.sodium.client.world.biome.BiomeColorSource; -import net.caffeinemc.mods.sodium.client.world.biome.BiomeColorView; import net.caffeinemc.mods.sodium.client.world.biome.LevelBiomeSlice; import net.caffeinemc.mods.sodium.client.world.cloned.ChunkRenderContext; import net.caffeinemc.mods.sodium.client.world.cloned.ClonedChunkSection; @@ -34,6 +36,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Arrays; +import java.util.List; import java.util.Objects; /** @@ -46,7 +49,7 @@ * *

Object pooling should be used to avoid huge allocations as this class contains many large arrays.

*/ -public final class LevelSlice implements BlockAndTintGetter, BiomeColorView, RenderAttachedBlockView { +public final class LevelSlice implements BlockAndTintGetter, RenderAttachedBlockView { private static final LightLayer[] LIGHT_TYPES = LightLayer.values(); // The number of blocks in a section. @@ -82,6 +85,10 @@ public final class LevelSlice implements BlockAndTintGetter, BiomeColorView, Ren // (Local Section -> Block States) table. private final BlockState[][] blockArrays; + // (Local Section -> Light Manager) table. + @SuppressWarnings("MismatchedReadAndWriteOfArray") + private final Object[] auxLightManager; + // (Local Section -> Light Arrays) table. private final @Nullable DataLayer[][] lightArrays; @@ -91,6 +98,9 @@ public final class LevelSlice implements BlockAndTintGetter, BiomeColorView, Ren // (Local Section -> Block Entity Render Data) table. private final @Nullable Int2ReferenceMap[] blockEntityRenderDataArrays; + // (Local Section -> Model Data) table. + private final SodiumModelDataContainer[] modelMapArrays; + // The starting point from which this slice captures blocks private int originBlockX, originBlockY, originBlockZ; @@ -135,7 +145,9 @@ public static ChunkRenderContext prepare(Level level, SectionPos pos, ClonedChun } } - return new ChunkRenderContext(pos, sections, box); + List renderers = PlatformLevelAccess.getInstance().getExtraRenderers(level, pos.origin()); + + return new ChunkRenderContext(pos, sections, box, renderers); } @SuppressWarnings("unchecked") @@ -147,6 +159,8 @@ public LevelSlice(ClientLevel level) { this.blockEntityArrays = new Int2ReferenceMap[SECTION_ARRAY_SIZE]; this.blockEntityRenderDataArrays = new Int2ReferenceMap[SECTION_ARRAY_SIZE]; + this.auxLightManager = new Object[SECTION_ARRAY_SIZE]; + this.modelMapArrays = new SodiumModelDataContainer[SECTION_ARRAY_SIZE]; this.biomeSlice = new LevelBiomeSlice(); this.biomeColors = new LevelColorCache(this.biomeSlice, Minecraft.getInstance().options.biomeBlendRadius().get()); @@ -186,7 +200,9 @@ private void copySectionData(ChunkRenderContext context, int sectionIndex) { this.lightArrays[sectionIndex][LightLayer.SKY.ordinal()] = section.getLightArray(LightLayer.SKY); this.blockEntityArrays[sectionIndex] = section.getBlockEntityMap(); + this.auxLightManager[sectionIndex] = section.getAuxLightManager(); this.blockEntityRenderDataArrays[sectionIndex] = section.getBlockEntityRenderDataMap(); + this.modelMapArrays[sectionIndex] = section.getModelMap(); } private void unpackBlockData(BlockState[] blockArray, ChunkRenderContext context, ClonedChunkSection section) { @@ -226,6 +242,7 @@ public void reset() { Arrays.fill(this.lightArrays[sectionIndex], null); this.blockEntityArrays[sectionIndex] = null; + this.auxLightManager[sectionIndex] = null; this.blockEntityRenderDataArrays[sectionIndex] = null; } } @@ -348,12 +365,7 @@ public int getMinBuildHeight() { return this.level.getMinBuildHeight(); } - @Override - public int getColor(BiomeColorSource source, int blockX, int blockY, int blockZ) { - return this.biomeColors.getColor(source, blockX, blockY, blockZ); - } - - @Override + //@Override public @Nullable Object getBlockEntityRenderData(BlockPos pos) { if (!this.volume.isInside(pos.getX(), pos.getY(), pos.getZ())) { return null; @@ -372,12 +384,30 @@ public int getColor(BiomeColorSource source, int blockX, int blockY, int blockZ) return blockEntityRenderDataMap.get(getLocalBlockIndex(relBlockX & 15, relBlockY & 15, relBlockZ & 15)); } - @Override + public SodiumModelData getPlatformModelData(BlockPos pos) { + if (!this.volume.isInside(pos.getX(), pos.getY(), pos.getZ())) { + return SodiumModelData.EMPTY; + } + + int relBlockX = pos.getX() - this.originBlockX; + int relBlockY = pos.getY() - this.originBlockY; + int relBlockZ = pos.getZ() - this.originBlockZ; + + var modelMap = this.modelMapArrays[getLocalSectionIndex(relBlockX >> 4, relBlockY >> 4, relBlockZ >> 4)]; + + if (modelMap.isEmpty()) { + return SodiumModelData.EMPTY; + } + + return modelMap.getModelData(pos); + } + + //@Override public boolean hasBiomes() { return true; } - @Override + //@Override public Holder getBiomeFabric(BlockPos pos) { return this.biomeSlice.getBiome(pos.getX(), pos.getY(), pos.getZ()); } @@ -389,4 +419,23 @@ public static int getLocalBlockIndex(int blockX, int blockY, int blockZ) { public static int getLocalSectionIndex(int sectionX, int sectionY, int sectionZ) { return (sectionY * SECTION_ARRAY_LENGTH * SECTION_ARRAY_LENGTH) + (sectionZ * SECTION_ARRAY_LENGTH) + sectionX; } + + @Override + public @Nullable Object getBlockEntityRenderAttachment(BlockPos pos) { + if (!this.volume.isInside(pos.getX(), pos.getY(), pos.getZ())) { + return null; + } + + int relBlockX = pos.getX() - this.originBlockX; + int relBlockY = pos.getY() - this.originBlockY; + int relBlockZ = pos.getZ() - this.originBlockZ; + + var blockEntityRenderDataMap = this.blockEntityRenderDataArrays[getLocalSectionIndex(relBlockX >> 4, relBlockY >> 4, relBlockZ >> 4)]; + + if (blockEntityRenderDataMap == null) { + return null; + } + + return blockEntityRenderDataMap.get(getLocalBlockIndex(relBlockX & 15, relBlockY & 15, relBlockZ & 15)); + } } diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/world/PalettedContainerROExtension.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/world/PalettedContainerROExtension.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/world/PalettedContainerROExtension.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/world/PalettedContainerROExtension.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/world/biome/BiomeColorMaps.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/world/biome/BiomeColorMaps.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/world/biome/BiomeColorMaps.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/world/biome/BiomeColorMaps.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/world/biome/LevelBiomeSlice.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/world/biome/LevelBiomeSlice.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/world/biome/LevelBiomeSlice.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/world/biome/LevelBiomeSlice.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/world/biome/LevelColorCache.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/world/biome/LevelColorCache.java similarity index 91% rename from src/main/java/net/caffeinemc/mods/sodium/client/world/biome/LevelColorCache.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/world/biome/LevelColorCache.java index 509f09220e..80561d0fc3 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/world/biome/LevelColorCache.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/world/biome/LevelColorCache.java @@ -50,14 +50,6 @@ public void update(ChunkRenderContext context) { this.populateStamp++; } - public int getColor(BiomeColorSource source, int blockX, int blockY, int blockZ) { - return switch (source) { - case GRASS -> getColor(BiomeColors.GRASS_COLOR_RESOLVER, blockX, blockY, blockZ); - case FOLIAGE -> getColor(BiomeColors.FOLIAGE_COLOR_RESOLVER, blockX, blockY, blockZ); - case WATER -> getColor(BiomeColors.WATER_COLOR_RESOLVER, blockX, blockY, blockZ); - }; - } - public int getColor(ColorResolver resolver, int blockX, int blockY, int blockZ) { var relBlockX = Mth.clamp(blockX, this.minBlockX, this.maxBlockX) - this.minBlockX; var relBlockY = Mth.clamp(blockY, this.minBlockY, this.maxBlockY) - this.minBlockY; diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/world/cloned/ChunkRenderContext.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/world/cloned/ChunkRenderContext.java similarity index 70% rename from src/main/java/net/caffeinemc/mods/sodium/client/world/cloned/ChunkRenderContext.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/world/cloned/ChunkRenderContext.java index 986be58cfa..0242748dcc 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/world/cloned/ChunkRenderContext.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/world/cloned/ChunkRenderContext.java @@ -1,17 +1,22 @@ package net.caffeinemc.mods.sodium.client.world.cloned; +import net.caffeinemc.mods.sodium.client.services.SodiumModelDataContainer; import net.minecraft.core.SectionPos; import net.minecraft.world.level.levelgen.structure.BoundingBox; +import java.util.List; + public class ChunkRenderContext { private final SectionPos origin; private final ClonedChunkSection[] sections; private final BoundingBox volume; + private final List renderers; - public ChunkRenderContext(SectionPos origin, ClonedChunkSection[] sections, BoundingBox volume) { + public ChunkRenderContext(SectionPos origin, ClonedChunkSection[] sections, BoundingBox volume, List renderers) { this.origin = origin; this.sections = sections; this.volume = volume; + this.renderers = renderers; } public ClonedChunkSection[] getSections() { @@ -25,4 +30,8 @@ public SectionPos getOrigin() { public BoundingBox getVolume() { return this.volume; } + + public List getRenderers() { + return renderers; + } } diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/world/cloned/ClonedChunkSection.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/world/cloned/ClonedChunkSection.java similarity index 91% rename from src/main/java/net/caffeinemc/mods/sodium/client/world/cloned/ClonedChunkSection.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/world/cloned/ClonedChunkSection.java index 61f7af38ff..aef6ace4ed 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/world/cloned/ClonedChunkSection.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/world/cloned/ClonedChunkSection.java @@ -3,6 +3,7 @@ import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; import it.unimi.dsi.fastutil.ints.Int2ReferenceMaps; import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; +import net.caffeinemc.mods.sodium.client.services.*; import net.caffeinemc.mods.sodium.client.world.PalettedContainerROExtension; import net.caffeinemc.mods.sodium.client.world.LevelSlice; import net.minecraft.core.BlockPos; @@ -38,10 +39,12 @@ public class ClonedChunkSection { private final @Nullable Int2ReferenceMap blockEntityRenderDataMap; private final @Nullable DataLayer[] lightDataArrays; + private final @Nullable Object auxLightManager; private final @Nullable PalettedContainerRO blockData; private final @Nullable PalettedContainerRO> biomeData; + private final SodiumModelDataContainer modelMap; private long lastUsedTimestamp = Long.MAX_VALUE; @@ -53,6 +56,8 @@ public ClonedChunkSection(Level level, LevelChunk chunk, @Nullable LevelChunkSec Int2ReferenceMap blockEntityMap = null; Int2ReferenceMap blockEntityRenderDataMap = null; + SodiumModelDataContainer modelMap = PlatformModelAccess.getInstance().getModelDataContainer(level, pos); + auxLightManager = PlatformLevelAccess.INSTANCE.getLightManager(chunk, pos); if (section != null) { if (!section.hasOnlyAir()) { @@ -62,9 +67,8 @@ public ClonedChunkSection(Level level, LevelChunk chunk, @Nullable LevelChunkSec blockData = constructDebugWorldContainer(pos); } blockEntityMap = copyBlockEntities(chunk, pos); - - if (blockEntityMap != null) { - blockEntityRenderDataMap = copyBlockEntityRenderData(blockEntityMap); + if (blockEntityMap != null && PlatformBlockAccess.getInstance().platformHasBlockData()) { + blockEntityRenderDataMap = copyBlockEntityRenderData(level, blockEntityMap); } } @@ -73,6 +77,7 @@ public ClonedChunkSection(Level level, LevelChunk chunk, @Nullable LevelChunkSec this.blockData = blockData; this.biomeData = biomeData; + this.modelMap = modelMap; this.blockEntityMap = blockEntityMap; this.blockEntityRenderDataMap = blockEntityRenderDataMap; @@ -173,7 +178,7 @@ private static Int2ReferenceMap copyBlockEntities(LevelChunk chunk, } @Nullable - private static Int2ReferenceMap copyBlockEntityRenderData(Int2ReferenceMap blockEntities) { + private static Int2ReferenceMap copyBlockEntityRenderData(Level level, Int2ReferenceMap blockEntities) { Int2ReferenceOpenHashMap blockEntityRenderDataMap = null; // Retrieve any render data after we have copied all block entities, as this will call into the code of @@ -181,7 +186,7 @@ private static Int2ReferenceMap copyBlockEntityRenderData(Int2ReferenceM // were iterating over any data in that chunk. // See https://github.com/CaffeineMC/sodium-fabric/issues/942 for more info. for (var entry : Int2ReferenceMaps.fastIterable(blockEntities)) { - Object data = entry.getValue().getRenderData(); + Object data = PlatformBlockAccess.getInstance().getBlockEntityData(entry.getValue()); if (data != null) { if (blockEntityRenderDataMap == null) { @@ -219,6 +224,10 @@ public SectionPos getPosition() { return this.blockEntityRenderDataMap; } + public SodiumModelDataContainer getModelMap() { + return modelMap; + } + public @Nullable DataLayer getLightArray(LightLayer lightType) { return this.lightDataArrays[lightType.ordinal()]; } @@ -230,4 +239,8 @@ public long getLastUsedTimestamp() { public void setLastUsedTimestamp(long timestamp) { this.lastUsedTimestamp = timestamp; } + + public Object getAuxLightManager() { + return auxLightManager; + } } diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/world/cloned/ClonedChunkSectionCache.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/world/cloned/ClonedChunkSectionCache.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/world/cloned/ClonedChunkSectionCache.java rename to common/src/main/java/net/caffeinemc/mods/sodium/client/world/cloned/ClonedChunkSectionCache.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/MixinOption.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/MixinOption.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/MixinOption.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/MixinOption.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/SodiumMixinPlugin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/SodiumMixinPlugin.java similarity index 85% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/SodiumMixinPlugin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/SodiumMixinPlugin.java index 8405d2ba23..e0276d8f4c 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/SodiumMixinPlugin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/SodiumMixinPlugin.java @@ -1,6 +1,7 @@ package net.caffeinemc.mods.sodium.mixin; import net.caffeinemc.mods.sodium.client.data.config.MixinConfig; +import net.caffeinemc.mods.sodium.client.services.PlatformInfoAccess; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.objectweb.asm.tree.ClassNode; @@ -17,6 +18,7 @@ public class SodiumMixinPlugin implements IMixinConfigPlugin { private final Logger logger = LogManager.getLogger("Sodium"); private MixinConfig config; + private boolean dependencyResolutionFailed; @Override public void onLoad(String mixinPackage) { @@ -26,17 +28,27 @@ public void onLoad(String mixinPackage) { throw new RuntimeException("Could not load configuration file for Sodium", e); } + this.dependencyResolutionFailed = PlatformInfoAccess.getInstance().isModInLoadingList("embeddium"); + + if (dependencyResolutionFailed) { + this.logger.error("Not applying any Sodium mixins; dependency resolution has failed."); + } + this.logger.info("Loaded configuration file for Sodium: {} options available, {} override(s) found", this.config.getOptionCount(), this.config.getOptionOverrideCount()); } @Override public String getRefMapperConfig() { - return null; + return PlatformInfoAccess.getInstance().platformUsesRefmap() ? "sodium.refmap.json" : null; } @Override public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if (dependencyResolutionFailed) { + return false; + } + if (!mixinClassName.startsWith(MIXIN_PACKAGE_ROOT)) { this.logger.error("Expected mixin '{}' to start with package root '{}', treating as foreign and " + "disabling!", mixinClassName, MIXIN_PACKAGE_ROOT); @@ -73,6 +85,7 @@ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { return option.isEnabled(); } + @Override public void acceptTargets(Set myTargets, Set otherTargets) { diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/MinecraftMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/MinecraftMixin.java similarity index 98% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/MinecraftMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/MinecraftMixin.java index 19c600e458..df0e469db2 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/MinecraftMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/MinecraftMixin.java @@ -2,7 +2,7 @@ import it.unimi.dsi.fastutil.longs.LongArrayFIFOQueue; import net.caffeinemc.mods.sodium.client.SodiumClientMod; -import net.caffeinemc.mods.sodium.client.compatibility.checks.ResourcePackScanner; +import net.caffeinemc.mods.sodium.client.checks.ResourcePackScanner; import net.minecraft.client.Minecraft; import net.minecraft.server.packs.resources.ReloadableResourceManager; import net.minecraft.util.profiling.ProfilerFiller; diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/WindowMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/WindowMixin.java similarity index 62% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/WindowMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/WindowMixin.java index 8cc6e9619b..a04acec7d1 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/WindowMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/WindowMixin.java @@ -6,16 +6,16 @@ import org.lwjgl.glfw.GLFW; 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; +import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(Window.class) public class WindowMixin { - @Inject(method = "", at = @At(value = "INVOKE", target = "Lorg/lwjgl/glfw/GLFW;glfwCreateWindow(IILjava/lang/CharSequence;JJ)J", shift = At.Shift.BEFORE)) - public void setAdditionalWindowHints(CallbackInfo ci) { + //@Redirect(method = "", at = @At(value = "INVOKE", target = "Lorg/lwjgl/glfw/GLFW;glfwCreateWindow(IILjava/lang/CharSequence;JJ)J"), require = 0) + public long setAdditionalWindowHints(int width, int height, CharSequence title, long monitor, long share) { if (SodiumClientMod.options().performance.useNoErrorGLContext && !Workarounds.isWorkaroundEnabled(Workarounds.Reference.NO_ERROR_CONTEXT_UNSUPPORTED)) { GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_NO_ERROR, GLFW.GLFW_TRUE); } + return GLFW.glfwCreateWindow(width, height, title, monitor, share); } } diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/gui/LevelLoadStatusManagerMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/gui/LevelLoadStatusManagerMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/gui/LevelLoadStatusManagerMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/gui/LevelLoadStatusManagerMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/model/FaceBakeryMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/model/FaceBakeryMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/model/FaceBakeryMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/model/FaceBakeryMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/model/colors/BlockColorsMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/model/colors/BlockColorsMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/model/colors/BlockColorsMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/model/colors/BlockColorsMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/model/colors/ItemColorsMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/model/colors/ItemColorsMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/model/colors/ItemColorsMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/model/colors/ItemColorsMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/chunk/LiquidBlockRendererMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/chunk/LiquidBlockRendererMixin.java similarity index 82% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/chunk/LiquidBlockRendererMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/chunk/LiquidBlockRendererMixin.java index 94c7146841..d1144b74fe 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/chunk/LiquidBlockRendererMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/chunk/LiquidBlockRendererMixin.java @@ -1,6 +1,6 @@ package net.caffeinemc.mods.sodium.mixin.core.render.chunk; -import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.FluidRenderer; +import net.caffeinemc.mods.sodium.client.services.PlatformLevelAccess; import net.minecraft.client.renderer.block.LiquidBlockRenderer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -12,7 +12,7 @@ public class LiquidBlockRendererMixin { @Inject(method = "tesselate", at = @At("HEAD"), cancellable = true) private void onHeadRender(CallbackInfo ci) { - if (FluidRenderer.renderFromVanilla()) { + if (PlatformLevelAccess.getInstance().tryRenderFluid()) { ci.cancel(); } } diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/frustum/FrustumMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/frustum/FrustumMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/frustum/FrustumMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/frustum/FrustumMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/BufferBuilderMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/BufferBuilderMixin.java similarity index 89% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/BufferBuilderMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/BufferBuilderMixin.java index 59bd5a3d35..f10a7b2bb6 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/BufferBuilderMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/BufferBuilderMixin.java @@ -24,28 +24,26 @@ @Mixin(BufferBuilder.class) public abstract class BufferBuilderMixin implements VertexBufferWriter, BufferBuilderExtension { @Shadow - @Final - private int vertexSize; + private int vertices; @Shadow @Final - private ByteBufferBuilder buffer; + private int vertexSize; @Shadow - private int vertices; + private long vertexPointer; @Shadow - private long vertexPointer; + @Final + private ByteBufferBuilder buffer; @Shadow private int elementsToFill; + @Unique private VertexFormatDescription formatDescription; - @Inject( - method = "", - at = @At(value = "TAIL") - ) + @Inject(method = "", at = @At("TAIL")) private void onFormatChanged(ByteBufferBuilder byteBufferBuilder, VertexFormat.Mode mode, VertexFormat format, CallbackInfo ci) { this.formatDescription = VertexFormatRegistry.instance() .get(format); @@ -53,11 +51,11 @@ private void onFormatChanged(ByteBufferBuilder byteBufferBuilder, VertexFormat.M @Override public void sodium$duplicateVertex() { - if (this.vertices != 0) { - long dst = this.buffer.reserve(this.vertexSize); - MemoryIntrinsics.copyMemory(dst - this.vertexSize, dst, this.vertexSize); - ++this.vertices; - } + if (vertices == 0) return; + + long dst = this.buffer.reserve(this.vertexSize); + MemoryIntrinsics.copyMemory(dst - this.vertexSize, dst, this.vertexSize); + ++this.vertices; } @Override @@ -69,6 +67,8 @@ public boolean canUseIntrinsics() { public void push(MemoryStack stack, long src, int count, VertexFormatDescription format) { var length = count * this.vertexSize; + // The buffer may change in the even, so we need to make sure that the + // pointer is retrieved *after* the resize var dst = this.buffer.reserve(length); if (format == this.formatDescription) { diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/EntityOutlineGeneratorMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/EntityOutlineGeneratorMixin.java similarity index 92% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/EntityOutlineGeneratorMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/EntityOutlineGeneratorMixin.java index 45ebd9e80c..c1980c1ee5 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/EntityOutlineGeneratorMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/EntityOutlineGeneratorMixin.java @@ -25,11 +25,10 @@ public abstract class EntityOutlineGeneratorMixin implements VertexBufferWriter @Shadow @Final private int color; - @Unique private boolean canUseIntrinsics; - @Inject(method = "", at = @At("RETURN")) + @Inject(method = "(Lcom/mojang/blaze3d/vertex/VertexConsumer;I)V", at = @At("RETURN")) private void onInit(CallbackInfo ci) { this.canUseIntrinsics = VertexBufferWriter.tryOf(this.delegate) != null; } @@ -42,7 +41,7 @@ public boolean canUseIntrinsics() { @Override public void push(MemoryStack stack, long ptr, int count, VertexFormatDescription format) { transform(ptr, count, format, - ColorARGB.toABGR(this.color)); + this.color); VertexBufferWriter.of(this.delegate) .push(stack, ptr, count, format); @@ -63,7 +62,7 @@ private static void transform(long ptr, int count, VertexFormatDescription forma long offsetColor = format.getElementOffset(CommonVertexAttribute.COLOR); for (int vertexIndex = 0; vertexIndex < count; vertexIndex++) { - ColorAttribute.set(ptr + offsetColor, color); + ColorAttribute.set(ptr + offsetColor, ColorARGB.toABGR(color)); ptr += stride; } } diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/SheetedDecalTextureGeneratorMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/SheetedDecalTextureGeneratorMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/SheetedDecalTextureGeneratorMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/SheetedDecalTextureGeneratorMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/SpriteCoordinateExpanderMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/SpriteCoordinateExpanderMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/SpriteCoordinateExpanderMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/SpriteCoordinateExpanderMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/VertexMultiConsumerMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/VertexMultiConsumerMixin.java similarity index 98% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/VertexMultiConsumerMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/VertexMultiConsumerMixin.java index 699391d8b2..edfd27095a 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/VertexMultiConsumerMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/immediate/consumer/VertexMultiConsumerMixin.java @@ -24,6 +24,7 @@ public static class DoubleMixin implements VertexBufferWriter { @Final private VertexConsumer second; + @Unique private boolean canUseIntrinsics; @Inject(method = "", at = @At("RETURN")) @@ -49,6 +50,7 @@ public static class MultipleMixin implements VertexBufferWriter { @Final private VertexConsumer[] delegates; + @Unique private boolean canUseIntrinsics; @Inject(method = "", at = @At("RETURN")) diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/world/LevelRendererMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/world/LevelRendererMixin.java similarity index 86% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/world/LevelRendererMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/world/LevelRendererMixin.java index 422468b622..ef694fe48a 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/world/LevelRendererMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/world/LevelRendererMixin.java @@ -6,7 +6,8 @@ import net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer; import net.caffeinemc.mods.sodium.client.render.chunk.ChunkRenderMatrices; import net.caffeinemc.mods.sodium.client.render.viewport.ViewportProvider; -import net.caffeinemc.mods.sodium.client.util.FlawlessFrames; +import net.caffeinemc.mods.sodium.client.services.PlatformInfoAccess; +import net.caffeinemc.mods.sodium.client.services.PlatformLevelAccess; import net.caffeinemc.mods.sodium.client.world.LevelRendererExtension; import net.minecraft.client.Camera; import net.minecraft.client.DeltaTracker; @@ -23,6 +24,7 @@ import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.core.BlockPos; import net.minecraft.server.level.BlockDestructionProgress; +import net.minecraft.world.level.block.entity.BlockEntity; import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.*; @@ -32,6 +34,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.SortedSet; +import java.util.function.Consumer; @Mixin(LevelRenderer.class) public abstract class LevelRendererMixin implements LevelRendererExtension { @@ -46,6 +49,17 @@ public abstract class LevelRendererMixin implements LevelRendererExtension { @Shadow @Nullable private ClientLevel level; + + @Shadow + private int ticks; + + @Shadow + @Final + private Minecraft minecraft; + + @Shadow + private Frustum cullingFrustum; + @Unique private SodiumWorldRenderer renderer; @@ -112,6 +126,8 @@ private void renderSectionLayer(RenderType renderLayer, double x, double y, doub } finally { RenderDevice.exitManagedCode(); } + + PlatformLevelAccess.getInstance().runChunkLayerEvents(renderLayer, ((LevelRenderer) (Object) this), modelMatrix, projectionMatrix, this.ticks, this.minecraft.gameRenderer.getMainCamera(), this.cullingFrustum); } /** @@ -122,7 +138,7 @@ private void renderSectionLayer(RenderType renderLayer, double x, double y, doub private void setupRender(Camera camera, Frustum frustum, boolean hasForcedFrustum, boolean spectator) { var viewport = ((ViewportProvider) frustum).sodium$createViewport(); - var updateChunksImmediately = FlawlessFrames.isActive(); + var updateChunksImmediately = PlatformInfoAccess.getInstance().isFlawlessFramesActive(); RenderDevice.enterManagedCode(); @@ -194,10 +210,19 @@ private void onRenderBlockEntities(DeltaTracker deltaTracker, boolean bl, Camera this.renderer.renderBlockEntities(new PoseStack(), this.renderBuffers, this.destructionProgress, camera, deltaTracker.getGameTimeDeltaPartialTick(false)); } + // Exclusive to NeoForge, allow to fail. + @SuppressWarnings("all") + @Inject(method = "iterateVisibleBlockEntities", at = @At("HEAD"), cancellable = true, require = 0) + public void replaceBlockEntityIteration(Consumer blockEntityConsumer, CallbackInfo ci) { + ci.cancel(); + + this.renderer.iterateVisibleBlockEntities(blockEntityConsumer); + } + /** - * @reason Replace the debug string - * @author JellySquid - */ + * @reason Replace the debug string + * @author JellySquid + */ @Overwrite public String getSectionStatistics() { return this.renderer.getChunksDebugString(); diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/world/RenderBuffersMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/world/RenderBuffersMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/world/RenderBuffersMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/render/world/RenderBuffersMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/biome/ClientLevelMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/biome/ClientLevelMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/biome/ClientLevelMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/biome/ClientLevelMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/chunk/PalettedContainerMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/chunk/PalettedContainerMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/chunk/PalettedContainerMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/chunk/PalettedContainerMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/chunk/SimpleBitStorageMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/chunk/SimpleBitStorageMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/chunk/SimpleBitStorageMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/chunk/SimpleBitStorageMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/chunk/ZeroBitStorageMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/chunk/ZeroBitStorageMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/chunk/ZeroBitStorageMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/chunk/ZeroBitStorageMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/map/ClientChunkCacheMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/map/ClientChunkCacheMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/map/ClientChunkCacheMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/map/ClientChunkCacheMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/map/ClientLevelMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/map/ClientLevelMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/map/ClientLevelMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/map/ClientLevelMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/map/ClientPacketListenerMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/map/ClientPacketListenerMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/map/ClientPacketListenerMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/world/map/ClientPacketListenerMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/AbstractTextureMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/AbstractTextureMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/AbstractTextureMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/AbstractTextureMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/BufferUploaderMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/BufferUploaderMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/BufferUploaderMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/BufferUploaderMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/DynamicTextureMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/DynamicTextureMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/DynamicTextureMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/DynamicTextureMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/GlStateManagerMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/GlStateManagerMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/GlStateManagerMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/GlStateManagerMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/HttpTextureMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/HttpTextureMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/HttpTextureMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/HttpTextureMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/NativeImageMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/NativeImageMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/NativeImageMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/NativeImageMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/PreloadedTextureMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/PreloadedTextureMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/PreloadedTextureMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/PreloadedTextureMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/RenderSystemMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/RenderSystemMixin.java similarity index 97% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/RenderSystemMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/RenderSystemMixin.java index 1954a4a29a..9b2c9b9c2f 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/RenderSystemMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/RenderSystemMixin.java @@ -36,7 +36,6 @@ private static void onReplayQueue(CallbackInfo ci) { "setShaderTexture(ILnet/minecraft/resources/ResourceLocation;)V", "setShaderTexture(II)V", "setProjectionMatrix", - "setInverseViewRotationMatrix", "setTextureMatrix", "resetTextureMatrix", "applyModelViewMatrix", diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/RenderTargetMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/RenderTargetMixin.java similarity index 72% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/RenderTargetMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/RenderTargetMixin.java index ee6583d37f..fe10114bcf 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/RenderTargetMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/RenderTargetMixin.java @@ -16,11 +16,4 @@ public class RenderTargetMixin { private boolean validateCurrentThread$imageOperations() { return RenderAsserts.validateCurrentThread(); } - - @Redirect(method = { - "blitToScreen(IIZ)V", - }, at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;isInInitPhase()Z")) - private boolean validateCurrentThread$draw() { - return RenderAsserts.validateCurrentThread(); - } } diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/SpriteContentsAnimatorImplMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/SpriteContentsAnimatorImplMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/SpriteContentsAnimatorImplMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/SpriteContentsAnimatorImplMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/TextureAtlasMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/TextureAtlasMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/TextureAtlasMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/TextureAtlasMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/TextureManagerMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/TextureManagerMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/TextureManagerMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/TextureManagerMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/VertexBufferMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/VertexBufferMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/VertexBufferMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/VertexBufferMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/VertexFormatMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/VertexFormatMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/VertexFormatMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/VertexFormatMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/hooks/console/GameRendererMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/hooks/console/GameRendererMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/hooks/console/GameRendererMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/hooks/console/GameRendererMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/hooks/debug/DebugScreenOverlayMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/hooks/debug/DebugScreenOverlayMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/hooks/debug/DebugScreenOverlayMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/hooks/debug/DebugScreenOverlayMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/hooks/settings/OptionsScreenMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/hooks/settings/OptionsScreenMixin.java similarity index 86% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/hooks/settings/OptionsScreenMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/hooks/settings/OptionsScreenMixin.java index 3ec83dc161..0e1c1d27ec 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/hooks/settings/OptionsScreenMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/hooks/settings/OptionsScreenMixin.java @@ -17,7 +17,10 @@ protected OptionsScreenMixin(Component title) { } @Dynamic - @Inject(method = "method_19828", at = @At("HEAD"), cancellable = true) + @Inject(method = { + "method_19828", + "lambda$init$2" + }, require = 1, at = @At("HEAD"), cancellable = true) private void open(CallbackInfoReturnable ci) { ci.setReturnValue(SodiumOptionsGUI.createScreen(this)); } diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/screen/LevelLoadingScreenMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/screen/LevelLoadingScreenMixin.java similarity index 97% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/screen/LevelLoadingScreenMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/screen/LevelLoadingScreenMixin.java index d2268a44d8..6f649536a0 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/screen/LevelLoadingScreenMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/gui/screen/LevelLoadingScreenMixin.java @@ -112,13 +112,12 @@ public static void renderChunks(GuiGraphics graphics, StoringChunkProgressListen } } - MeshData meshData = bufferBuilder.build(); + MeshData data = bufferBuilder.build(); - if (meshData != null) { - BufferUploader.drawWithShader(meshData); + if (data != null) { + BufferUploader.drawWithShader(data); } - - tessellator.clear(); + Tesselator.getInstance().clear(); RenderSystem.disableBlend(); } diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/options/overlays/GuiMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/options/overlays/GuiMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/options/overlays/GuiMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/options/overlays/GuiMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/options/render_layers/ItemBlockRenderTypesMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/options/render_layers/ItemBlockRenderTypesMixin.java similarity index 84% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/options/render_layers/ItemBlockRenderTypesMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/options/render_layers/ItemBlockRenderTypesMixin.java index 8c42d41123..1bca2f0f73 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/options/render_layers/ItemBlockRenderTypesMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/options/render_layers/ItemBlockRenderTypesMixin.java @@ -15,9 +15,11 @@ public class ItemBlockRenderTypesMixin { @Unique private static boolean leavesFancy; + // getRenderLayers is a NeoForge only function required for the leaves to properly work. + @SuppressWarnings("all") @Redirect( - method = { "getChunkRenderType", "getMovingBlockRenderType" }, - at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/ItemBlockRenderTypes;renderCutout:Z")) + method = { "getChunkRenderType", "getMovingBlockRenderType", "getRenderLayers" }, + at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/ItemBlockRenderTypes;renderCutout:Z"), require = 2) private static boolean redirectLeavesShouldBeFancy() { return leavesFancy; } diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/options/render_layers/LeavesBlockMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/options/render_layers/LeavesBlockMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/options/render_layers/LeavesBlockMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/options/render_layers/LeavesBlockMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/options/weather/LevelRendererMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/options/weather/LevelRendererMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/options/weather/LevelRendererMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/options/weather/LevelRendererMixin.java diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/CubeMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/CubeMixin.java new file mode 100644 index 0000000000..d1590c9c14 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/CubeMixin.java @@ -0,0 +1,51 @@ +package net.caffeinemc.mods.sodium.mixin.features.render.entity; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.caffeinemc.mods.sodium.api.util.ColorARGB; +import net.caffeinemc.mods.sodium.api.vertex.buffer.VertexBufferWriter; +import net.caffeinemc.mods.sodium.client.render.immediate.model.EntityRenderer; +import net.caffeinemc.mods.sodium.client.render.immediate.model.ModelCuboid; +import net.caffeinemc.mods.sodium.client.render.vertex.VertexConsumerUtils; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.core.Direction; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Set; + +@Mixin(ModelPart.Cube.class) +public class CubeMixin { + @Mutable + @Shadow + @Final + public float minX; + + @Unique + private ModelCuboid sodium$cuboid; + + // Inject at the start of the function, so we don't capture modified locals + @Redirect(method = "", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/client/model/geom/ModelPart$Cube;minX:F", ordinal = 0)) + private void onInit(ModelPart.Cube instance, float value, int u, int v, float x, float y, float z, float sizeX, float sizeY, float sizeZ, float extraX, float extraY, float extraZ, boolean mirror, float textureWidth, float textureHeight, Set renderDirections) { + this.sodium$cuboid = new ModelCuboid(u, v, x, y, z, sizeX, sizeY, sizeZ, extraX, extraY, extraZ, mirror, textureWidth, textureHeight, renderDirections); + + this.minX = value; + } + + @Inject(method = "compile", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack$Pose;pose()Lorg/joml/Matrix4f;"), cancellable = true) + private void onCompile(PoseStack.Pose pose, VertexConsumer buffer, int light, int overlay, int color, CallbackInfo ci) { + VertexBufferWriter writer = VertexConsumerUtils.convertOrLog(buffer); + + if (writer == null) { + return; + } + + ci.cancel(); + + EntityRenderer.renderCuboid(pose, writer, this.sodium$cuboid, light, overlay, ColorARGB.toABGR(color)); + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/ModelPartMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/ModelPartMixin.java new file mode 100644 index 0000000000..e5a20fa916 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/ModelPartMixin.java @@ -0,0 +1,54 @@ +package net.caffeinemc.mods.sodium.mixin.features.render.entity; + +import net.caffeinemc.mods.sodium.client.render.immediate.model.EntityRenderer; +import net.caffeinemc.mods.sodium.api.math.MatrixHelper; +import net.minecraft.client.model.geom.ModelPart; +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +@Mixin(ModelPart.class) +public class ModelPartMixin { + @Shadow + public float x; + @Shadow + public float y; + @Shadow + public float z; + + @Shadow + public float xScale; + @Shadow + public float yScale; + @Shadow + public float zScale; + + @Shadow + public float yRot; + @Shadow + public float xRot; + @Shadow + public float zRot; + + /** + * @author JellySquid + * @reason Apply transform more quickly + */ + @Overwrite + public void translateAndRotate(PoseStack matrixStack) { + if (this.x != 0.0F || this.y != 0.0F || this.z != 0.0F) { + matrixStack.translate(this.x * (1.0f / 16.0f), this.y * (1.0f / 16.0f), this.z * (1.0f / 16.0f)); + } + + if (this.xRot != 0.0F || this.yRot != 0.0F || this.zRot != 0.0F) { + MatrixHelper.rotateZYX(matrixStack.last(), this.zRot, this.yRot, this.xRot); + } + + if (this.xScale != 1.0F || this.yScale != 1.0F || this.zScale != 1.0F) { + matrixStack.scale(this.xScale, this.yScale, this.zScale); + } + } +} diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/cull/EntityRendererMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/cull/EntityRendererMixin.java similarity index 93% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/cull/EntityRendererMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/cull/EntityRendererMixin.java index 1e11ca4ef3..59de0bc289 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/cull/EntityRendererMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/cull/EntityRendererMixin.java @@ -9,7 +9,6 @@ import net.minecraft.world.phys.AABB; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(EntityRenderer.class) public abstract class EntityRendererMixin { diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/shadows/EntityRenderDispatcherMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/shadows/EntityRenderDispatcherMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/shadows/EntityRenderDispatcherMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/shadows/EntityRenderDispatcherMixin.java diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/frapi/BakedModelMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/frapi/BakedModelMixin.java new file mode 100644 index 0000000000..55d863a21f --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/frapi/BakedModelMixin.java @@ -0,0 +1,29 @@ +package net.caffeinemc.mods.sodium.mixin.features.render.frapi; + +import net.caffeinemc.mods.sodium.client.render.frapi.render.AbstractBlockRenderContext; +import net.caffeinemc.mods.sodium.client.render.frapi.render.ItemRenderContext; +import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; +import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; +import org.spongepowered.asm.mixin.Mixin; + +import java.util.function.Supplier; + +@Mixin(BakedModel.class) +public interface BakedModelMixin extends FabricBakedModel { + @Override + default void emitBlockQuads(BlockAndTintGetter blockView, BlockState state, BlockPos pos, Supplier randomSupplier, RenderContext context) { + ((AbstractBlockRenderContext) context).bufferDefaultModel((BakedModel) this, state); + } + + // Override the default implementation to redirect to the fast ItemRenderer#renderBakedItemModel method when no transforms are applied. + @Override + default void emitItemQuads(ItemStack stack, Supplier randomSupplier, RenderContext context) { + ((ItemRenderContext) context).bufferDefaultModel((BakedModel) this, null); + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/frapi/ItemRendererAccessor.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/frapi/ItemRendererAccessor.java new file mode 100644 index 0000000000..0cd683bcf1 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/frapi/ItemRendererAccessor.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.mixin.features.render.frapi; + +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.world.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(ItemRenderer.class) +public interface ItemRendererAccessor { + @Invoker("hasAnimatedTexture") + static boolean sodium$hasAnimatedTexture(ItemStack stack) { + throw new AssertionError(); + } +} \ No newline at end of file diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/frapi/ItemRendererMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/frapi/ItemRendererMixin.java new file mode 100644 index 0000000000..a9d7ab6b83 --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/frapi/ItemRendererMixin.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.mixin.features.render.frapi; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.caffeinemc.mods.sodium.client.render.frapi.render.ItemRenderContext; +import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; +import net.minecraft.client.color.item.ItemColors; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.item.ItemStack; +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; + +/** + * Entrypoint of the FRAPI pipeline for item rendering, for the baked models that require it. + */ +@Mixin(ItemRenderer.class) +public abstract class ItemRendererMixin { + @Final + @Shadow + private ItemColors itemColors; + + @Shadow + protected abstract void renderModelLists(BakedModel bakedModel, ItemStack itemStack, int i, int j, PoseStack poseStack, VertexConsumer vertexConsumer); + + @Unique + private final ItemRenderContext.VanillaModelBufferer vanillaBufferer = this::renderModelLists; + + @Unique + private final ThreadLocal contexts = ThreadLocal.withInitial(() -> new ItemRenderContext(itemColors, vanillaBufferer)); + + @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/BakedModel;isCustomRenderer()Z"), cancellable = true) + private void beforeRenderItem(ItemStack stack, ItemDisplayContext transformMode, boolean invert, PoseStack matrixStack, MultiBufferSource vertexConsumerProvider, int light, int overlay, BakedModel model, CallbackInfo ci) { + if (!((FabricBakedModel) model).isVanillaAdapter()) { + contexts.get().renderModel(stack, transformMode, invert, matrixStack, vertexConsumerProvider, light, overlay, model); + matrixStack.popPose(); + ci.cancel(); + } + } +} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/frapi/ModelBlockRendererMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/frapi/ModelBlockRendererMixin.java new file mode 100644 index 0000000000..e231e6497a --- /dev/null +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/frapi/ModelBlockRendererMixin.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.mixin.features.render.frapi; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.caffeinemc.mods.sodium.client.render.frapi.render.NonTerrainBlockRenderContext; +import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel; +import net.minecraft.client.color.block.BlockColors; +import net.minecraft.client.renderer.block.ModelBlockRenderer; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; +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; + +/** + * Entrypoint of the FRAPI pipeline for non-terrain block rendering, for the baked models that require it. + */ +@Mixin(ModelBlockRenderer.class) +public abstract class ModelBlockRendererMixin { + @Shadow + @Final + private BlockColors blockColors; + + @Unique + private final ThreadLocal contexts = ThreadLocal.withInitial(() -> new NonTerrainBlockRenderContext(blockColors)); + + @Inject(method = "tesselateBlock", at = @At("HEAD"), cancellable = true) + private void onRender(BlockAndTintGetter blockView, BakedModel model, BlockState state, BlockPos pos, PoseStack matrix, VertexConsumer buffer, boolean cull, RandomSource rand, long seed, int overlay, CallbackInfo ci) { + if (!((FabricBakedModel) model).isVanillaAdapter()) { + contexts.get().renderModel(blockView, model, state, pos, matrix, buffer, cull, rand, seed, overlay); + ci.cancel(); + } + } +} diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/gui/font/BakedGlyphMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/gui/font/BakedGlyphMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/gui/font/BakedGlyphMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/gui/font/BakedGlyphMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/gui/outlines/LevelRendererMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/gui/outlines/LevelRendererMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/gui/outlines/LevelRendererMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/gui/outlines/LevelRendererMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/DirectionMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/DirectionMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/DirectionMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/DirectionMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/buffer_builder/intrinsics/BufferBuilderMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/buffer_builder/intrinsics/BufferBuilderMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/buffer_builder/intrinsics/BufferBuilderMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/buffer_builder/intrinsics/BufferBuilderMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/buffer_builder/sorting/MeshDataMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/buffer_builder/sorting/MeshDataMixin.java similarity index 97% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/buffer_builder/sorting/MeshDataMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/buffer_builder/sorting/MeshDataMixin.java index 1bea7357f8..d05d3a9f06 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/buffer_builder/sorting/MeshDataMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/buffer_builder/sorting/MeshDataMixin.java @@ -9,6 +9,7 @@ import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; +import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexSorting; import java.nio.ByteBuffer; diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/buffer_builder/sorting/VertexSortingMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/buffer_builder/sorting/VertexSortingMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/buffer_builder/sorting/VertexSortingMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/buffer_builder/sorting/VertexSortingMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/matrix_stack/PoseStackMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/matrix_stack/PoseStackMixin.java similarity index 95% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/matrix_stack/PoseStackMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/matrix_stack/PoseStackMixin.java index ade0dadda2..fa72ac8594 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/matrix_stack/PoseStackMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/matrix_stack/PoseStackMixin.java @@ -38,6 +38,8 @@ public void pushPose() { entry = new PoseStack.Pose(new Matrix4f(prev.pose()), new Matrix3f(prev.normal())); } + entry.trustedNormals = prev.trustedNormals; + this.poseStack.addLast(entry); } diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/matrix_stack/VertexConsumerMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/matrix_stack/VertexConsumerMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/matrix_stack/VertexConsumerMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/immediate/matrix_stack/VertexConsumerMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/model/ItemBlockRenderTypesMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/model/ItemBlockRenderTypesMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/model/ItemBlockRenderTypesMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/model/ItemBlockRenderTypesMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/model/item/ItemRendererMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/model/item/ItemRendererMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/model/item/ItemRendererMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/model/item/ItemRendererMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/particle/SingleQuadParticleMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/particle/SingleQuadParticleMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/particle/SingleQuadParticleMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/particle/SingleQuadParticleMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/clouds/LevelRendererMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/clouds/LevelRendererMixin.java similarity index 84% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/clouds/LevelRendererMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/clouds/LevelRendererMixin.java index 15a392614b..a5047b7122 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/clouds/LevelRendererMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/clouds/LevelRendererMixin.java @@ -34,14 +34,16 @@ public class LevelRendererMixin { * @author jellysquid3 * @reason Optimize cloud rendering */ - @Overwrite - public void renderClouds(PoseStack poseStack, Matrix4f modelMatrix, Matrix4f projectionMatrix, float tickDelta, double x, double y, double z) { + @Inject(method = "renderClouds", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/DimensionSpecialEffects;getCloudHeight()F"), cancellable = true) // Inject after Forge checks dimension support + public void renderClouds(PoseStack poseStack, Matrix4f matrix4f, Matrix4f projectionMatrix, float tickDelta, double x, double y, double z, CallbackInfo ci) { + ci.cancel(); + if (this.cloudRenderer == null) { this.cloudRenderer = new CloudRenderer(this.minecraft.getResourceManager()); } poseStack.pushPose(); - poseStack.mulPose(modelMatrix); + poseStack.mulPose(matrix4f); ClientLevel level = Objects.requireNonNull(this.level); Camera camera = this.minecraft.gameRenderer.getMainCamera(); diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/sky/ClientLevelMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/sky/ClientLevelMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/sky/ClientLevelMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/sky/ClientLevelMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/sky/FogRendererMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/sky/FogRendererMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/sky/FogRendererMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/sky/FogRendererMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/sky/LevelRendererMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/sky/LevelRendererMixin.java similarity index 89% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/sky/LevelRendererMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/sky/LevelRendererMixin.java index 57132fd198..4edcbc806d 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/sky/LevelRendererMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/world/sky/LevelRendererMixin.java @@ -7,12 +7,16 @@ import net.minecraft.world.level.material.FogType; import org.joml.Matrix4f; 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(LevelRenderer.class) -public class LevelRendererMixin { +public abstract class LevelRendererMixin { + @Shadow + protected abstract boolean doesMobEffectBlockSky(Camera camera); + /** *

Prevents the sky layer from rendering when the fog distance is reduced * from the default. This helps prevent situations where the sky can be seen @@ -36,7 +40,7 @@ private void preRenderSky(Matrix4f matrix4f, Matrix4f matrix4f2, float f, Camera // This prevents the sky from being visible through chunks culled by Sodium's fog occlusion. // Fixes https://bugs.mojang.com/browse/MC-152504. // Credit to bytzo for noticing the change in 1.18.2. - if (camera.getFluidInCamera() == FogType.WATER) { + if (camera.getFluidInCamera() != FogType.NONE || this.doesMobEffectBlockSky(camera)) { ci.cancel(); } } diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/shader/uniform/ShaderInstanceMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/shader/uniform/ShaderInstanceMixin.java similarity index 92% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/shader/uniform/ShaderInstanceMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/shader/uniform/ShaderInstanceMixin.java index 947e81516b..4c37086f9f 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/shader/uniform/ShaderInstanceMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/shader/uniform/ShaderInstanceMixin.java @@ -35,8 +35,8 @@ public class ShaderInstanceMixin { @Unique private Object2IntMap uniformCache; - @Inject(method = "", at = @At("RETURN")) - private void initCache(ResourceProvider factory, String name, VertexFormat format, CallbackInfo ci) { + @Unique + private void initCache() { this.uniformCache = new Object2IntOpenHashMap<>(); this.uniformCache.defaultReturnValue(-1); @@ -51,6 +51,11 @@ private void initCache(ResourceProvider factory, String name, VertexFormat forma } } + @Inject(method = "updateLocations", at = @At("RETURN"), require = 0) + private void initCache(CallbackInfo ci) { + this.initCache(); + } + @Redirect(method = "apply", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/shaders/Uniform;glGetUniformLocation(ILjava/lang/CharSequence;)I")) private int redirectGetUniformLocation(int program, CharSequence name) { var location = this.uniformCache.getInt(name); diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/NativeImageAccessor.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/NativeImageAccessor.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/NativeImageAccessor.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/NativeImageAccessor.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/SpriteContentsInvoker.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/SpriteContentsInvoker.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/SpriteContentsInvoker.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/SpriteContentsInvoker.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/AnimatedTextureAccessor.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/AnimatedTextureAccessor.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/AnimatedTextureAccessor.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/AnimatedTextureAccessor.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/GuiGraphicsMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/GuiGraphicsMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/GuiGraphicsMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/GuiGraphicsMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/ModelBlockRendererMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/ModelBlockRendererMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/ModelBlockRendererMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/ModelBlockRendererMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/SpriteContentsFrameInfoAccessor.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/SpriteContentsFrameInfoAccessor.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/SpriteContentsFrameInfoAccessor.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/SpriteContentsFrameInfoAccessor.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/SpriteContentsMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/SpriteContentsMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/SpriteContentsMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/SpriteContentsMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/SpriteContentsTickerMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/SpriteContentsTickerMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/SpriteContentsTickerMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/SpriteContentsTickerMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/TextureAtlasMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/TextureAtlasMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/TextureAtlasMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/TextureAtlasMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/TextureSheetParticleMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/TextureSheetParticleMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/TextureSheetParticleMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/tracking/TextureSheetParticleMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsAccessor.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsAccessor.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsAccessor.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsAccessor.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsAnimatedTextureAccessor.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsAnimatedTextureAccessor.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsAnimatedTextureAccessor.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsAnimatedTextureAccessor.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsFrameInfoAccessor.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsFrameInfoAccessor.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsFrameInfoAccessor.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsFrameInfoAccessor.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsInterpolationMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsInterpolationMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsInterpolationMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsInterpolationMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsTickerAccessor.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsTickerAccessor.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsTickerAccessor.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/animations/upload/SpriteContentsTickerAccessor.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/mipmaps/MipmapGeneratorMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/mipmaps/MipmapGeneratorMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/mipmaps/MipmapGeneratorMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/mipmaps/MipmapGeneratorMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/mipmaps/SpriteContentsMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/mipmaps/SpriteContentsMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/mipmaps/SpriteContentsMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/textures/mipmaps/SpriteContentsMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/world/biome/BiomeMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/world/biome/BiomeMixin.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/world/biome/BiomeMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/features/world/biome/BiomeMixin.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/workarounds/context_creation/WindowMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/workarounds/context_creation/WindowMixin.java similarity index 76% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/workarounds/context_creation/WindowMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/workarounds/context_creation/WindowMixin.java index 363170d932..f41356cf2d 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/workarounds/context_creation/WindowMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/workarounds/context_creation/WindowMixin.java @@ -1,5 +1,7 @@ package net.caffeinemc.mods.sodium.mixin.workarounds.context_creation; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.mojang.blaze3d.platform.DisplayData; import com.mojang.blaze3d.platform.ScreenManager; import com.mojang.blaze3d.platform.Window; @@ -9,6 +11,7 @@ import net.caffeinemc.mods.sodium.client.compatibility.environment.GLContextInfo; import net.caffeinemc.mods.sodium.client.compatibility.workarounds.Workarounds; import net.caffeinemc.mods.sodium.client.compatibility.workarounds.nvidia.NvidiaWorkarounds; +import net.caffeinemc.mods.sodium.client.services.PlatformInfoAccess; import net.minecraft.Util; import org.lwjgl.glfw.GLFW; import org.lwjgl.opengl.WGL; @@ -23,6 +26,10 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.function.IntSupplier; +import java.util.function.LongSupplier; +import java.util.function.Supplier; + @Mixin(Window.class) public class WindowMixin { @@ -33,7 +40,7 @@ public class WindowMixin { @Unique private long wglPrevContext = MemoryUtil.NULL; - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lorg/lwjgl/glfw/GLFW;glfwCreateWindow(IILjava/lang/CharSequence;JJ)J")) + @Redirect(method = "", at = @At(value = "INVOKE", target = "Lorg/lwjgl/glfw/GLFW;glfwCreateWindow(IILjava/lang/CharSequence;JJ)J"), expect = 0, require = 0) private long wrapGlfwCreateWindow(int width, int height, CharSequence title, long monitor, long share) { final boolean applyNvidiaWorkarounds = Workarounds.isWorkaroundEnabled(Workarounds.Reference.NVIDIA_THREADED_OPTIMIZATIONS); @@ -50,6 +57,24 @@ private long wrapGlfwCreateWindow(int width, int height, CharSequence title, lon } } + @SuppressWarnings("all") + @WrapOperation(method = "", at = @At(value = "INVOKE", target = "Lnet/neoforged/fml/loading/ImmediateWindowHandler;setupMinecraftWindow(Ljava/util/function/IntSupplier;Ljava/util/function/IntSupplier;Ljava/util/function/Supplier;Ljava/util/function/LongSupplier;)J"), expect = 0, require = 0) + private long wrapGlfwCreateWindowForge(final IntSupplier width, final IntSupplier height, final Supplier title, final LongSupplier monitor, Operation op) { + final boolean applyNvidiaWorkarounds = Workarounds.isWorkaroundEnabled(Workarounds.Reference.NVIDIA_THREADED_OPTIMIZATIONS); + + if (applyNvidiaWorkarounds && !PlatformInfoAccess.getInstance().platformHasEarlyLoadingScreen()) { + NvidiaWorkarounds.install(); + } + + try { + return op.call(width, height, title, monitor); + } finally { + if (applyNvidiaWorkarounds) { + NvidiaWorkarounds.uninstall(); + } + } + } + @Inject(method = "", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL;createCapabilities()Lorg/lwjgl/opengl/GLCapabilities;", shift = At.Shift.AFTER)) private void postContextReady(WindowEventHandler eventHandler, ScreenManager monitorTracker, DisplayData settings, String videoMode, String title, CallbackInfo ci) { GLContextInfo driver = GLContextInfo.create(); diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/workarounds/event_loop/RenderSystemMixin.java b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/workarounds/event_loop/RenderSystemMixin.java similarity index 94% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/workarounds/event_loop/RenderSystemMixin.java rename to common/src/main/java/net/caffeinemc/mods/sodium/mixin/workarounds/event_loop/RenderSystemMixin.java index b4459c7058..f99b92e68e 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/workarounds/event_loop/RenderSystemMixin.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/mixin/workarounds/event_loop/RenderSystemMixin.java @@ -7,6 +7,7 @@ @Mixin(RenderSystem.class) public class RenderSystemMixin { + @SuppressWarnings("EmptyMethod") @Redirect(method = "flipFrame", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;pollEvents()V", ordinal = 0), remap = false) private static void removeFirstPoll() { // noop diff --git a/src/main/resources/assets/minecraft/shaders/core/clouds.fsh b/common/src/main/resources/assets/minecraft/shaders/core/clouds.fsh similarity index 100% rename from src/main/resources/assets/minecraft/shaders/core/clouds.fsh rename to common/src/main/resources/assets/minecraft/shaders/core/clouds.fsh diff --git a/src/main/resources/assets/minecraft/shaders/core/clouds.json b/common/src/main/resources/assets/minecraft/shaders/core/clouds.json similarity index 100% rename from src/main/resources/assets/minecraft/shaders/core/clouds.json rename to common/src/main/resources/assets/minecraft/shaders/core/clouds.json diff --git a/src/main/resources/assets/minecraft/shaders/core/clouds.vsh b/common/src/main/resources/assets/minecraft/shaders/core/clouds.vsh similarity index 100% rename from src/main/resources/assets/minecraft/shaders/core/clouds.vsh rename to common/src/main/resources/assets/minecraft/shaders/core/clouds.vsh diff --git a/src/main/resources/assets/minecraft/textures/block/acacia_leaves.png b/common/src/main/resources/assets/minecraft/textures/block/acacia_leaves.png similarity index 100% rename from src/main/resources/assets/minecraft/textures/block/acacia_leaves.png rename to common/src/main/resources/assets/minecraft/textures/block/acacia_leaves.png diff --git a/src/main/resources/assets/minecraft/textures/block/azalea_leaves.png b/common/src/main/resources/assets/minecraft/textures/block/azalea_leaves.png similarity index 100% rename from src/main/resources/assets/minecraft/textures/block/azalea_leaves.png rename to common/src/main/resources/assets/minecraft/textures/block/azalea_leaves.png diff --git a/src/main/resources/assets/minecraft/textures/block/birch_leaves.png b/common/src/main/resources/assets/minecraft/textures/block/birch_leaves.png similarity index 100% rename from src/main/resources/assets/minecraft/textures/block/birch_leaves.png rename to common/src/main/resources/assets/minecraft/textures/block/birch_leaves.png diff --git a/src/main/resources/assets/minecraft/textures/block/cherry_leaves.png b/common/src/main/resources/assets/minecraft/textures/block/cherry_leaves.png similarity index 100% rename from src/main/resources/assets/minecraft/textures/block/cherry_leaves.png rename to common/src/main/resources/assets/minecraft/textures/block/cherry_leaves.png diff --git a/src/main/resources/assets/minecraft/textures/block/dark_oak_leaves.png b/common/src/main/resources/assets/minecraft/textures/block/dark_oak_leaves.png similarity index 100% rename from src/main/resources/assets/minecraft/textures/block/dark_oak_leaves.png rename to common/src/main/resources/assets/minecraft/textures/block/dark_oak_leaves.png diff --git a/src/main/resources/assets/minecraft/textures/block/flowering_azalea_leaves.png b/common/src/main/resources/assets/minecraft/textures/block/flowering_azalea_leaves.png similarity index 100% rename from src/main/resources/assets/minecraft/textures/block/flowering_azalea_leaves.png rename to common/src/main/resources/assets/minecraft/textures/block/flowering_azalea_leaves.png diff --git a/src/main/resources/assets/minecraft/textures/block/jungle_leaves.png b/common/src/main/resources/assets/minecraft/textures/block/jungle_leaves.png similarity index 100% rename from src/main/resources/assets/minecraft/textures/block/jungle_leaves.png rename to common/src/main/resources/assets/minecraft/textures/block/jungle_leaves.png diff --git a/src/main/resources/assets/minecraft/textures/block/mangrove_leaves.png b/common/src/main/resources/assets/minecraft/textures/block/mangrove_leaves.png similarity index 100% rename from src/main/resources/assets/minecraft/textures/block/mangrove_leaves.png rename to common/src/main/resources/assets/minecraft/textures/block/mangrove_leaves.png diff --git a/src/main/resources/assets/minecraft/textures/block/oak_leaves.png b/common/src/main/resources/assets/minecraft/textures/block/oak_leaves.png similarity index 100% rename from src/main/resources/assets/minecraft/textures/block/oak_leaves.png rename to common/src/main/resources/assets/minecraft/textures/block/oak_leaves.png diff --git a/src/main/resources/assets/minecraft/textures/block/spruce_leaves.png b/common/src/main/resources/assets/minecraft/textures/block/spruce_leaves.png similarity index 100% rename from src/main/resources/assets/minecraft/textures/block/spruce_leaves.png rename to common/src/main/resources/assets/minecraft/textures/block/spruce_leaves.png diff --git a/src/main/resources/assets/sodium/lang/en_us.json b/common/src/main/resources/assets/sodium/lang/en_us.json similarity index 100% rename from src/main/resources/assets/sodium/lang/en_us.json rename to common/src/main/resources/assets/sodium/lang/en_us.json diff --git a/src/main/resources/assets/sodium/shaders/blocks/block_layer_opaque.fsh b/common/src/main/resources/assets/sodium/shaders/blocks/block_layer_opaque.fsh similarity index 100% rename from src/main/resources/assets/sodium/shaders/blocks/block_layer_opaque.fsh rename to common/src/main/resources/assets/sodium/shaders/blocks/block_layer_opaque.fsh diff --git a/src/main/resources/assets/sodium/shaders/blocks/block_layer_opaque.vsh b/common/src/main/resources/assets/sodium/shaders/blocks/block_layer_opaque.vsh similarity index 100% rename from src/main/resources/assets/sodium/shaders/blocks/block_layer_opaque.vsh rename to common/src/main/resources/assets/sodium/shaders/blocks/block_layer_opaque.vsh diff --git a/src/main/resources/assets/sodium/shaders/include/chunk_material.glsl b/common/src/main/resources/assets/sodium/shaders/include/chunk_material.glsl similarity index 84% rename from src/main/resources/assets/sodium/shaders/include/chunk_material.glsl rename to common/src/main/resources/assets/sodium/shaders/include/chunk_material.glsl index 04e4e5b336..bd73ad3976 100644 --- a/src/main/resources/assets/sodium/shaders/include/chunk_material.glsl +++ b/common/src/main/resources/assets/sodium/shaders/include/chunk_material.glsl @@ -1,7 +1,7 @@ const uint MATERIAL_USE_MIP_OFFSET = 0u; const uint MATERIAL_ALPHA_CUTOFF_OFFSET = 1u; -const float[4] ALPHA_CUTOFF = float[4](0.0, 0.1, 0.5, 1.0); +const float[4] ALPHA_CUTOFF = float[4](0.0, 0.1, 0.1, 1.0); float _material_mip_bias(uint material) { return ((material >> MATERIAL_USE_MIP_OFFSET) & 1u) != 0u ? 0.0 : -4.0; diff --git a/src/main/resources/assets/sodium/shaders/include/chunk_matrices.glsl b/common/src/main/resources/assets/sodium/shaders/include/chunk_matrices.glsl similarity index 100% rename from src/main/resources/assets/sodium/shaders/include/chunk_matrices.glsl rename to common/src/main/resources/assets/sodium/shaders/include/chunk_matrices.glsl diff --git a/common/src/main/resources/assets/sodium/shaders/include/chunk_vertex.glsl b/common/src/main/resources/assets/sodium/shaders/include/chunk_vertex.glsl new file mode 100644 index 0000000000..b6a1ae4deb --- /dev/null +++ b/common/src/main/resources/assets/sodium/shaders/include/chunk_vertex.glsl @@ -0,0 +1,69 @@ +// The position of the vertex around the model origin +vec3 _vert_position; + +// The block texture coordinate of the vertex +vec2 _vert_tex_diffuse_coord; + +// The light texture coordinate of the vertex +vec2 _vert_tex_light_coord; + +// The color of the vertex +vec4 _vert_color; + +// The index of the draw command which this vertex belongs to +uint _draw_id; + +// The material bits for the primitive +uint _material_params; + +#ifdef USE_VERTEX_COMPRESSION +const uint POSITION_BITS = 20u; +const uint POSITION_MAX_COORD = 1u << POSITION_BITS; +const uint POSITION_MAX_VALUE = POSITION_MAX_COORD - 1u; + +const uint TEXTURE_BITS = 15u; +const uint TEXTURE_MAX_COORD = 1u << TEXTURE_BITS; +const uint TEXTURE_MAX_VALUE = TEXTURE_MAX_COORD - 1u; + +const float VERTEX_SCALE = 32.0 / POSITION_MAX_COORD; +const float VERTEX_OFFSET = -8.0; + +// The amount of inset the texture coordinates from the edges of the texture, to avoid texture bleeding +const float TEXTURE_FUZZ_AMOUNT = 1.0 / 64.0; +const float TEXTURE_GROW_FACTOR = (1.0 - TEXTURE_FUZZ_AMOUNT) / TEXTURE_MAX_COORD; + +in uint a_PositionHi; +in uint a_PositionLo; +in vec4 a_Color; +in uvec2 a_TexCoord; +in uvec4 a_LightAndData; + +uvec3 _deinterleave_u20x3(uint packed_hi, uint packed_lo) { + uvec3 hi = (uvec3(packed_hi) >> uvec3(0u, 10u, 20u)) & 0x3FFu; + uvec3 lo = (uvec3(packed_lo) >> uvec3(0u, 10u, 20u)) & 0x3FFu; + + return (hi << 10u) | lo; +} + +vec2 _get_texcoord() { + return vec2(a_TexCoord & TEXTURE_MAX_VALUE) / float(TEXTURE_MAX_COORD); +} + +vec2 _get_texcoord_bias() { + return mix(vec2(-TEXTURE_GROW_FACTOR), vec2(TEXTURE_GROW_FACTOR), bvec2(a_TexCoord >> TEXTURE_BITS)); +} + +void _vert_init() { + _vert_position = ((_deinterleave_u20x3(a_PositionHi, a_PositionLo) * VERTEX_SCALE) + VERTEX_OFFSET); + _vert_color = a_Color; + _vert_tex_diffuse_coord = _get_texcoord() + _get_texcoord_bias(); + + _vert_tex_light_coord = vec2(a_LightAndData.xy) / vec2(256.0); + + _material_params = a_LightAndData[2]; + _draw_id = a_LightAndData[3]; +} + +#else +#error "Vertex compression must be enabled" +#endif \ No newline at end of file diff --git a/src/main/resources/assets/sodium/shaders/include/fog.glsl b/common/src/main/resources/assets/sodium/shaders/include/fog.glsl similarity index 100% rename from src/main/resources/assets/sodium/shaders/include/fog.glsl rename to common/src/main/resources/assets/sodium/shaders/include/fog.glsl diff --git a/src/main/resources/assets/sodium/textures/gui/arrows.png b/common/src/main/resources/assets/sodium/textures/gui/arrows.png similarity index 100% rename from src/main/resources/assets/sodium/textures/gui/arrows.png rename to common/src/main/resources/assets/sodium/textures/gui/arrows.png diff --git a/src/main/resources/programmer_art/assets/minecraft/textures/block/acacia_leaves.png b/common/src/main/resources/programmer_art/assets/minecraft/textures/block/acacia_leaves.png similarity index 100% rename from src/main/resources/programmer_art/assets/minecraft/textures/block/acacia_leaves.png rename to common/src/main/resources/programmer_art/assets/minecraft/textures/block/acacia_leaves.png diff --git a/src/main/resources/programmer_art/assets/minecraft/textures/block/birch_leaves.png b/common/src/main/resources/programmer_art/assets/minecraft/textures/block/birch_leaves.png similarity index 100% rename from src/main/resources/programmer_art/assets/minecraft/textures/block/birch_leaves.png rename to common/src/main/resources/programmer_art/assets/minecraft/textures/block/birch_leaves.png diff --git a/src/main/resources/programmer_art/assets/minecraft/textures/block/dark_oak_leaves.png b/common/src/main/resources/programmer_art/assets/minecraft/textures/block/dark_oak_leaves.png similarity index 100% rename from src/main/resources/programmer_art/assets/minecraft/textures/block/dark_oak_leaves.png rename to common/src/main/resources/programmer_art/assets/minecraft/textures/block/dark_oak_leaves.png diff --git a/src/main/resources/programmer_art/assets/minecraft/textures/block/jungle_leaves.png b/common/src/main/resources/programmer_art/assets/minecraft/textures/block/jungle_leaves.png similarity index 100% rename from src/main/resources/programmer_art/assets/minecraft/textures/block/jungle_leaves.png rename to common/src/main/resources/programmer_art/assets/minecraft/textures/block/jungle_leaves.png diff --git a/src/main/resources/programmer_art/assets/minecraft/textures/block/oak_leaves.png b/common/src/main/resources/programmer_art/assets/minecraft/textures/block/oak_leaves.png similarity index 100% rename from src/main/resources/programmer_art/assets/minecraft/textures/block/oak_leaves.png rename to common/src/main/resources/programmer_art/assets/minecraft/textures/block/oak_leaves.png diff --git a/src/main/resources/programmer_art/assets/minecraft/textures/block/spruce_leaves.png b/common/src/main/resources/programmer_art/assets/minecraft/textures/block/spruce_leaves.png similarity index 100% rename from src/main/resources/programmer_art/assets/minecraft/textures/block/spruce_leaves.png rename to common/src/main/resources/programmer_art/assets/minecraft/textures/block/spruce_leaves.png diff --git a/src/main/resources/assets/sodium/icon.png b/common/src/main/resources/sodium-icon.png similarity index 100% rename from src/main/resources/assets/sodium/icon.png rename to common/src/main/resources/sodium-icon.png diff --git a/src/main/resources/sodium.accesswidener b/common/src/main/resources/sodium.accesswidener similarity index 100% rename from src/main/resources/sodium.accesswidener rename to common/src/main/resources/sodium.accesswidener diff --git a/src/main/resources/sodium.mixins.json b/common/src/main/resources/sodium.mixins.json similarity index 95% rename from src/main/resources/sodium.mixins.json rename to common/src/main/resources/sodium.mixins.json index ed405322d7..5ceba82f0b 100644 --- a/src/main/resources/sodium.mixins.json +++ b/common/src/main/resources/sodium.mixins.json @@ -15,7 +15,6 @@ "core.gui.LevelLoadStatusManagerMixin", "core.model.colors.BlockColorsMixin", "core.model.colors.ItemColorsMixin", - "core.model.quad.BakedQuadMixin", "core.model.FaceBakeryMixin", "core.render.chunk.LiquidBlockRendererMixin", "core.render.frustum.FrustumMixin", @@ -38,8 +37,6 @@ "features.gui.hooks.debug.DebugScreenOverlayMixin", "features.gui.hooks.settings.OptionsScreenMixin", "features.gui.screen.LevelLoadingScreenMixin", - "features.model.MultiPartBakedModelMixin", - "features.model.WeightedBakedModelMixin", "features.options.overlays.GuiMixin", "features.options.render_layers.LeavesBlockMixin", "features.options.render_layers.ItemBlockRenderTypesMixin", @@ -48,6 +45,10 @@ "features.render.entity.ModelPartMixin", "features.render.entity.cull.EntityRendererMixin", "features.render.entity.shadows.EntityRenderDispatcherMixin", + "features.render.frapi.BakedModelMixin", + "features.render.frapi.ModelBlockRendererMixin", + "features.render.frapi.ItemRendererMixin", + "features.render.frapi.ItemRendererAccessor", "features.render.gui.font.BakedGlyphMixin", "features.render.gui.outlines.LevelRendererMixin", "features.render.immediate.DirectionMixin", @@ -57,7 +58,6 @@ "features.render.immediate.matrix_stack.PoseStackMixin", "features.render.immediate.matrix_stack.VertexConsumerMixin", "features.render.model.ItemBlockRenderTypesMixin", - "features.render.model.block.ModelBlockRendererMixin", "features.render.model.item.ItemRendererMixin", "features.render.particle.SingleQuadParticleMixin", "features.render.world.clouds.LevelRendererMixin", diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/checks/BugChecks.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/checks/BugChecks.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/compatibility/checks/BugChecks.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/checks/BugChecks.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/checks/ModuleScanner.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/checks/ModuleScanner.java similarity index 84% rename from src/main/java/net/caffeinemc/mods/sodium/client/compatibility/checks/ModuleScanner.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/checks/ModuleScanner.java index db61df7b21..0c2cd3e499 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/checks/ModuleScanner.java +++ b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/checks/ModuleScanner.java @@ -1,12 +1,15 @@ package net.caffeinemc.mods.sodium.client.compatibility.checks; +import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.platform.Window; +import com.sun.jna.Platform; +import com.sun.jna.platform.win32.Kernel32Util; +import com.sun.jna.platform.win32.Tlhelp32; import net.caffeinemc.mods.sodium.client.platform.MessageBox; import net.caffeinemc.mods.sodium.client.platform.windows.WindowsFileVersion; import net.caffeinemc.mods.sodium.client.platform.windows.api.Kernel32; import net.caffeinemc.mods.sodium.client.platform.windows.api.version.Version; import net.minecraft.client.Minecraft; -import net.minecraft.util.NativeModuleLister; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -15,6 +18,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.List; +import java.util.Optional; import java.util.regex.Pattern; /** @@ -28,10 +32,10 @@ public class ModuleScanner { private static final String[] RTSS_HOOKS_MODULE_NAMES = { "RTSSHooks64.dll", "RTSSHooks.dll" }; public static void checkModules() { - List modules; + List modules; try { - modules = NativeModuleLister.listModules(); + modules = listModules(); } catch (Throwable t) { LOGGER.warn("Failed to scan the currently loaded modules", t); return; @@ -48,6 +52,22 @@ public static void checkModules() { } } + private static List listModules() { + if (!Platform.isWindows()) { + return ImmutableList.of(); + } else { + int i = com.sun.jna.platform.win32.Kernel32.INSTANCE.GetCurrentProcessId(); + ImmutableList.Builder builder = ImmutableList.builder(); + + for(Tlhelp32.MODULEENTRY32W mODULEENTRY32W : Kernel32Util.getModules(i)) { + String string = mODULEENTRY32W.szModule(); + builder.add(string); + } + + return builder.build(); + } + } + private static void checkRTSSModules() { LOGGER.warn("RivaTuner Statistics Server (RTSS) has injected into the process! Attempting to apply workarounds for compatibility..."); @@ -140,10 +160,10 @@ private static boolean isRTSSCompatible(WindowsFileVersion version) { return WindowsFileVersion.fromFileVersion(fileVersion); } - private static boolean isModuleLoaded(List modules, String[] names) { + private static boolean isModuleLoaded(List modules, String[] names) { for (var name : names) { for (var module : modules) { - if (module.name.equalsIgnoreCase(name)) { + if (module.equalsIgnoreCase(name)) { return true; } } diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/checks/PostLaunchChecks.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/checks/PostLaunchChecks.java similarity index 83% rename from src/main/java/net/caffeinemc/mods/sodium/client/compatibility/checks/PostLaunchChecks.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/checks/PostLaunchChecks.java index 68080168d2..311ce50f43 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/checks/PostLaunchChecks.java +++ b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/checks/PostLaunchChecks.java @@ -1,10 +1,13 @@ package net.caffeinemc.mods.sodium.client.compatibility.checks; -import net.caffeinemc.mods.sodium.client.gui.console.Console; -import net.caffeinemc.mods.sodium.client.gui.console.message.MessageLevel; -import net.minecraft.network.chat.Component; +import net.caffeinemc.mods.sodium.client.compatibility.workarounds.nvidia.NvidiaDriverVersion; +import net.caffeinemc.mods.sodium.client.console.Console; +import net.caffeinemc.mods.sodium.client.console.message.MessageLevel; +import net.caffeinemc.mods.sodium.client.compatibility.environment.GLContextInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import oshi.PlatformEnum; +import oshi.SystemInfo; /** * Performs OpenGL driver validation after the game creates an OpenGL context. This runs immediately after OpenGL @@ -16,7 +19,7 @@ public class PostLaunchChecks { public static void onContextInitialized() { // FIXME: This can be determined earlier, but we can't access the GUI classes in pre-launch if (isUsingPojavLauncher()) { - Console.instance().logMessage(MessageLevel.SEVERE, Component.translatable("sodium.console.pojav_launcher"), 30.0); + Console.instance().logMessage(MessageLevel.SEVERE, "sodium.console.pojav_launcher", true, 30.0); LOGGER.error("It appears that PojavLauncher is being used with an OpenGL compatibility layer. This will " + "likely cause severe performance issues, graphical issues, and crashes when used with Sodium. This " + "configuration is not supported -- you are on your own!"); diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/checks/PreLaunchChecks.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/checks/PreLaunchChecks.java similarity index 97% rename from src/main/java/net/caffeinemc/mods/sodium/client/compatibility/checks/PreLaunchChecks.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/checks/PreLaunchChecks.java index 413c39b38e..966e5488ee 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/checks/PreLaunchChecks.java +++ b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/checks/PreLaunchChecks.java @@ -1,13 +1,12 @@ package net.caffeinemc.mods.sodium.client.compatibility.checks; +import net.caffeinemc.mods.sodium.client.compatibility.environment.OsUtils; import net.caffeinemc.mods.sodium.client.compatibility.environment.probe.GraphicsAdapterProbe; import net.caffeinemc.mods.sodium.client.compatibility.environment.probe.GraphicsAdapterVendor; import net.caffeinemc.mods.sodium.client.compatibility.workarounds.nvidia.NvidiaDriverVersion; import net.caffeinemc.mods.sodium.client.platform.MessageBox; import net.caffeinemc.mods.sodium.client.platform.windows.WindowsFileVersion; import net.caffeinemc.mods.sodium.client.platform.windows.api.d3dkmt.D3DKMT; -import net.caffeinemc.mods.sodium.client.util.OsUtils; -import net.caffeinemc.mods.sodium.client.util.OsUtils.OperatingSystem; import org.jetbrains.annotations.Nullable; import org.lwjgl.Version; import org.slf4j.Logger; @@ -110,7 +109,7 @@ private static void showCriticalErrorAndClose(String title, String message, Stri // https://github.com/CaffeineMC/sodium-fabric/issues/899 private static @Nullable WindowsFileVersion findIntelDriverMatchingBug899() { - if (OsUtils.getOs() != OperatingSystem.WIN) { + if (OsUtils.getOs() != OsUtils.OperatingSystem.WIN) { return null; } @@ -146,7 +145,7 @@ private static void showCriticalErrorAndClose(String title, String message, Stri private static @Nullable WindowsFileVersion findNvidiaDriverMatchingBug1486() { // The Linux driver has two separate branches which have overlapping version numbers, despite also having // different feature sets. As a result, we can't reliably determine which Linux drivers are broken... - if (OsUtils.getOs() != OperatingSystem.WIN) { + if (OsUtils.getOs() != OsUtils.OperatingSystem.WIN) { return null; } diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/environment/GLContextInfo.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/environment/GLContextInfo.java similarity index 99% rename from src/main/java/net/caffeinemc/mods/sodium/client/compatibility/environment/GLContextInfo.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/environment/GLContextInfo.java index fb54c1647a..1a64f8ba54 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/environment/GLContextInfo.java +++ b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/environment/GLContextInfo.java @@ -6,6 +6,7 @@ public record GLContextInfo(String vendor, String renderer, String version) { @Nullable public static GLContextInfo create() { + String vendor = GL11C.glGetString(GL11C.GL_VENDOR); String renderer = GL11C.glGetString(GL11C.GL_RENDERER); String version = GL11C.glGetString(GL11C.GL_VERSION); diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/OsUtils.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/environment/OsUtils.java similarity index 88% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/OsUtils.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/environment/OsUtils.java index 7f45a484e1..4f39eb9ce0 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/util/OsUtils.java +++ b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/environment/OsUtils.java @@ -1,4 +1,4 @@ -package net.caffeinemc.mods.sodium.client.util; +package net.caffeinemc.mods.sodium.client.compatibility.environment; import org.apache.commons.lang3.SystemUtils; diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/environment/probe/GraphicsAdapterInfo.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/environment/probe/GraphicsAdapterInfo.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/compatibility/environment/probe/GraphicsAdapterInfo.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/environment/probe/GraphicsAdapterInfo.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/environment/probe/GraphicsAdapterProbe.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/environment/probe/GraphicsAdapterProbe.java similarity index 98% rename from src/main/java/net/caffeinemc/mods/sodium/client/compatibility/environment/probe/GraphicsAdapterProbe.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/environment/probe/GraphicsAdapterProbe.java index 6e79b6b767..e78cb129e4 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/environment/probe/GraphicsAdapterProbe.java +++ b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/environment/probe/GraphicsAdapterProbe.java @@ -1,7 +1,7 @@ package net.caffeinemc.mods.sodium.client.compatibility.environment.probe; +import net.caffeinemc.mods.sodium.client.compatibility.environment.OsUtils; import net.caffeinemc.mods.sodium.client.platform.windows.api.d3dkmt.D3DKMT; -import net.caffeinemc.mods.sodium.client.util.OsUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import oshi.util.ExecutingCommand; diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/environment/probe/GraphicsAdapterVendor.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/environment/probe/GraphicsAdapterVendor.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/compatibility/environment/probe/GraphicsAdapterVendor.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/environment/probe/GraphicsAdapterVendor.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/Workarounds.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/Workarounds.java similarity index 97% rename from src/main/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/Workarounds.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/Workarounds.java index a1185ea5f5..5768eb8102 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/Workarounds.java +++ b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/Workarounds.java @@ -1,9 +1,9 @@ package net.caffeinemc.mods.sodium.client.compatibility.workarounds; +import net.caffeinemc.mods.sodium.client.compatibility.environment.OsUtils; import net.caffeinemc.mods.sodium.client.compatibility.environment.probe.GraphicsAdapterInfo; import net.caffeinemc.mods.sodium.client.compatibility.environment.probe.GraphicsAdapterProbe; import net.caffeinemc.mods.sodium.client.compatibility.environment.probe.GraphicsAdapterVendor; -import net.caffeinemc.mods.sodium.client.util.OsUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/nvidia/NvidiaDriverVersion.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/nvidia/NvidiaDriverVersion.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/nvidia/NvidiaDriverVersion.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/nvidia/NvidiaDriverVersion.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/nvidia/NvidiaWorkarounds.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/nvidia/NvidiaWorkarounds.java similarity index 96% rename from src/main/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/nvidia/NvidiaWorkarounds.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/nvidia/NvidiaWorkarounds.java index 7be0e47231..ab86532358 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/nvidia/NvidiaWorkarounds.java +++ b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/compatibility/workarounds/nvidia/NvidiaWorkarounds.java @@ -1,9 +1,9 @@ package net.caffeinemc.mods.sodium.client.compatibility.workarounds.nvidia; +import net.caffeinemc.mods.sodium.client.compatibility.environment.OsUtils; import net.caffeinemc.mods.sodium.client.platform.unix.Libc; import net.caffeinemc.mods.sodium.client.platform.windows.api.Kernel32; import net.caffeinemc.mods.sodium.client.platform.windows.WindowsCommandLine; -import net.caffeinemc.mods.sodium.client.util.OsUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/Console.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/console/Console.java similarity index 58% rename from src/main/java/net/caffeinemc/mods/sodium/client/gui/console/Console.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/console/Console.java index b01243b07a..7e4fa1a760 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/Console.java +++ b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/console/Console.java @@ -1,8 +1,7 @@ -package net.caffeinemc.mods.sodium.client.gui.console; +package net.caffeinemc.mods.sodium.client.console; -import net.caffeinemc.mods.sodium.client.gui.console.message.Message; -import net.caffeinemc.mods.sodium.client.gui.console.message.MessageLevel; -import net.minecraft.network.chat.Component; +import net.caffeinemc.mods.sodium.client.console.message.Message; +import net.caffeinemc.mods.sodium.client.console.message.MessageLevel; import org.jetbrains.annotations.NotNull; import java.util.ArrayDeque; @@ -10,16 +9,16 @@ import java.util.Objects; public class Console implements ConsoleSink { - static final Console INSTANCE = new Console(); + public static final Console INSTANCE = new Console(); private final ArrayDeque messages = new ArrayDeque<>(); @Override - public void logMessage(@NotNull MessageLevel level, @NotNull Component text, double duration) { + public void logMessage(@NotNull MessageLevel level, @NotNull String text, boolean translatable, double duration) { Objects.requireNonNull(level); Objects.requireNonNull(text); - this.messages.addLast(new Message(level, text.copy(), duration)); + this.messages.addLast(new Message(level, text, translatable, duration)); } public Deque getMessageDrain() { diff --git a/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/console/ConsoleSink.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/console/ConsoleSink.java new file mode 100644 index 0000000000..fb02fa03aa --- /dev/null +++ b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/console/ConsoleSink.java @@ -0,0 +1,8 @@ +package net.caffeinemc.mods.sodium.client.console; + +import net.caffeinemc.mods.sodium.client.console.message.MessageLevel; +import org.jetbrains.annotations.NotNull; + +public interface ConsoleSink { + void logMessage(@NotNull MessageLevel level, @NotNull String text, boolean translatable, double duration); +} diff --git a/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/console/message/Message.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/console/message/Message.java new file mode 100644 index 0000000000..b427889a41 --- /dev/null +++ b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/console/message/Message.java @@ -0,0 +1,5 @@ +package net.caffeinemc.mods.sodium.client.console.message; + +public record Message(MessageLevel level, String text, boolean translated, double duration) { + +} diff --git a/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/console/message/MessageLevel.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/console/message/MessageLevel.java new file mode 100644 index 0000000000..d4a29ce768 --- /dev/null +++ b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/console/message/MessageLevel.java @@ -0,0 +1,7 @@ +package net.caffeinemc.mods.sodium.client.console.message; + +public enum MessageLevel { + INFO, + WARN, + SEVERE +} diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/MessageBox.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/MessageBox.java similarity index 89% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/MessageBox.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/MessageBox.java index 60b392357a..0ff28c6638 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/platform/MessageBox.java +++ b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/MessageBox.java @@ -1,8 +1,7 @@ package net.caffeinemc.mods.sodium.client.platform; +import net.caffeinemc.mods.sodium.client.compatibility.environment.OsUtils; import net.caffeinemc.mods.sodium.client.platform.windows.api.msgbox.MsgBoxParamSw; -import net.caffeinemc.mods.sodium.client.util.OsUtils; -import net.minecraft.Util; import net.caffeinemc.mods.sodium.client.platform.windows.api.msgbox.MsgBoxCallback; import net.caffeinemc.mods.sodium.client.platform.windows.api.User32; import org.jetbrains.annotations.Nullable; @@ -12,6 +11,9 @@ import com.mojang.blaze3d.platform.Window; import org.lwjgl.util.tinyfd.TinyFileDialogs; +import java.awt.*; +import java.io.IOException; +import java.net.URI; import java.nio.ByteBuffer; import java.util.Locale; import java.util.Objects; @@ -55,8 +57,11 @@ public void showMessageBox(@Nullable Window window, IconType icon, String title, boolean clicked = TinyFileDialogs.tinyfd_messageBox(title, helpUrl == null ? description : description + NOTICE, helpUrl == null ? "ok" : "okcancel", icon.name().toLowerCase(Locale.ROOT), false); if (clicked && helpUrl != null) { - Util.getPlatform() - .openUri(helpUrl); + try { + Desktop.getDesktop().browse(URI.create(helpUrl)); + } catch (IOException e) { + System.out.println("Failed to open! Giving up."); + } } } } @@ -75,8 +80,11 @@ public void showMessageBox(@Nullable Window window, if (helpUrl != null) { msgBoxCallback = MsgBoxCallback.create(lpHelpInfo -> { - Util.getPlatform() - .openUri(helpUrl); + try { + Desktop.getDesktop().browse(URI.create(helpUrl)); + } catch (IOException e) { + System.out.println("Failed to open! Giving up."); + } }); } else { msgBoxCallback = null; diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/unix/Libc.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/unix/Libc.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/unix/Libc.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/unix/Libc.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/WindowsCommandLine.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/WindowsCommandLine.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/WindowsCommandLine.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/WindowsCommandLine.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/WindowsFileVersion.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/WindowsFileVersion.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/WindowsFileVersion.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/WindowsFileVersion.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/Gdi32.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/Gdi32.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/Gdi32.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/Gdi32.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/Kernel32.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/Kernel32.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/Kernel32.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/Kernel32.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/User32.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/User32.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/User32.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/User32.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMT.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMT.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMT.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMT.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTAdapterInfoStruct.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTAdapterInfoStruct.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTAdapterInfoStruct.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTAdapterInfoStruct.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTAdapterRegistryInfoStruct.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTAdapterRegistryInfoStruct.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTAdapterRegistryInfoStruct.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTAdapterRegistryInfoStruct.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTEnumAdaptersStruct.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTEnumAdaptersStruct.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTEnumAdaptersStruct.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTEnumAdaptersStruct.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTOpenGLInfoStruct.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTOpenGLInfoStruct.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTOpenGLInfoStruct.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTOpenGLInfoStruct.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTQueryAdapterInfoStruct.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTQueryAdapterInfoStruct.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTQueryAdapterInfoStruct.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTQueryAdapterInfoStruct.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTQueryAdapterInfoType.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTQueryAdapterInfoType.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTQueryAdapterInfoType.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/d3dkmt/D3DKMTQueryAdapterInfoType.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/msgbox/MsgBoxCallback.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/msgbox/MsgBoxCallback.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/msgbox/MsgBoxCallback.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/msgbox/MsgBoxCallback.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/msgbox/MsgBoxCallbackI.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/msgbox/MsgBoxCallbackI.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/msgbox/MsgBoxCallbackI.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/msgbox/MsgBoxCallbackI.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/msgbox/MsgBoxParamSw.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/msgbox/MsgBoxParamSw.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/msgbox/MsgBoxParamSw.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/msgbox/MsgBoxParamSw.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/LanguageCodePage.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/LanguageCodePage.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/LanguageCodePage.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/LanguageCodePage.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/QueryResult.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/QueryResult.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/QueryResult.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/QueryResult.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/Version.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/Version.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/Version.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/Version.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/VersionFixedFileInfoStruct.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/VersionFixedFileInfoStruct.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/VersionFixedFileInfoStruct.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/VersionFixedFileInfoStruct.java diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/VersionInfo.java b/common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/VersionInfo.java similarity index 100% rename from src/main/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/VersionInfo.java rename to common/src/workarounds/java/net/caffeinemc/mods/sodium/client/platform/windows/api/version/VersionInfo.java diff --git a/common/src/workarounds/resources/META-INF/MANIFEST.MF b/common/src/workarounds/resources/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..5e57fdd49a --- /dev/null +++ b/common/src/workarounds/resources/META-INF/MANIFEST.MF @@ -0,0 +1 @@ +FMLModType: LIBRARY diff --git a/fabric/build.gradle.kts b/fabric/build.gradle.kts new file mode 100644 index 0000000000..ee017f4916 --- /dev/null +++ b/fabric/build.gradle.kts @@ -0,0 +1,91 @@ +plugins { + id("java") + id("idea") + id("fabric-loom") version ("1.7.3") +} + +val MINECRAFT_VERSION: String by rootProject.extra +val PARCHMENT_VERSION: String? by rootProject.extra +val FABRIC_LOADER_VERSION: String by rootProject.extra +val FABRIC_API_VERSION: String by rootProject.extra +val MOD_VERSION: String by rootProject.extra + +base { + archivesName.set("sodium-fabric") +} + +dependencies { + minecraft("com.mojang:minecraft:${MINECRAFT_VERSION}") + mappings(loom.layered { + officialMojangMappings() + if (PARCHMENT_VERSION != null) { + parchment("org.parchmentmc.data:parchment-${MINECRAFT_VERSION}:${PARCHMENT_VERSION}@zip") + } + }) + modImplementation("net.fabricmc:fabric-loader:$FABRIC_LOADER_VERSION") + + fun addEmbeddedFabricModule(name: String) { + val module = fabricApi.module(name, FABRIC_API_VERSION) + modImplementation(module) + include(module) + } + + // Fabric API modules + addEmbeddedFabricModule("fabric-api-base") + addEmbeddedFabricModule("fabric-block-view-api-v2") + addEmbeddedFabricModule("fabric-renderer-api-v1") + addEmbeddedFabricModule("fabric-rendering-data-attachment-v1") + addEmbeddedFabricModule("fabric-rendering-fluids-v1") + addEmbeddedFabricModule("fabric-resource-loader-v0") + include(implementation(group = "com.lodborg", name = "interval-tree", version = "1.0.0")) + + implementation("com.google.code.findbugs:jsr305:3.0.1") + + implementation(project.project(":common").sourceSets.getByName("api").output) + implementation(project.project(":common").sourceSets.getByName("main").output) + implementation(project.project(":common").sourceSets.getByName("workarounds").output) +} + +tasks.named("compileTestJava").configure { + enabled = false +} + +tasks.named("test").configure { + enabled = false +} + +loom { + if (project(":common").file("src/main/resources/sodium.accesswidener").exists()) + accessWidenerPath.set(project(":common").file("src/main/resources/sodium.accesswidener")) + + @Suppress("UnstableApiUsage") + mixin { defaultRefmapName.set("sodium-fabric.refmap.json") } + + runs { + named("client") { + client() + configName = "Fabric Client" + ideConfigGenerated(true) + runDir("run") + } + } +} + +tasks { + processResources { + from(project.project(":common").sourceSets.main.get().resources) + inputs.property("version", project.version) + + filesMatching("fabric.mod.json") { + expand(mapOf("version" to project.version)) + } + } + + jar { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + + from(zipTree(project.project(":common").tasks.jar.get().archiveFile)) + + manifest.attributes["Main-Class"] = "net.caffeinemc.mods.sodium.desktop.LaunchWarn" + } +} \ No newline at end of file diff --git a/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/FabricInfoAccess.java b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/FabricInfoAccess.java new file mode 100644 index 0000000000..9461b1c876 --- /dev/null +++ b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/FabricInfoAccess.java @@ -0,0 +1,43 @@ +package net.caffeinemc.mods.sodium.fabric; + +import net.caffeinemc.mods.sodium.client.services.PlatformInfoAccess; +import net.fabricmc.loader.api.FabricLoader; + +import java.nio.file.Path; + +public class FabricInfoAccess implements PlatformInfoAccess { + @Override + public boolean isDevelopmentEnvironment() { + return FabricLoader.getInstance().isDevelopmentEnvironment(); + } + + @Override + public Path getGameDirectory() { + return FabricLoader.getInstance().getGameDir(); + } + + @Override + public Path getConfigDirectory() { + return FabricLoader.getInstance().getConfigDir(); + } + + @Override + public boolean isFlawlessFramesActive() { + return FlawlessFrames.isActive(); + } + + @Override + public boolean platformHasEarlyLoadingScreen() { + return false; + } + + @Override + public boolean platformUsesRefmap() { + return true; + } + + @Override + public boolean isModInLoadingList(String modId) { + return FabricLoader.getInstance().isModLoaded(modId); + } +} diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/util/FlawlessFrames.java b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/FlawlessFrames.java similarity index 96% rename from src/main/java/net/caffeinemc/mods/sodium/client/util/FlawlessFrames.java rename to fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/FlawlessFrames.java index ed42b33fca..949c3272b6 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/util/FlawlessFrames.java +++ b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/FlawlessFrames.java @@ -1,4 +1,4 @@ -package net.caffeinemc.mods.sodium.client.util; +package net.caffeinemc.mods.sodium.fabric; import net.fabricmc.loader.api.FabricLoader; @@ -12,9 +12,9 @@ * Implements the "Flawless Frames" FREX feature using which third-party mods can instruct Sodium to sacrifice * performance (even beyond the point where it can no longer achieve interactive frame rates) in exchange for * a noticeable boost to quality. - * + *

* In Sodium's case, this means waiting for all chunks to be fully updated and ready for rendering before each frame. - * + *

* See https://github.com/grondag/frex/pull/9 */ public class FlawlessFrames { diff --git a/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/MixinConfigFabric.java b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/MixinConfigFabric.java new file mode 100644 index 0000000000..42c9cd9a52 --- /dev/null +++ b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/MixinConfigFabric.java @@ -0,0 +1,40 @@ +package net.caffeinemc.mods.sodium.fabric; + +import net.caffeinemc.mods.sodium.client.data.config.MixinConfig; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; +import net.fabricmc.loader.api.metadata.CustomValue; +import net.fabricmc.loader.api.metadata.ModMetadata; + +import java.util.Map; + +public class MixinConfigFabric extends MixinConfig { + public MixinConfigFabric() { + super(); + } + + @Override + public void applyModOverrides() { + for (ModContainer container : FabricLoader.getInstance().getAllMods()) { + ModMetadata meta = container.getMetadata(); + + if (meta.containsCustomValue(JSON_KEY_SODIUM_OPTIONS)) { + CustomValue overrides = meta.getCustomValue(JSON_KEY_SODIUM_OPTIONS); + + if (overrides.getType() != CustomValue.CvType.OBJECT) { + LOGGER.warn("Mod '{}' contains invalid Sodium option overrides, ignoring", meta.getId()); + continue; + } + + for (Map.Entry entry : overrides.getAsObject()) { + if (entry.getValue().getType() != CustomValue.CvType.BOOLEAN) { + LOGGER.warn("Mod '{}' attempted to override option '{}' with an invalid value, ignoring", meta.getId(), entry.getKey()); + continue; + } + + this.applyModOverride(meta.getId(), entry.getKey(), entry.getValue().getAsBoolean()); + } + } + } + } +} diff --git a/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/SodiumFabricMod.java b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/SodiumFabricMod.java new file mode 100644 index 0000000000..1e152b4632 --- /dev/null +++ b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/SodiumFabricMod.java @@ -0,0 +1,27 @@ +package net.caffeinemc.mods.sodium.fabric; + +import net.caffeinemc.mods.sodium.client.SodiumClientMod; +import net.caffeinemc.mods.sodium.client.render.frapi.SodiumRenderer; +import net.caffeinemc.mods.sodium.fabric.texture.SpriteFinderCache; +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.renderer.v1.RendererAccess; +import net.fabricmc.fabric.api.resource.ResourceManagerHelper; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; +import net.minecraft.server.packs.PackType; + +public class SodiumFabricMod implements ClientModInitializer { + @Override + public void onInitializeClient() { + ModContainer mod = FabricLoader.getInstance() + .getModContainer("sodium") + .orElseThrow(NullPointerException::new); + + SodiumClientMod.onInitialization(mod.getMetadata().getVersion().getFriendlyString()); + + FlawlessFrames.onClientInitialization(); + + ResourceManagerHelper.get(PackType.CLIENT_RESOURCES).registerReloadListener(SpriteFinderCache.ReloadListener.INSTANCE); + RendererAccess.INSTANCE.registerRenderer(SodiumRenderer.INSTANCE); + } +} diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/SodiumPreLaunch.java b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/SodiumPreLaunch.java similarity index 93% rename from src/main/java/net/caffeinemc/mods/sodium/client/SodiumPreLaunch.java rename to fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/SodiumPreLaunch.java index b011f9a5d2..167edadf8b 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/SodiumPreLaunch.java +++ b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/SodiumPreLaunch.java @@ -1,8 +1,8 @@ -package net.caffeinemc.mods.sodium.client; +package net.caffeinemc.mods.sodium.fabric; import net.caffeinemc.mods.sodium.client.compatibility.checks.PreLaunchChecks; -import net.caffeinemc.mods.sodium.client.compatibility.workarounds.Workarounds; import net.caffeinemc.mods.sodium.client.compatibility.environment.probe.GraphicsAdapterProbe; +import net.caffeinemc.mods.sodium.client.compatibility.workarounds.Workarounds; import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint; public class SodiumPreLaunch implements PreLaunchEntrypoint { diff --git a/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/block/FabricBlockAccess.java b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/block/FabricBlockAccess.java new file mode 100644 index 0000000000..fcfd259c89 --- /dev/null +++ b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/block/FabricBlockAccess.java @@ -0,0 +1,92 @@ +package net.caffeinemc.mods.sodium.fabric.block; + +import net.caffeinemc.mods.sodium.api.util.NormI8; +import net.caffeinemc.mods.sodium.client.model.quad.ModelQuadView; +import net.caffeinemc.mods.sodium.client.services.PlatformBlockAccess; +import net.caffeinemc.mods.sodium.client.services.SodiumModelData; +import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry; +import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; +import org.jetbrains.annotations.Nullable; + +public class FabricBlockAccess implements PlatformBlockAccess { + /** + * Ported from Indigo. + * Finds mean of per-face shading factors weighted by normal components. + * Not how light actually works but the vanilla diffuse shading model is a hack to start with + * and this gives reasonable results for non-cubic surfaces in a vanilla-style renderer. + */ + private float normalShade(BlockAndTintGetter blockView, float normalX, float normalY, float normalZ, boolean hasShade) { + float sum = 0; + float div = 0; + + if (normalX > 0) { + sum += normalX * blockView.getShade(Direction.EAST, hasShade); + div += normalX; + } else if (normalX < 0) { + sum += -normalX * blockView.getShade(Direction.WEST, hasShade); + div -= normalX; + } + + if (normalY > 0) { + sum += normalY * blockView.getShade(Direction.UP, hasShade); + div += normalY; + } else if (normalY < 0) { + sum += -normalY * blockView.getShade(Direction.DOWN, hasShade); + div -= normalY; + } + + if (normalZ > 0) { + sum += normalZ * blockView.getShade(Direction.SOUTH, hasShade); + div += normalZ; + } else if (normalZ < 0) { + sum += -normalZ * blockView.getShade(Direction.NORTH, hasShade); + div -= normalZ; + } + + return sum / div; + } + + @Override + public int getLightEmission(BlockState state, BlockAndTintGetter level, BlockPos pos) { + return state.getLightEmission(); + } + + @Override + public boolean shouldSkipRender(BlockGetter level, BlockState selfState, BlockState otherState, BlockPos selfPos, BlockPos otherPos, Direction facing) { + return false; + } + + @Override + public boolean shouldShowFluidOverlay(BlockState block, BlockAndTintGetter level, BlockPos pos, FluidState fluidState) { + return FluidRenderHandlerRegistry.INSTANCE.isBlockTransparent(block.getBlock()); + } + + @Override + public @Nullable Object getBlockEntityData(BlockEntity blockEntity) { + return blockEntity.getRenderData(); + } + + @Override + public boolean platformHasBlockData() { + return true; + } + + @Override + public float getAccurateBlockShade(ModelQuadView quad, BlockAndTintGetter level, boolean shade) { + return normalShade(level, NormI8.unpackX(quad.getFaceNormal()), NormI8.unpackY(quad.getFaceNormal()), NormI8.unpackZ(quad.getFaceNormal()), shade); + } + + @Override + public TriState usesAmbientOcclusion(BakedModel model, BlockState state, SodiumModelData data, RenderType renderType, BlockAndTintGetter level, BlockPos pos) { + return model.useAmbientOcclusion() ? TriState.DEFAULT : TriState.FALSE; + } +} diff --git a/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/level/FabricLevelAccess.java b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/level/FabricLevelAccess.java new file mode 100644 index 0000000000..0c737f7c64 --- /dev/null +++ b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/level/FabricLevelAccess.java @@ -0,0 +1,54 @@ +package net.caffeinemc.mods.sodium.fabric.level; + +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.caffeinemc.mods.sodium.client.model.color.ColorProviderRegistry; +import net.caffeinemc.mods.sodium.client.model.light.LightPipelineProvider; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.FluidRenderer; +import net.caffeinemc.mods.sodium.client.services.PlatformLevelAccess; +import net.caffeinemc.mods.sodium.client.world.LevelSlice; +import net.caffeinemc.mods.sodium.fabric.render.FluidRendererImpl; +import net.minecraft.client.Camera; +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.culling.Frustum; +import net.minecraft.core.BlockPos; +import net.minecraft.core.SectionPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.chunk.LevelChunk; +import org.jetbrains.annotations.Nullable; +import org.joml.Matrix4f; + +import java.util.List; +import java.util.function.Function; + +public class FabricLevelAccess implements PlatformLevelAccess { + @Override + public FluidRenderer createPlatformFluidRenderer(ColorProviderRegistry colorRegistry, LightPipelineProvider lightPipelineProvider) { + return new FluidRendererImpl(colorRegistry, lightPipelineProvider); + } + + @Override + public boolean tryRenderFluid() { + return FluidRendererImpl.tryRenderFluid(); + } + + @Override + public void runChunkLayerEvents(RenderType renderLayer, LevelRenderer levelRenderer, Matrix4f modelMatrix, Matrix4f projectionMatrix, int ticks, Camera mainCamera, Frustum cullingFrustum) { + + } + + @Override + public List getExtraRenderers(Level level, BlockPos origin) { + return List.of(); + } + + @Override + public void renderAdditionalRenderers(List renderers, Function typeToConsumer, LevelSlice slice) { + + } + + @Override + public @Nullable Object getLightManager(LevelChunk chunk, SectionPos pos) { + return null; + } +} diff --git a/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/model/FabricModelAccess.java b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/model/FabricModelAccess.java new file mode 100644 index 0000000000..0566c84e8a --- /dev/null +++ b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/model/FabricModelAccess.java @@ -0,0 +1,50 @@ +package net.caffeinemc.mods.sodium.fabric.model; + +import it.unimi.dsi.fastutil.longs.Long2ObjectMaps; +import net.caffeinemc.mods.sodium.client.services.PlatformModelAccess; +import net.caffeinemc.mods.sodium.client.services.SodiumModelData; +import net.caffeinemc.mods.sodium.client.services.SodiumModelDataContainer; +import net.caffeinemc.mods.sodium.client.world.LevelSlice; +import net.minecraft.client.renderer.ItemBlockRenderTypes; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.SectionPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +import java.util.Collections; +import java.util.List; + +public class FabricModelAccess implements PlatformModelAccess { + private static final SodiumModelDataContainer EMPTY_CONTAINER = new SodiumModelDataContainer(Long2ObjectMaps.emptyMap()); + + @Override + public Iterable getModelRenderTypes(BlockAndTintGetter level, BakedModel model, BlockState state, BlockPos pos, RandomSource random, SodiumModelData modelData) { + return Collections.singleton(ItemBlockRenderTypes.getChunkRenderType(state)); + } + + @Override + public List getQuads(BlockAndTintGetter level, BlockPos pos, BakedModel model, BlockState state, Direction face, RandomSource random, RenderType renderType, SodiumModelData modelData) { + return model.getQuads(state, face, random); + } + + @Override + public SodiumModelDataContainer getModelDataContainer(Level level, SectionPos sectionPos) { + return EMPTY_CONTAINER; + } + + @Override + public SodiumModelData getModelData(LevelSlice slice, BakedModel model, BlockState state, BlockPos pos, SodiumModelData originalData) { + return null; + } + + @Override + public SodiumModelData getEmptyModelData() { + return null; + } +} diff --git a/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/render/FabricColorProviders.java b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/render/FabricColorProviders.java new file mode 100644 index 0000000000..a8ff796ed3 --- /dev/null +++ b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/render/FabricColorProviders.java @@ -0,0 +1,29 @@ +package net.caffeinemc.mods.sodium.fabric.render; + +import net.caffeinemc.mods.sodium.client.model.color.ColorProvider; +import net.caffeinemc.mods.sodium.client.model.quad.ModelQuadView; +import net.caffeinemc.mods.sodium.client.world.LevelSlice; +import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.material.FluidState; + +import java.util.Arrays; + +public class FabricColorProviders { + public static ColorProvider adapt(FluidRenderHandler handler) { + return new FabricFluidAdapter(handler); + } + + private static class FabricFluidAdapter implements ColorProvider { + private final FluidRenderHandler handler; + + public FabricFluidAdapter(FluidRenderHandler handler) { + this.handler = handler; + } + + @Override + public void getColors(LevelSlice slice, BlockPos pos, FluidState state, ModelQuadView quad, int[] output) { + Arrays.fill(output, this.handler.getFluidColor(slice, pos, state)); + } + } +} diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/FluidRenderer.java b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/render/FluidRendererImpl.java similarity index 73% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/FluidRenderer.java rename to fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/render/FluidRendererImpl.java index f78b7ea1f0..dd08118410 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/FluidRenderer.java +++ b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/render/FluidRendererImpl.java @@ -1,9 +1,12 @@ -package net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline; +package net.caffeinemc.mods.sodium.fabric.render; +import net.caffeinemc.mods.sodium.client.model.color.ColorProvider; import net.caffeinemc.mods.sodium.client.model.color.ColorProviderRegistry; import net.caffeinemc.mods.sodium.client.model.light.LightPipelineProvider; import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildBuffers; import net.caffeinemc.mods.sodium.client.render.chunk.compile.buffers.ChunkModelBuilder; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.DefaultFluidRenderer; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.FluidRenderer; import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.DefaultMaterials; import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.Material; import net.caffeinemc.mods.sodium.client.render.chunk.translucent_sorting.TranslucentGeometryCollector; @@ -13,24 +16,32 @@ import net.minecraft.core.BlockPos; import net.minecraft.tags.FluidTags; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.Fluids; -public class FluidRenderer { +public class FluidRendererImpl extends FluidRenderer { // The current default context is set up before invoking FluidRenderHandler#renderFluid and cleared afterwards. private static final ThreadLocal CURRENT_DEFAULT_CONTEXT = ThreadLocal.withInitial(DefaultRenderContext::new); + private final ColorProviderRegistry colorProviderRegistry; private final DefaultFluidRenderer defaultRenderer; - public FluidRenderer(ColorProviderRegistry colorProviderRegistry, LightPipelineProvider lighters) { + public FluidRendererImpl(ColorProviderRegistry colorProviderRegistry, LightPipelineProvider lighters) { + this.colorProviderRegistry = colorProviderRegistry; defaultRenderer = new DefaultFluidRenderer(colorProviderRegistry, lighters); } + public static boolean tryRenderFluid() { + return CURRENT_DEFAULT_CONTEXT.get().renderIfSetUp(); + } + public void render(LevelSlice level, BlockState blockState, FluidState fluidState, BlockPos blockPos, BlockPos offset, TranslucentGeometryCollector collector, ChunkBuildBuffers buffers) { var material = DefaultMaterials.forFluidState(fluidState); var meshBuilder = buffers.get(material); FluidRenderHandler handler = FluidRenderHandlerRegistry.INSTANCE.get(fluidState.getType()); + boolean hasModOverride = FluidRenderHandlerRegistry.INSTANCE.getOverride(fluidState.getType()) != null; // Match the vanilla FluidRenderer's behavior if the handler is null if (handler == null) { @@ -60,7 +71,7 @@ public void render(LevelSlice level, BlockState blockState, FluidState fluidStat // parameters are bundled into a DefaultRenderContext which is stored in a ThreadLocal. DefaultRenderContext defaultContext = CURRENT_DEFAULT_CONTEXT.get(); - defaultContext.setUp(this.defaultRenderer, level, fluidState, blockPos, offset, collector, meshBuilder, material, handler); + defaultContext.setUp(this.colorProviderRegistry, this.defaultRenderer, level, fluidState, blockPos, offset, collector, meshBuilder, material, handler, hasModOverride); try { handler.renderFluid(blockPos, level, meshBuilder.asFallbackVertexConsumer(material, collector), blockState, fluidState); @@ -69,10 +80,6 @@ public void render(LevelSlice level, BlockState blockState, FluidState fluidStat } } - public static boolean renderFromVanilla() { - return CURRENT_DEFAULT_CONTEXT.get().renderIfSetUp(); - } - private static class DefaultRenderContext { private DefaultFluidRenderer renderer; private LevelSlice level; @@ -83,8 +90,11 @@ private static class DefaultRenderContext { private ChunkModelBuilder meshBuilder; private Material material; private FluidRenderHandler handler; + private ColorProviderRegistry colorProviderRegistry; + private boolean hasModOverride; - public void setUp(DefaultFluidRenderer renderer, LevelSlice level, FluidState fluidState, BlockPos blockPos, BlockPos offset, TranslucentGeometryCollector collector, ChunkModelBuilder meshBuilder, Material material, FluidRenderHandler handler) { + public void setUp(ColorProviderRegistry colorProviderRegistry, DefaultFluidRenderer renderer, LevelSlice level, FluidState fluidState, BlockPos blockPos, BlockPos offset, TranslucentGeometryCollector collector, ChunkModelBuilder meshBuilder, Material material, FluidRenderHandler handler, boolean hasModOverride) { + this.colorProviderRegistry = colorProviderRegistry; this.renderer = renderer; this.level = level; this.fluidState = fluidState; @@ -94,6 +104,7 @@ public void setUp(DefaultFluidRenderer renderer, LevelSlice level, FluidState fl this.meshBuilder = meshBuilder; this.material = material; this.handler = handler; + this.hasModOverride = hasModOverride; } public void clear() { @@ -106,11 +117,23 @@ public void clear() { this.meshBuilder = null; this.material = null; this.handler = null; + this.hasModOverride = false; + } + + public ColorProvider getColorProvider(Fluid fluid) { + var override = this.colorProviderRegistry.getColorProvider(fluid); + + if (!hasModOverride && override != null) { + return override; + } + + return FabricColorProviders.adapt(handler); } public boolean renderIfSetUp() { if (this.renderer != null) { - this.renderer.render(this.level, this.fluidState, this.blockPos, this.offset, this.collector, this.meshBuilder, this.material, this.handler); + this.renderer.render(this.level, this.fluidState, this.blockPos, this.offset, this.collector, this.meshBuilder, this.material, + getColorProvider(fluidState.getType()), handler.getFluidSprites(this.level, this.blockPos, this.fluidState)); return true; } diff --git a/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/texture/FabricTextureAccess.java b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/texture/FabricTextureAccess.java new file mode 100644 index 0000000000..4599800b3f --- /dev/null +++ b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/texture/FabricTextureAccess.java @@ -0,0 +1,11 @@ +package net.caffeinemc.mods.sodium.fabric.texture; + +import net.caffeinemc.mods.sodium.client.services.PlatformTextureAccess; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; + +public class FabricTextureAccess implements PlatformTextureAccess { + @Override + public TextureAtlasSprite findInBlockAtlas(float texU, float texV) { + return SpriteFinderCache.forBlockAtlas().find(texU, texV); + } +} diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/SpriteFinderCache.java b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/texture/SpriteFinderCache.java similarity index 85% rename from src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/SpriteFinderCache.java rename to fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/texture/SpriteFinderCache.java index 8115cfcb56..81bab135a4 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/client/render/frapi/SpriteFinderCache.java +++ b/fabric/src/main/java/net/caffeinemc/mods/sodium/fabric/texture/SpriteFinderCache.java @@ -1,6 +1,7 @@ -package net.caffeinemc.mods.sodium.client.render.frapi; +package net.caffeinemc.mods.sodium.fabric.texture; import net.fabricmc.fabric.api.renderer.v1.model.SpriteFinder; +import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener; import net.fabricmc.fabric.api.resource.ResourceReloadListenerKeys; import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener; import net.minecraft.client.Minecraft; @@ -8,6 +9,7 @@ import net.minecraft.client.resources.model.ModelManager; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.ResourceManagerReloadListener; import java.util.Collection; import java.util.List; @@ -24,7 +26,7 @@ public static SpriteFinder forBlockAtlas() { return blockAtlasSpriteFinder; } - public static class ReloadListener implements SimpleSynchronousResourceReloadListener { + public static class ReloadListener implements ResourceManagerReloadListener, IdentifiableResourceReloadListener { public static final ResourceLocation ID = ResourceLocation.fromNamespaceAndPath("sodium", "sprite_finder_cache"); public static final List DEPENDENCIES = List.of(ResourceReloadListenerKeys.MODELS); public static final ReloadListener INSTANCE = new ReloadListener(); diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/model/quad/BakedQuadMixin.java b/fabric/src/main/java/net/caffeinemc/mods/sodium/mixin/fabric/core/model/quad/BakedQuadMixin.java similarity index 88% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/core/model/quad/BakedQuadMixin.java rename to fabric/src/main/java/net/caffeinemc/mods/sodium/mixin/fabric/core/model/quad/BakedQuadMixin.java index bfbe01de72..bed6b8dec2 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/core/model/quad/BakedQuadMixin.java +++ b/fabric/src/main/java/net/caffeinemc/mods/sodium/mixin/fabric/core/model/quad/BakedQuadMixin.java @@ -1,4 +1,4 @@ -package net.caffeinemc.mods.sodium.mixin.core.model.quad; +package net.caffeinemc.mods.sodium.mixin.fabric.core.model.quad; import net.caffeinemc.mods.sodium.client.model.quad.BakedQuadView; import net.caffeinemc.mods.sodium.client.model.quad.properties.ModelQuadFacing; @@ -44,7 +44,7 @@ public class BakedQuadMixin implements BakedQuadView { private int normal; @Unique - private ModelQuadFacing normalFace; + private ModelQuadFacing normalFace = null; @Inject(method = "", at = @At("RETURN")) private void init(int[] vertexData, int colorIndex, Direction face, TextureAtlasSprite sprite, boolean shade, CallbackInfo ci) { @@ -74,6 +74,16 @@ public int getColor(int idx) { return this.vertices[ModelQuadUtil.vertexOffset(idx) + ModelQuadUtil.COLOR_INDEX]; } + @Override + public int getVertexNormal(int idx) { + return this.vertices[ModelQuadUtil.vertexOffset(idx) + ModelQuadUtil.NORMAL_INDEX]; + } + + @Override + public int getLight(int idx) { + return this.vertices[ModelQuadUtil.vertexOffset(idx) + ModelQuadUtil.LIGHT_INDEX]; + } + @Override public TextureAtlasSprite getSprite() { return this.sprite; @@ -105,7 +115,7 @@ public ModelQuadFacing getNormalFace() { } @Override - public int getNormal() { + public int getFaceNormal() { return this.normal; } diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/model/MultiPartBakedModelMixin.java b/fabric/src/main/java/net/caffeinemc/mods/sodium/mixin/fabric/features/model/MultiPartBakedModelMixin.java similarity index 93% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/model/MultiPartBakedModelMixin.java rename to fabric/src/main/java/net/caffeinemc/mods/sodium/mixin/fabric/features/model/MultiPartBakedModelMixin.java index 6fd0ea0ed2..af83f38319 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/model/MultiPartBakedModelMixin.java +++ b/fabric/src/main/java/net/caffeinemc/mods/sodium/mixin/fabric/features/model/MultiPartBakedModelMixin.java @@ -1,18 +1,21 @@ -package net.caffeinemc.mods.sodium.mixin.features.model; +package net.caffeinemc.mods.sodium.mixin.fabric.features.model; import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; -import org.apache.commons.lang3.tuple.Pair; -import org.spongepowered.asm.mixin.*; - -import java.util.*; -import java.util.concurrent.locks.StampedLock; -import java.util.function.Predicate; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.MultiPartBakedModel; import net.minecraft.core.Direction; import net.minecraft.util.RandomSource; import net.minecraft.world.level.block.state.BlockState; +import org.apache.commons.lang3.tuple.Pair; +import org.spongepowered.asm.mixin.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.locks.StampedLock; +import java.util.function.Predicate; @Mixin(MultiPartBakedModel.class) public class MultiPartBakedModelMixin { diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/model/WeightedBakedModelMixin.java b/fabric/src/main/java/net/caffeinemc/mods/sodium/mixin/fabric/features/model/WeightedBakedModelMixin.java similarity index 93% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/model/WeightedBakedModelMixin.java rename to fabric/src/main/java/net/caffeinemc/mods/sodium/mixin/fabric/features/model/WeightedBakedModelMixin.java index b987fa6dea..41bef68758 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/model/WeightedBakedModelMixin.java +++ b/fabric/src/main/java/net/caffeinemc/mods/sodium/mixin/fabric/features/model/WeightedBakedModelMixin.java @@ -1,9 +1,5 @@ -package net.caffeinemc.mods.sodium.mixin.features.model; +package net.caffeinemc.mods.sodium.mixin.fabric.features.model; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.*; - -import java.util.*; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.WeightedBakedModel; @@ -11,6 +7,11 @@ import net.minecraft.util.RandomSource; import net.minecraft.util.random.WeightedEntry; import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.*; + +import java.util.Collections; +import java.util.List; @Mixin(WeightedBakedModel.class) public class WeightedBakedModelMixin { @@ -22,22 +23,6 @@ public class WeightedBakedModelMixin { @Final private int totalWeight; - /** - * @author JellySquid - * @reason Avoid excessive object allocations - */ - @Overwrite - public List getQuads(@Nullable BlockState state, @Nullable Direction face, RandomSource random) { - WeightedEntry.Wrapper quad = getAt(this.list, Math.abs((int) random.nextLong()) % this.totalWeight); - - if (quad != null) { - return quad.data() - .getQuads(state, face, random); - } - - return Collections.emptyList(); - } - @Unique private static T getAt(List pool, int totalWeight) { int i = 0; @@ -56,4 +41,20 @@ private static T getAt(List pool, int totalWeight) return weighted; } + + /** + * @author JellySquid + * @reason Avoid excessive object allocations + */ + @Overwrite + public List getQuads(@Nullable BlockState state, @Nullable Direction face, RandomSource random) { + WeightedEntry.Wrapper quad = getAt(this.list, Math.abs((int) random.nextLong()) % this.totalWeight); + + if (quad != null) { + return quad.data() + .getQuads(state, face, random); + } + + return Collections.emptyList(); + } } diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/model/block/ModelBlockRendererMixin.java b/fabric/src/main/java/net/caffeinemc/mods/sodium/mixin/fabric/features/render/model/block/ModelBlockRendererMixin.java similarity index 90% rename from src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/model/block/ModelBlockRendererMixin.java rename to fabric/src/main/java/net/caffeinemc/mods/sodium/mixin/fabric/features/render/model/block/ModelBlockRendererMixin.java index 121c85d2ee..59240cbb4b 100644 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/model/block/ModelBlockRendererMixin.java +++ b/fabric/src/main/java/net/caffeinemc/mods/sodium/mixin/fabric/features/render/model/block/ModelBlockRendererMixin.java @@ -1,12 +1,14 @@ -package net.caffeinemc.mods.sodium.mixin.features.render.model.block; +package net.caffeinemc.mods.sodium.mixin.fabric.features.render.model.block; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.caffeinemc.mods.sodium.api.util.ColorABGR; +import net.caffeinemc.mods.sodium.api.vertex.buffer.VertexBufferWriter; import net.caffeinemc.mods.sodium.client.model.quad.BakedQuadView; import net.caffeinemc.mods.sodium.client.render.immediate.model.BakedModelEncoder; import net.caffeinemc.mods.sodium.client.render.texture.SpriteUtil; import net.caffeinemc.mods.sodium.client.render.vertex.VertexConsumerUtils; import net.caffeinemc.mods.sodium.client.util.DirectionUtil; -import net.caffeinemc.mods.sodium.api.util.ColorABGR; -import net.caffeinemc.mods.sodium.api.vertex.buffer.VertexBufferWriter; import net.minecraft.client.renderer.block.ModelBlockRenderer; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.resources.model.BakedModel; @@ -20,8 +22,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; + import java.util.List; @Mixin(ModelBlockRenderer.class) @@ -29,14 +30,34 @@ public class ModelBlockRendererMixin { @Unique private final RandomSource random = new SingleThreadedRandomSource(42L); + @Unique + @SuppressWarnings("ForLoopReplaceableByForEach") + private static void renderQuads(PoseStack.Pose matrices, VertexBufferWriter writer, int defaultColor, List quads, int light, int overlay) { + for (int i = 0; i < quads.size(); i++) { + BakedQuad bakedQuad = quads.get(i); + + if (bakedQuad.getVertices().length < 32) { + continue; // ignore bad quads + } + + BakedQuadView quad = (BakedQuadView) bakedQuad; + + int color = quad.hasColor() ? defaultColor : 0xFFFFFFFF; + + BakedModelEncoder.writeQuadVertices(writer, matrices, quad, color, light, overlay); + + SpriteUtil.markSpriteActive(quad.getSprite()); + } + } + /** * @reason Use optimized vertex writer intrinsics, avoid allocations * @author JellySquid */ - @Inject(method = "renderModel(Lcom/mojang/blaze3d/vertex/PoseStack$Pose;Lcom/mojang/blaze3d/vertex/VertexConsumer;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/client/resources/model/BakedModel;FFFII)V", at = @At("HEAD"), cancellable = true) + @Inject(method = "renderModel", at = @At("HEAD"), cancellable = true) private void renderFast(PoseStack.Pose entry, VertexConsumer vertexConsumer, BlockState blockState, BakedModel bakedModel, float red, float green, float blue, int light, int overlay, CallbackInfo ci) { var writer = VertexConsumerUtils.convertOrLog(vertexConsumer); - if(writer == null) { + if (writer == null) { return; } @@ -67,24 +88,4 @@ private void renderFast(PoseStack.Pose entry, VertexConsumer vertexConsumer, Blo renderQuads(entry, writer, defaultColor, quads, light, overlay); } } - - @Unique - @SuppressWarnings("ForLoopReplaceableByForEach") - private static void renderQuads(PoseStack.Pose matrices, VertexBufferWriter writer, int defaultColor, List quads, int light, int overlay) { - for (int i = 0; i < quads.size(); i++) { - BakedQuad bakedQuad = quads.get(i); - - if (bakedQuad.getVertices().length < 32) { - continue; // ignore bad quads - } - - BakedQuadView quad = (BakedQuadView) bakedQuad; - - int color = quad.hasColor() ? defaultColor : 0xFFFFFFFF; - - BakedModelEncoder.writeQuadVertices(writer, matrices, quad, color, light, overlay); - - SpriteUtil.markSpriteActive(quad.getSprite()); - } - } } diff --git a/fabric/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.data.config.MixinConfig b/fabric/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.data.config.MixinConfig new file mode 100644 index 0000000000..fc0d19a72e --- /dev/null +++ b/fabric/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.data.config.MixinConfig @@ -0,0 +1 @@ +net.caffeinemc.mods.sodium.fabric.MixinConfigFabric \ No newline at end of file diff --git a/fabric/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformBlockAccess b/fabric/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformBlockAccess new file mode 100644 index 0000000000..d5c344c89f --- /dev/null +++ b/fabric/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformBlockAccess @@ -0,0 +1 @@ +net.caffeinemc.mods.sodium.fabric.block.FabricBlockAccess \ No newline at end of file diff --git a/fabric/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformInfoAccess b/fabric/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformInfoAccess new file mode 100644 index 0000000000..af48e761ac --- /dev/null +++ b/fabric/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformInfoAccess @@ -0,0 +1 @@ +net.caffeinemc.mods.sodium.fabric.FabricInfoAccess \ No newline at end of file diff --git a/fabric/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformLevelAccess b/fabric/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformLevelAccess new file mode 100644 index 0000000000..194bf9fe8d --- /dev/null +++ b/fabric/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformLevelAccess @@ -0,0 +1 @@ +net.caffeinemc.mods.sodium.fabric.level.FabricLevelAccess \ No newline at end of file diff --git a/fabric/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformModelAccess b/fabric/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformModelAccess new file mode 100644 index 0000000000..d19ccea5a2 --- /dev/null +++ b/fabric/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformModelAccess @@ -0,0 +1 @@ +net.caffeinemc.mods.sodium.fabric.model.FabricModelAccess \ No newline at end of file diff --git a/fabric/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformTextureAccess b/fabric/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformTextureAccess new file mode 100644 index 0000000000..59fc70d083 --- /dev/null +++ b/fabric/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformTextureAccess @@ -0,0 +1 @@ +net.caffeinemc.mods.sodium.fabric.texture.FabricTextureAccess \ No newline at end of file diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json new file mode 100644 index 0000000000..1c7a84a3cb --- /dev/null +++ b/fabric/src/main/resources/fabric.mod.json @@ -0,0 +1,108 @@ +{ + "schemaVersion" : 1, + "id" : "sodium", + "version" : "${version}", + "name" : "Sodium", + "description" : "Sodium is a powerful rendering engine for Minecraft which greatly improves frame rates and micro-stutter, while fixing many graphical issues", + "authors" : [ + { + "name" : "@jellysquid3", + "contact" : { + "email" : "jellysquid@pm.me", + "homepage" : "https://jellysquid.me" + } + } + ], + "contributors" : [ + "@IMS212", + "@bytzo", + "@PepperCode1", + "@FlashyReese", + "@altrisi", + "@Grayray75", + "@Madis0", + "@Johni0702", + "@comp500", + "@coderbot16", + "@Moulberry", + "@MCRcortex", + "@Altirix", + "@embeddedt", + "@pajicadvance", + "@Kroppeb", + "@douira", + "@burgerindividual", + "@TwistedZero", + "@Leo40Git", + "@haykam821" + ], + "contact" : { + "homepage" : "https://github.com/CaffeineMC/sodium-fabric", + "sources" : "https://github.com/CaffeineMC/sodium-fabric", + "issues" : "https://github.com/CaffeineMC/sodium-fabric/issues" + }, + "license" : "Polyform-Shield-1.0.0", + "icon" : "sodium-icon.png", + "environment" : "client", + "entrypoints" : { + "client" : [ + "net.caffeinemc.mods.sodium.fabric.SodiumFabricMod" + ], + "preLaunch" : [ + "net.caffeinemc.mods.sodium.fabric.SodiumPreLaunch" + ] + }, + "custom" : { + "fabric-renderer-api-v1:contains_renderer" : true, + "modmenu" : { + "links" : { + "modmenu.donate" : "https://caffeinemc.net/donate", + "modmenu.discord" : "https://caffeinemc.net/discord", + "modmenu.github_releases" : "https://github.com/CaffeineMC/sodium-fabric/releases", + "modmenu.kofi" : "https://caffeinemc.net/donate", + "modmenu.modrinth" : "https://modrinth.com/mod/sodium" + } + } + }, + "accessWidener" : "sodium.accesswidener", + "mixins" : [ + "sodium.mixins.json", + "sodium-fabric.mixins.json" + ], + "depends" : { + "fabricloader" : ">=0.12.0", + "fabric-block-view-api-v2" : "*", + "fabric-renderer-api-v1" : "*", + "fabric-rendering-data-attachment-v1" : "*", + "fabric-rendering-fluids-v1" : ">=2.0.0", + "fabric-resource-loader-v0" : "*" + }, + "breaks" : { + "embeddium": "*", + "optifabric" : "*", + "canvas" : "*", + "sodium-blendingregistry" : "*", + "ocrenderfix_sodium" : "*", + "betterfpsdist" : "<1.20.1-3.8", + "bobby" : "<5.0.1", + "cauldron_dyeing" : "<1.0.11", + "cullleaves" : "<=3.1.0", + "custom_hud" : "<=3.1.0+1.20", + "dashloader" : "<5.0.0-beta.2", + "farsight" : "<1.20.1-4.0", + "fluidvoidfading" : "<1.1.2", + "iceberg" : "<1.1.14", + "iris" : "<=1.6.14", + "immersive_portals" : "<=5.1.3", + "notenoughcrashes" : "<4.4.6", + "noxesium" : "<1.0.2", + "rayon" : "<=1.7.2+1.20.1", + "reeses-sodium-options" : "<1.7.1", + "sodium-extra" : "<0.5.4", + "sspb" : "<3.2.0", + "supplementaries" : "<=1.20-2.7.32" + }, + "provides" : [ + "indium" + ] +} diff --git a/fabric/src/main/resources/sodium-fabric.mixins.json b/fabric/src/main/resources/sodium-fabric.mixins.json new file mode 100644 index 0000000000..f27a82fd62 --- /dev/null +++ b/fabric/src/main/resources/sodium-fabric.mixins.json @@ -0,0 +1,18 @@ +{ + "package": "net.caffeinemc.mods.sodium.mixin.fabric", + "required": true, + "compatibilityLevel": "JAVA_17", + "refmap": "sodium-fabric.refmap.json", + "injectors": { + "defaultRequire": 1 + }, + "overwrites": { + "conformVisibility": true + }, + "client": [ + "core.model.quad.BakedQuadMixin", + "features.model.MultiPartBakedModelMixin", + "features.model.WeightedBakedModelMixin", + "features.render.model.block.ModelBlockRendererMixin" + ] +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 35f5ac1b0e..3a82e5ed65 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,4 @@ # Done to increase the memory available to gradle. -org.gradle.jvmargs=-Xmx2G \ No newline at end of file +org.gradle.jvmargs=-Xmx2G +org.gradle.caching=true +org.gradle.parallel=true \ No newline at end of file diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts new file mode 100644 index 0000000000..1d46b8eded --- /dev/null +++ b/neoforge/build.gradle.kts @@ -0,0 +1,156 @@ +plugins { + id("idea") + id("net.neoforged.moddev") version "1.0.15" + id("java-library") +} + +val MINECRAFT_VERSION: String by rootProject.extra +val PARCHMENT_VERSION: String? by rootProject.extra +val NEOFORGE_VERSION: String by rootProject.extra +val MOD_VERSION: String by rootProject.extra + +base { + archivesName = "sodium-neoforge" +} + +sourceSets { + val service = create("service") + + service.apply { + compileClasspath += main.get().compileClasspath + compileClasspath += project(":common").sourceSets.getByName("workarounds").output + } + + main.get().apply { + compileClasspath += project(":common").sourceSets.getByName("workarounds").output + runtimeClasspath += project(":common").sourceSets.getByName("workarounds").output + } +} + +repositories { + maven("https://maven.pkg.github.com/ims212/Forge_Fabric_API") { + credentials { + username = "IMS212" + // Read only token + password = "ghp_" + "DEuGv0Z56vnSOYKLCXdsS9svK4nb9K39C1Hn" + } + } + maven("https://maven.su5ed.dev/releases") + maven("https://maven.neoforged.net/releases/") + + exclusiveContent { + forRepository { + maven { + name = "Modrinth" + url = uri("https://api.modrinth.com/maven") + } + } + filter { + includeGroup("maven.modrinth") + } + } +} + +val serviceJar: Jar by tasks.creating(Jar::class) { + from(sourceSets.getByName("service").output) + from(project(":common").sourceSets.getByName("workarounds").output) + from(rootDir.resolve("LICENSE.md")) + manifest.attributes["FMLModType"] = "LIBRARY" + archiveClassifier = "service" +} + +configurations { + create("serviceConfig") { + isCanBeConsumed = true + isCanBeResolved = false + outgoing { + artifact(serviceJar) + } + } +} + +dependencies { + jarJar(project(":neoforge", "serviceConfig")) +} + +tasks.jar { + val api = project.project(":common").sourceSets.getByName("api") + from(api.output.classesDirs) + from(api.output.resourcesDir) + + val main = project.project(":common").sourceSets.getByName("main") + from(main.output.classesDirs) { + exclude("/sodium.refmap.json") + } + from(main.output.resourcesDir) + + val desktop = project.project(":common").sourceSets.getByName("desktop") + from(desktop.output.classesDirs) + from(desktop.output.resourcesDir) + + from(rootDir.resolve("LICENSE.md")) + + filesMatching("neoforge.mods.toml") { + expand(mapOf("version" to MOD_VERSION)) + } + + manifest.attributes["Main-Class"] = "net.caffeinemc.mods.sodium.desktop.LaunchWarn" +} + +neoForge { + // Specify the version of NeoForge to use. + version = NEOFORGE_VERSION + + parchment { + mappingsVersion = PARCHMENT_VERSION + minecraftVersion = MINECRAFT_VERSION + } + + runs { + create("client") { + client() + } + } + + mods { + create("sodium") { + sourceSet(sourceSets.main.get()) + sourceSet(project.project(":common").sourceSets.main.get()) + sourceSet(project.project(":common").sourceSets.getByName("api")) + } + + create("sodiumservice") { + sourceSet(sourceSets["service"]) + sourceSet(project(":common").sourceSets["workarounds"]) + } + } +} + +fun includeDep(dependency: String, closure: Action) { + dependencies.implementation(dependency, closure) + dependencies.jarJar(dependency, closure) +} + +fun includeDep(dependency: String) { + dependencies.implementation(dependency) + dependencies.jarJar(dependency) +} + +tasks.named("compileTestJava").configure { + enabled = false +} + +dependencies { + compileOnly(project.project(":common").sourceSets.main.get().output) + compileOnly(project.project(":common").sourceSets.getByName("api").output) + includeDep("org.sinytra.forgified-fabric-api:fabric-api-base:0.4.42+d1308dedd1") + includeDep("org.sinytra.forgified-fabric-api:fabric-renderer-api-v1:3.3.0+e3455cb4d1") + includeDep("net.fabricmc:fabric_rendering_data_attachment_v1:0.3.46+${MINECRAFT_VERSION}") { + isTransitive = false + } + includeDep("org.sinytra.forgified-fabric-api:fabric-block-view-api-v2:1.0.10+9afaaf8cd1") + includeDep("com.lodborg:interval-tree:1.0.0") + additionalRuntimeClasspath("com.lodborg:interval-tree:1.0.0") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(21) \ No newline at end of file diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/MixinConfigImpl.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/MixinConfigImpl.java new file mode 100644 index 0000000000..799a5fe9dc --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/MixinConfigImpl.java @@ -0,0 +1,33 @@ +package net.caffeinemc.mods.sodium.neoforge; + +import net.caffeinemc.mods.sodium.client.data.config.MixinConfig; +import net.neoforged.fml.loading.FMLLoader; +import net.neoforged.fml.loading.moddiscovery.ModInfo; + +import java.util.Map; + +public class MixinConfigImpl extends MixinConfig { + public MixinConfigImpl() { + super(); + } + + @Override + public void applyModOverrides() { + for (ModInfo meta : FMLLoader.getLoadingModList().getMods()) { + meta.getConfigElement(JSON_KEY_SODIUM_OPTIONS).ifPresent(override -> { + if (override instanceof Map overrides && overrides.keySet().stream().allMatch(key -> key instanceof String)) { + overrides.forEach((key, value) -> { + if (!(value instanceof Boolean) || !(key instanceof String)) { + LOGGER.warn("Mod '{}' attempted to override option '{}' with an invalid value, ignoring", meta.getModId(), key); + return; + } + + this.applyModOverride(meta.getModId(), (String) key, (Boolean) value); + }); + } else { + LOGGER.warn("Mod '{}' contains invalid Sodium option overrides, ignoring", meta.getModId()); + } + }); + } + } +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/NeoForgeInfoAccess.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/NeoForgeInfoAccess.java new file mode 100644 index 0000000000..bbe1143435 --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/NeoForgeInfoAccess.java @@ -0,0 +1,46 @@ +package net.caffeinemc.mods.sodium.neoforge; + +import net.caffeinemc.mods.sodium.client.services.PlatformInfoAccess; +import net.neoforged.fml.loading.FMLConfig; +import net.neoforged.fml.loading.FMLLoader; +import net.neoforged.fml.loading.FMLPaths; +import net.neoforged.fml.loading.LoadingModList; + +import java.nio.file.Path; + +public class NeoForgeInfoAccess implements PlatformInfoAccess { + @Override + public boolean isDevelopmentEnvironment() { + return !FMLLoader.isProduction(); + } + + @Override + public Path getGameDirectory() { + return FMLPaths.GAMEDIR.get(); + } + + @Override + public Path getConfigDirectory() { + return FMLPaths.CONFIGDIR.get(); + } + + @Override + public boolean isFlawlessFramesActive() { + return false; + } + + @Override + public boolean platformHasEarlyLoadingScreen() { + return FMLConfig.getBoolConfigValue(FMLConfig.ConfigValue.EARLY_WINDOW_CONTROL); + } + + @Override + public boolean platformUsesRefmap() { + return false; + } + + @Override + public boolean isModInLoadingList(String modId) { + return LoadingModList.get().getModFileById(modId) != null; + } +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/SodiumForgeMod.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/SodiumForgeMod.java new file mode 100644 index 0000000000..4409e5522d --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/SodiumForgeMod.java @@ -0,0 +1,28 @@ +package net.caffeinemc.mods.sodium.neoforge; + +import net.caffeinemc.mods.sodium.client.SodiumClientMod; +import net.caffeinemc.mods.sodium.client.gui.SodiumOptionsGUI; +import net.caffeinemc.mods.sodium.client.render.frapi.SodiumRenderer; +import net.caffeinemc.mods.sodium.neoforge.texture.SpriteFinderCache; +import net.fabricmc.fabric.api.renderer.v1.RendererAccess; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.fml.ModContainer; +import net.neoforged.fml.ModList; +import net.neoforged.fml.ModLoadingContext; +import net.neoforged.fml.common.Mod; +import net.neoforged.neoforge.client.event.RegisterClientReloadListenersEvent; +import net.neoforged.neoforge.client.gui.IConfigScreenFactory; + +@Mod("sodium") +public class SodiumForgeMod { + public SodiumForgeMod(IEventBus bus, ModContainer modContainer) { + SodiumClientMod.onInitialization(ModList.get().getModContainerById("sodium").orElseThrow().getModInfo().getVersion().toString()); + bus.addListener(this::onResourceReload); + modContainer.registerExtensionPoint(IConfigScreenFactory.class, (minecraft, screen) -> SodiumOptionsGUI.createScreen(screen)); + RendererAccess.INSTANCE.registerRenderer(SodiumRenderer.INSTANCE); + } + + public void onResourceReload(RegisterClientReloadListenersEvent event) { + event.registerReloadListener(SpriteFinderCache.ReloadListener.INSTANCE); + } +} \ No newline at end of file diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/block/NeoForgeBlockAccess.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/block/NeoForgeBlockAccess.java new file mode 100644 index 0000000000..229cedaed6 --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/block/NeoForgeBlockAccess.java @@ -0,0 +1,62 @@ +package net.caffeinemc.mods.sodium.neoforge.block; + +import net.caffeinemc.mods.sodium.api.util.NormI8; +import net.caffeinemc.mods.sodium.client.model.quad.ModelQuadView; +import net.caffeinemc.mods.sodium.client.services.PlatformBlockAccess; +import net.caffeinemc.mods.sodium.client.services.SodiumModelData; +import net.caffeinemc.mods.sodium.client.util.DirectionUtil; +import net.fabricmc.fabric.api.util.TriState; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; +import net.neoforged.neoforge.client.model.data.ModelData; +import org.jetbrains.annotations.Nullable; + +public class NeoForgeBlockAccess implements PlatformBlockAccess { + private static final TriState[] TRI_STATES = new TriState[] { + TriState.TRUE, + TriState.DEFAULT, + TriState.FALSE + }; + + @Override + public int getLightEmission(BlockState state, BlockAndTintGetter level, BlockPos pos) { + return state.getLightEmission(level, pos); + } + + @Override + public boolean shouldSkipRender(BlockGetter level, BlockState selfState, BlockState otherState, BlockPos selfPos, BlockPos otherPos, Direction facing) { + return (otherState.hidesNeighborFace(level, otherPos, selfState, DirectionUtil.getOpposite(facing))) && selfState.supportsExternalFaceHiding(); + } + + @Override + public boolean shouldShowFluidOverlay(BlockState block, BlockAndTintGetter level, BlockPos pos, FluidState fluidState) { + return block.shouldDisplayFluidOverlay(level, pos, fluidState); + } + + @Override + public @Nullable Object getBlockEntityData(BlockEntity blockEntity) { + return null; + } + + @Override + public boolean platformHasBlockData() { + return false; + } + + @Override + public float getAccurateBlockShade(ModelQuadView quad, BlockAndTintGetter level, boolean shade) { + return level.getShade(NormI8.unpackX(quad.getFaceNormal()), NormI8.unpackY(quad.getFaceNormal()), NormI8.unpackZ(quad.getFaceNormal()), shade); + } + + @Override + public TriState usesAmbientOcclusion(BakedModel model, BlockState state, SodiumModelData data, RenderType renderType, BlockAndTintGetter level, BlockPos pos) { + return TRI_STATES[model.useAmbientOcclusion(state, (ModelData) (Object) data, renderType).ordinal()]; + } +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/level/NeoForgeLevelAccess.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/level/NeoForgeLevelAccess.java new file mode 100644 index 0000000000..34fe1f3795 --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/level/NeoForgeLevelAccess.java @@ -0,0 +1,62 @@ +package net.caffeinemc.mods.sodium.neoforge.level; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.caffeinemc.mods.sodium.client.model.color.ColorProviderRegistry; +import net.caffeinemc.mods.sodium.client.model.light.LightPipelineProvider; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.FluidRenderer; +import net.caffeinemc.mods.sodium.client.services.PlatformLevelAccess; +import net.caffeinemc.mods.sodium.client.world.LevelSlice; +import net.caffeinemc.mods.sodium.neoforge.render.FluidRendererImpl; +import net.minecraft.client.Camera; +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.culling.Frustum; +import net.minecraft.core.BlockPos; +import net.minecraft.core.SectionPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.chunk.LevelChunk; +import net.neoforged.neoforge.client.ClientHooks; +import net.neoforged.neoforge.client.event.AddSectionGeometryEvent; +import org.jetbrains.annotations.Nullable; +import org.joml.Matrix4f; + +import java.util.List; +import java.util.function.Function; + +public class NeoForgeLevelAccess implements PlatformLevelAccess { + private static final ThreadLocal emptyStack = ThreadLocal.withInitial(PoseStack::new); + + @Override + public FluidRenderer createPlatformFluidRenderer(ColorProviderRegistry colorRegistry, LightPipelineProvider lightPipelineProvider) { + return new FluidRendererImpl(colorRegistry, lightPipelineProvider); + } + + @Override + public boolean tryRenderFluid() { + return false; + } + + @Override + public void runChunkLayerEvents(RenderType renderType, LevelRenderer levelRenderer, Matrix4f modelMatrix, Matrix4f projectionMatrix, int renderTick, Camera camera, Frustum frustum) { + ClientHooks.dispatchRenderStage(renderType, levelRenderer, modelMatrix, projectionMatrix, renderTick, camera, frustum); + } + + @Override + public List getExtraRenderers(Level level, BlockPos origin) { + return ClientHooks.gatherAdditionalRenderers(origin, level); + } + + @Override + public void renderAdditionalRenderers(List renderers, Function typeToConsumer, LevelSlice slice) { + AddSectionGeometryEvent.SectionRenderingContext context = new AddSectionGeometryEvent.SectionRenderingContext(typeToConsumer, slice, emptyStack.get()); + for (Object o : renderers) { + ((AddSectionGeometryEvent.AdditionalSectionRenderer) o).render(context); + } + } + + @Override + public @Nullable Object getLightManager(LevelChunk chunk, SectionPos pos) { + return chunk.getAuxLightManager(pos.origin()); + } +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/AbstractBlockRenderContextMixin.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/AbstractBlockRenderContextMixin.java new file mode 100644 index 0000000000..7aa798c3c1 --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/AbstractBlockRenderContextMixin.java @@ -0,0 +1,28 @@ +package net.caffeinemc.mods.sodium.neoforge.mixin; + +import net.caffeinemc.mods.sodium.client.render.frapi.render.AbstractBlockRenderContext; +import net.caffeinemc.mods.sodium.client.services.SodiumModelData; +import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; +import net.minecraft.client.renderer.RenderType; +import net.neoforged.neoforge.client.model.data.ModelData; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(AbstractBlockRenderContext.class) +public abstract class AbstractBlockRenderContextMixin implements RenderContext { + @Shadow + protected RenderType type; + + @Shadow + protected SodiumModelData modelData; + + @Override + public ModelData getModelData() { + return (ModelData) (Object) this.modelData; + } + + @Override + public RenderType getRenderType() { + return type; + } +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/ChunkRenderTypeSetAccessor.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/ChunkRenderTypeSetAccessor.java new file mode 100644 index 0000000000..367914f6bf --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/ChunkRenderTypeSetAccessor.java @@ -0,0 +1,19 @@ +package net.caffeinemc.mods.sodium.neoforge.mixin; + +import net.neoforged.neoforge.client.ChunkRenderTypeSet; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +import java.util.BitSet; + +@Mixin(ChunkRenderTypeSet.class) +public interface ChunkRenderTypeSetAccessor { + @Invoker("") + static ChunkRenderTypeSet create(BitSet set) { + throw new IllegalStateException("Not shadowed"); + } + + @Accessor + BitSet getBits(); +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/ClientHooksMixin.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/ClientHooksMixin.java new file mode 100644 index 0000000000..81c5a286a6 --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/ClientHooksMixin.java @@ -0,0 +1,17 @@ +package net.caffeinemc.mods.sodium.neoforge.mixin; + +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.neoforged.neoforge.client.ClientHooks; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(ClientHooks.class) +public class ClientHooksMixin { + // TODO: This is not a proper fix at all. Figure out why Forge is causing the UV shrink ratio to go insane. + @Redirect(method = "fixItemModelSeams", at = @At(value = "INVOKE", target = + "Lnet/minecraft/client/renderer/texture/TextureAtlasSprite;uvShrinkRatio()F")) + private static float alterUvShrinkRatio(TextureAtlasSprite sprite) { + return 0.0f; + } +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/LevelSliceMixin.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/LevelSliceMixin.java new file mode 100644 index 0000000000..42e32222cb --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/LevelSliceMixin.java @@ -0,0 +1,71 @@ +package net.caffeinemc.mods.sodium.neoforge.mixin; + + +import net.caffeinemc.mods.sodium.client.services.SodiumModelData; +import net.caffeinemc.mods.sodium.client.services.SodiumModelDataContainer; +import net.caffeinemc.mods.sodium.client.world.LevelSlice; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.ChunkPos; +import net.neoforged.neoforge.client.model.data.ModelData; +import net.neoforged.neoforge.common.world.AuxiliaryLightManager; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +/** + * This is a self-mixin to implement Forge interfaces into LevelSlice. + */ +@Mixin(LevelSlice.class) +public abstract class LevelSliceMixin implements BlockAndTintGetter { + @Shadow + @Final + private Object[] auxLightManager; + + @Shadow + @Final + private ClientLevel level; + + @Shadow + private int originBlockX, originBlockY, originBlockZ; + + @Shadow + public static int getLocalSectionIndex(int sectionX, int sectionY, int sectionZ) { + throw new IllegalStateException("Not shadowed!"); + } + + @Shadow + public SodiumModelData getPlatformModelData(BlockPos pos) { + throw new IllegalStateException("Not shadowed!"); + } + + @Override + public ModelData getModelData(BlockPos pos) { + SodiumModelData modelData = getPlatformModelData(pos); + return modelData != null ? (ModelData) (Object) modelData : null; + } + + @Override + public @Nullable AuxiliaryLightManager getAuxLightManager(ChunkPos pos) { + int relChunkX = pos.x - (this.originBlockX >> 4); + int relChunkZ = pos.z - (this.originBlockZ >> 4); + + return (AuxiliaryLightManager) auxLightManager[getLocalSectionIndex(relChunkX, 0, relChunkZ)]; + } + + @Override + public @Nullable AuxiliaryLightManager getAuxLightManager(BlockPos pos) { + int relBlockX = pos.getX() - this.originBlockX; + int relBlockY = pos.getY() - this.originBlockY; + int relBlockZ = pos.getZ() - this.originBlockZ; + + return (AuxiliaryLightManager) auxLightManager[getLocalSectionIndex(relBlockX >> 4, relBlockY >> 4, relBlockZ >> 4)]; + } + + @Override + public float getShade(float normalX, float normalY, float normalZ, boolean shade) { + return this.level.getShade(normalX, normalY, normalZ, shade); + } +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/ModelDataMixin.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/ModelDataMixin.java new file mode 100644 index 0000000000..d6a703ac36 --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/ModelDataMixin.java @@ -0,0 +1,9 @@ +package net.caffeinemc.mods.sodium.neoforge.mixin; + +import net.caffeinemc.mods.sodium.client.services.SodiumModelData; +import net.neoforged.neoforge.client.model.data.ModelData; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ModelData.class) +public class ModelDataMixin implements SodiumModelData { +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/ResourcePackLoaderMixin.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/ResourcePackLoaderMixin.java new file mode 100644 index 0000000000..bc7035a5a1 --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/ResourcePackLoaderMixin.java @@ -0,0 +1,35 @@ +package net.caffeinemc.mods.sodium.neoforge.mixin; + +import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet; +import net.minecraft.server.packs.repository.Pack; +import net.neoforged.fml.loading.LoadingModList; +import net.neoforged.neoforge.resource.ResourcePackLoader; +import net.neoforged.neoforgespi.locating.IModFile; +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.Redirect; + +import java.util.Map; +import java.util.Set; + +@Mixin(ResourcePackLoader.class) +public class ResourcePackLoaderMixin { + @Unique + private static final IModFile SODIUM_FILE = LoadingModList.get().getModFileById("sodium").getFile(); + + @Redirect(remap = false, method = "packFinder", at = @At(value = "INVOKE", target = "Ljava/util/Map;entrySet()Ljava/util/Set;")) + private static Set> changeSet(Map instance) { + ReferenceLinkedOpenHashSet> sortedSet = new ReferenceLinkedOpenHashSet<>(); + instance.entrySet().stream().sorted((e0, e1) -> { + if (e0.getKey() == SODIUM_FILE) { + return -1; + } + if (e1.getKey() == SODIUM_FILE) { + return 1; + } + return 0; + }).forEach(sortedSet::add); + return sortedSet; + } +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/SimpleBakedModelAccessor.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/SimpleBakedModelAccessor.java new file mode 100644 index 0000000000..9b4c2e1c04 --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/SimpleBakedModelAccessor.java @@ -0,0 +1,12 @@ +package net.caffeinemc.mods.sodium.neoforge.mixin; + +import net.minecraft.client.resources.model.SimpleBakedModel; +import net.neoforged.neoforge.client.ChunkRenderTypeSet; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(SimpleBakedModel.class) +public interface SimpleBakedModelAccessor { + @Accessor + ChunkRenderTypeSet getBlockRenderTypes(); +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/core/model/quad/BakedQuadMixin.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/core/model/quad/BakedQuadMixin.java new file mode 100644 index 0000000000..a2682022f0 --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/core/model/quad/BakedQuadMixin.java @@ -0,0 +1,134 @@ +package net.caffeinemc.mods.sodium.neoforge.mixin.core.model.quad; + +import net.caffeinemc.mods.sodium.client.model.quad.BakedQuadView; +import net.caffeinemc.mods.sodium.client.model.quad.properties.ModelQuadFacing; +import net.caffeinemc.mods.sodium.client.model.quad.properties.ModelQuadFlags; +import net.caffeinemc.mods.sodium.client.util.ModelQuadUtil; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.Direction; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(BakedQuad.class) +public class BakedQuadMixin implements BakedQuadView { + @Shadow + @Final + protected int[] vertices; + + @Shadow + @Final + protected TextureAtlasSprite sprite; + + @Shadow + @Final + protected int tintIndex; + + @Shadow + @Final + protected Direction direction; // This is really the light face, but we can't rename it. + + @Shadow + @Final + private boolean shade; + + @Unique + private int flags; + + @Unique + private int normal; + + @Unique + private ModelQuadFacing normalFace = null; + + @Inject(method = { + "([IILnet/minecraft/core/Direction;Lnet/minecraft/client/renderer/texture/TextureAtlasSprite;ZZ)V" + }, at = @At("RETURN")) + private void init(int[] is, int i, Direction face, TextureAtlasSprite arg2, boolean bl, boolean hasAmbientOcclusion, CallbackInfo ci) { + this.normal = this.calculateNormal(); + this.normalFace = ModelQuadFacing.fromPackedNormal(this.normal); + + this.flags = ModelQuadFlags.getQuadFlags(this, face); + } + + @Override + public float getX(int idx) { + return Float.intBitsToFloat(this.vertices[ModelQuadUtil.vertexOffset(idx) + ModelQuadUtil.POSITION_INDEX]); + } + + @Override + public float getY(int idx) { + return Float.intBitsToFloat(this.vertices[ModelQuadUtil.vertexOffset(idx) + ModelQuadUtil.POSITION_INDEX + 1]); + } + + @Override + public float getZ(int idx) { + return Float.intBitsToFloat(this.vertices[ModelQuadUtil.vertexOffset(idx) + ModelQuadUtil.POSITION_INDEX + 2]); + } + + @Override + public int getColor(int idx) { + return this.vertices[ModelQuadUtil.vertexOffset(idx) + ModelQuadUtil.COLOR_INDEX]; + } + + @Override + public int getVertexNormal(int idx) { + return this.vertices[ModelQuadUtil.vertexOffset(idx) + ModelQuadUtil.NORMAL_INDEX]; + } + + @Override + public int getLight(int idx) { + return this.vertices[ModelQuadUtil.vertexOffset(idx) + ModelQuadUtil.LIGHT_INDEX]; + } + + @Override + public TextureAtlasSprite getSprite() { + return this.sprite; + } + + @Override + public float getTexU(int idx) { + return Float.intBitsToFloat(this.vertices[ModelQuadUtil.vertexOffset(idx) + ModelQuadUtil.TEXTURE_INDEX]); + } + + @Override + public float getTexV(int idx) { + return Float.intBitsToFloat(this.vertices[ModelQuadUtil.vertexOffset(idx) + ModelQuadUtil.TEXTURE_INDEX + 1]); + } + + @Override + public int getFlags() { + return this.flags; + } + + @Override + public int getColorIndex() { + return this.tintIndex; + } + + @Override + public ModelQuadFacing getNormalFace() { + return this.normalFace; + } + + @Override + public int getFaceNormal() { + return this.normal; + } + + @Override + public Direction getLightFace() { + return this.direction; + } + + @Override + @Unique(silent = true) // The target class has a function with the same name in a remapped environment + public boolean hasShade() { + return this.shade; + } +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/features/model/MultiPartBakedModelMixin.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/features/model/MultiPartBakedModelMixin.java new file mode 100644 index 0000000000..a1facd13da --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/features/model/MultiPartBakedModelMixin.java @@ -0,0 +1,149 @@ +package net.caffeinemc.mods.sodium.neoforge.mixin.features.model; + +import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; +import net.caffeinemc.mods.sodium.neoforge.mixin.ChunkRenderTypeSetAccessor; +import net.caffeinemc.mods.sodium.neoforge.mixin.SimpleBakedModelAccessor; +import net.minecraft.client.renderer.ItemBlockRenderTypes; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.resources.model.MultiPartBakedModel; +import net.minecraft.client.resources.model.SimpleBakedModel; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.client.ChunkRenderTypeSet; +import net.neoforged.neoforge.client.model.data.ModelData; +import net.neoforged.neoforge.client.model.data.MultipartModelData; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import javax.annotation.Nullable; +import java.util.*; +import java.util.concurrent.locks.StampedLock; +import java.util.function.Predicate; + +@Mixin(MultiPartBakedModel.class) +public class MultiPartBakedModelMixin { + @Unique + private final Map stateCacheFast = new Reference2ReferenceOpenHashMap<>(); + @Unique + private final StampedLock lock = new StampedLock(); + + @Shadow + @Final + private List, BakedModel>> selectors; + + @Unique + private boolean canSkipRenderTypeCheck; + + @Inject(method = "", at = @At("RETURN")) + private void storeClassInfo(List, BakedModel>> list, CallbackInfo ci) { + this.canSkipRenderTypeCheck = this.selectors.stream().allMatch(model -> (model.getRight() instanceof SimpleBakedModel simpleModel && ((SimpleBakedModelAccessor) simpleModel).getBlockRenderTypes() == null)); + } + + /** + * @author JellySquid + * @reason Avoid expensive allocations and replace bitfield indirection + */ + @Overwrite + public List getQuads(@Nullable BlockState state, @Nullable Direction direction, RandomSource random, ModelData modelData, @org.jetbrains.annotations.Nullable RenderType renderType) { + if (state == null) { + return Collections.emptyList(); + } + + BakedModel[] models; + + long readStamp = this.lock.readLock(); + try { + models = this.stateCacheFast.get(state); + } finally { + this.lock.unlockRead(readStamp); + } + + if (models == null) { + long writeStamp = this.lock.writeLock(); + try { + List modelList = new ArrayList<>(this.selectors.size()); + + for (Pair, BakedModel> pair : this.selectors) { + if (pair.getLeft().test(state)) { + modelList.add(pair.getRight()); + } + } + + models = modelList.toArray(BakedModel[]::new); + this.stateCacheFast.put(state, models); + } finally { + this.lock.unlockWrite(writeStamp); + } + } + + List quads = new ArrayList<>(); + long seed = random.nextLong(); + + for (BakedModel model : models) { + random.setSeed(seed); + + if (canSkipRenderTypeCheck || renderType == null || model.getRenderTypes(state, random, modelData).contains(renderType)) { + quads.addAll(model.getQuads(state, direction, random, MultipartModelData.resolve(modelData, model), renderType)); + } + } + + return quads; + } + + /** + * @author embeddedt, IMS + * @reason Optimize render type lookup using existing cache + */ + @Overwrite + public ChunkRenderTypeSet getRenderTypes(@NotNull BlockState state, @NotNull RandomSource random, @NotNull ModelData data) { + long seed = random.nextLong(); + + if (canSkipRenderTypeCheck) { + return ItemBlockRenderTypes.getRenderLayers(state); + } + + BakedModel[] models; + + long readStamp = this.lock.readLock(); + try { + models = this.stateCacheFast.get(state); + } finally { + this.lock.unlockRead(readStamp); + } + + if (models == null) { + long writeStamp = this.lock.writeLock(); + try { + List modelList = new ArrayList<>(this.selectors.size()); + + for (Pair, BakedModel> pair : this.selectors) { + if (pair.getLeft().test(state)) { + modelList.add(pair.getRight()); + } + } + + models = modelList.toArray(BakedModel[]::new); + this.stateCacheFast.put(state, models); + } finally { + this.lock.unlockWrite(writeStamp); + } + } + + BitSet bits = new BitSet(); + + for (BakedModel model : models) { + random.setSeed(seed); + + bits.or((((ChunkRenderTypeSetAccessor) (Object) model.getRenderTypes(state, random, data)).getBits())); + } + + return ChunkRenderTypeSetAccessor.create(bits); + } +} \ No newline at end of file diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/features/model/WeightedBakedModelMixin.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/features/model/WeightedBakedModelMixin.java new file mode 100644 index 0000000000..31afaf092f --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/features/model/WeightedBakedModelMixin.java @@ -0,0 +1,79 @@ +package net.caffeinemc.mods.sodium.neoforge.mixin.features.model; + +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.resources.model.WeightedBakedModel; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.util.random.WeightedEntry; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.client.ChunkRenderTypeSet; +import net.neoforged.neoforge.client.model.data.ModelData; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.*; + +import java.util.Collections; +import java.util.List; + +@Mixin(WeightedBakedModel.class) +public class WeightedBakedModelMixin { + @Shadow + @Final + private List> list; + + @Shadow + @Final + private int totalWeight; + + @Unique + private static T getAt(List pool, int totalWeight) { + int i = 0; + int len = pool.size(); + + T weighted; + + do { + if (i >= len) { + return null; + } + + weighted = pool.get(i++); + totalWeight -= weighted.getWeight().asInt(); + } while (totalWeight >= 0); + + return weighted; + } + + /** + * @author JellySquid + * @reason Avoid excessive object allocations + */ + @Overwrite + public List getQuads(@javax.annotation.Nullable BlockState state, @javax.annotation.Nullable Direction face, RandomSource random, ModelData modelData, @org.jetbrains.annotations.Nullable RenderType renderType) { + WeightedEntry.Wrapper quad = getAt(this.list, Math.abs((int) random.nextLong()) % this.totalWeight); + + if (quad != null) { + return quad.data() + .getQuads(state, face, random, modelData, renderType); + } + + return Collections.emptyList(); + } + + /** + * @author JellySquid + * @reason Avoid excessive object allocations + */ + @Overwrite + public ChunkRenderTypeSet getRenderTypes(@NotNull BlockState state, @NotNull RandomSource rand, @NotNull ModelData data) { + WeightedEntry.Wrapper quad = getAt(this.list, Math.abs((int) rand.nextLong()) % this.totalWeight); + + if (quad != null) { + return quad.data() + .getRenderTypes(state, rand, data); + } + + return ChunkRenderTypeSet.none(); + } +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/features/render/model/block/ModelBlockRendererMixin.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/features/render/model/block/ModelBlockRendererMixin.java new file mode 100644 index 0000000000..7feb74b4d2 --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/mixin/features/render/model/block/ModelBlockRendererMixin.java @@ -0,0 +1,93 @@ +package net.caffeinemc.mods.sodium.neoforge.mixin.features.render.model.block; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.caffeinemc.mods.sodium.api.util.ColorABGR; +import net.caffeinemc.mods.sodium.api.vertex.buffer.VertexBufferWriter; +import net.caffeinemc.mods.sodium.client.model.quad.BakedQuadView; +import net.caffeinemc.mods.sodium.client.render.immediate.model.BakedModelEncoder; +import net.caffeinemc.mods.sodium.client.render.texture.SpriteUtil; +import net.caffeinemc.mods.sodium.client.render.vertex.VertexConsumerUtils; +import net.caffeinemc.mods.sodium.client.util.DirectionUtil; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.ModelBlockRenderer; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.SingleThreadedRandomSource; +import net.neoforged.neoforge.client.model.data.ModelData; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; + +@Mixin(ModelBlockRenderer.class) +public class ModelBlockRendererMixin { + @Unique + private final RandomSource random = new SingleThreadedRandomSource(42L); + + @Unique + @SuppressWarnings("ForLoopReplaceableByForEach") + private static void renderQuads(PoseStack.Pose matrices, VertexBufferWriter writer, int defaultColor, List quads, int light, int overlay) { + for (int i = 0; i < quads.size(); i++) { + BakedQuad bakedQuad = quads.get(i); + + if (bakedQuad.getVertices().length < 32) { + continue; // ignore bad quads + } + + BakedQuadView quad = (BakedQuadView) bakedQuad; + + int color = quad.hasColor() ? defaultColor : 0xFFFFFFFF; + + BakedModelEncoder.writeQuadVertices(writer, matrices, quad, color, light, overlay); + + SpriteUtil.markSpriteActive(quad.getSprite()); + } + } + + /** + * @reason Use optimized vertex writer intrinsics, avoid allocations + * @author JellySquid + */ + @Inject(method = "renderModel(Lcom/mojang/blaze3d/vertex/PoseStack$Pose;Lcom/mojang/blaze3d/vertex/VertexConsumer;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/client/resources/model/BakedModel;FFFIILnet/neoforged/neoforge/client/model/data/ModelData;Lnet/minecraft/client/renderer/RenderType;)V", at = @At("HEAD"), cancellable = true) + private void renderFast(PoseStack.Pose entry, VertexConsumer vertexConsumer, BlockState blockState, BakedModel bakedModel, float red, float green, float blue, int light, int overlay, ModelData modelData, RenderType renderType, CallbackInfo ci) { + var writer = VertexConsumerUtils.convertOrLog(vertexConsumer); + if (writer == null) { + return; + } + + ci.cancel(); + + RandomSource random = this.random; + + // Clamp color ranges + red = Mth.clamp(red, 0.0F, 1.0F); + green = Mth.clamp(green, 0.0F, 1.0F); + blue = Mth.clamp(blue, 0.0F, 1.0F); + + int defaultColor = ColorABGR.pack(red, green, blue, 1.0F); + + for (Direction direction : DirectionUtil.ALL_DIRECTIONS) { + random.setSeed(42L); + List quads = bakedModel.getQuads(blockState, direction, random, modelData, renderType); + + if (!quads.isEmpty()) { + renderQuads(entry, writer, defaultColor, quads, light, overlay); + } + } + + random.setSeed(42L); + List quads = bakedModel.getQuads(blockState, null, random, modelData, renderType); + + if (!quads.isEmpty()) { + renderQuads(entry, writer, defaultColor, quads, light, overlay); + } + } +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/model/NeoForgeModelAccess.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/model/NeoForgeModelAccess.java new file mode 100644 index 0000000000..b0996b3674 --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/model/NeoForgeModelAccess.java @@ -0,0 +1,56 @@ +package net.caffeinemc.mods.sodium.neoforge.model; + +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import net.caffeinemc.mods.sodium.client.services.PlatformModelAccess; +import net.caffeinemc.mods.sodium.client.services.SodiumModelData; +import net.caffeinemc.mods.sodium.client.services.SodiumModelDataContainer; +import net.caffeinemc.mods.sodium.client.world.LevelSlice; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.SectionPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.client.model.data.ModelData; + +import java.util.List; +import java.util.Set; + +public class NeoForgeModelAccess implements PlatformModelAccess { + @Override + public Iterable getModelRenderTypes(BlockAndTintGetter level, BakedModel model, BlockState state, BlockPos pos, RandomSource random, SodiumModelData modelData) { + return model.getRenderTypes(state, random, (ModelData) (Object) modelData); + } + + @Override + public List getQuads(BlockAndTintGetter level, BlockPos pos, BakedModel model, BlockState state, Direction face, RandomSource random, RenderType renderType, SodiumModelData modelData) { + return model.getQuads(state, face, random, (ModelData) (Object) modelData, renderType); + } + + @Override + public SodiumModelDataContainer getModelDataContainer(Level level, SectionPos sectionPos) { + Set> entrySet = level.getModelDataManager().getAt(sectionPos).long2ObjectEntrySet(); + Long2ObjectMap modelDataMap = new Long2ObjectOpenHashMap<>(entrySet.size()); + + for (Long2ObjectMap.Entry entry : entrySet) { + modelDataMap.put(entry.getLongKey(), (SodiumModelData) (Object) entry.getValue()); + } + + return new SodiumModelDataContainer(modelDataMap); + } + + @Override + public SodiumModelData getModelData(LevelSlice slice, BakedModel model, BlockState state, BlockPos pos, SodiumModelData originalData) { + return (SodiumModelData) (Object) model.getModelData(slice, pos, state, (ModelData) (Object) originalData); + } + + @Override + public SodiumModelData getEmptyModelData() { + return (SodiumModelData) (Object) ModelData.EMPTY; + } +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/render/FluidRendererImpl.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/render/FluidRendererImpl.java new file mode 100644 index 0000000000..3c450bd0bd --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/render/FluidRendererImpl.java @@ -0,0 +1,124 @@ +package net.caffeinemc.mods.sodium.neoforge.render; + +import net.caffeinemc.mods.sodium.client.model.color.ColorProvider; +import net.caffeinemc.mods.sodium.client.model.color.ColorProviderRegistry; +import net.caffeinemc.mods.sodium.client.model.light.LightPipelineProvider; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildBuffers; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.buffers.ChunkModelBuilder; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.DefaultFluidRenderer; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.FluidRenderer; +import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.DefaultMaterials; +import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.Material; +import net.caffeinemc.mods.sodium.client.render.chunk.translucent_sorting.TranslucentGeometryCollector; +import net.caffeinemc.mods.sodium.client.world.LevelSlice; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.FluidState; +import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; +import net.neoforged.neoforge.client.textures.FluidSpriteCache; + +public class FluidRendererImpl extends FluidRenderer { + // The current default context is set up before invoking FluidRenderHandler#renderFluid and cleared afterwards. + private static final ThreadLocal CURRENT_DEFAULT_CONTEXT = ThreadLocal.withInitial(DefaultRenderContext::new); + + private final ColorProviderRegistry colorProviderRegistry; + private final DefaultFluidRenderer defaultRenderer; + + public FluidRendererImpl(ColorProviderRegistry colorProviderRegistry, LightPipelineProvider lighters) { + this.colorProviderRegistry = colorProviderRegistry; + defaultRenderer = new DefaultFluidRenderer(colorProviderRegistry, lighters); + } + + public void render(LevelSlice level, BlockState blockState, FluidState fluidState, BlockPos blockPos, BlockPos offset, TranslucentGeometryCollector collector, ChunkBuildBuffers buffers) { + var material = DefaultMaterials.forFluidState(fluidState); + var meshBuilder = buffers.get(material); + + IClientFluidTypeExtensions handler = IClientFluidTypeExtensions.of(fluidState); + + // Invoking FluidRenderHandler#renderFluid can invoke vanilla FluidRenderer#render. + // + // Sodium cannot let vanilla FluidRenderer#render run (during the invocation of FluidRenderHandler#renderFluid) + // for two reasons. + // 1. It is the hot path and vanilla FluidRenderer#render is not very fast. + // 2. Fabric API's mixins to FluidRenderer#render expect it to be initially called from the chunk rebuild task, + // not from inside FluidRenderHandler#renderFluid. Not upholding this assumption will result in all custom + // geometry to be buffered twice. + // + // The default implementation of FluidRenderHandler#renderFluid invokes vanilla FluidRenderer#render, but + // Fabric API does not support invoking vanilla FluidRenderer#render from FluidRenderHandler#renderFluid + // directly and it does not support calling the default implementation of FluidRenderHandler#renderFluid (super) + // more than once. Because of this, the parameters to vanilla FluidRenderer#render will be the same as those + // initially passed to FluidRenderHandler#renderFluid, so they can be ignored. + // + // Due to all the above, Sodium injects into head of vanilla FluidRenderer#render before Fabric API and cancels + // the call if it was invoked from inside FluidRenderHandler#renderFluid. The injector ends up calling + // DefaultFluidRenderer#render, which emulates what vanilla FluidRenderer#render does, but is more efficient. + // To allow invoking this method from the injector, where there is no local Sodium context, the renderer and + // parameters are bundled into a DefaultRenderContext which is stored in a ThreadLocal. + + DefaultRenderContext defaultContext = CURRENT_DEFAULT_CONTEXT.get(); + defaultContext.setUp(this.colorProviderRegistry, this.defaultRenderer, level, fluidState, blockPos, offset, collector, meshBuilder, material, handler); + + try { + if (!handler.renderFluid(fluidState, level, blockPos, meshBuilder.asFallbackVertexConsumer(material, collector), blockState)) { + defaultContext.render(); + } + } finally { + defaultContext.clear(); + } + } + + private static class DefaultRenderContext { + private DefaultFluidRenderer renderer; + private LevelSlice level; + private FluidState fluidState; + private BlockPos blockPos; + private BlockPos offset; + private TranslucentGeometryCollector collector; + private ChunkModelBuilder meshBuilder; + private Material material; + private IClientFluidTypeExtensions handler; + private ColorProviderRegistry colorProviderRegistry; + + public void setUp(ColorProviderRegistry colorProviderRegistry, DefaultFluidRenderer renderer, LevelSlice level, FluidState fluidState, BlockPos blockPos, BlockPos offset, TranslucentGeometryCollector collector, ChunkModelBuilder meshBuilder, Material material, IClientFluidTypeExtensions handler) { + this.colorProviderRegistry = colorProviderRegistry; + this.renderer = renderer; + this.level = level; + this.fluidState = fluidState; + this.blockPos = blockPos; + this.offset = offset; + this.collector = collector; + this.meshBuilder = meshBuilder; + this.material = material; + this.handler = handler; + } + + public void clear() { + this.renderer = null; + this.level = null; + this.fluidState = null; + this.blockPos = null; + this.offset = null; + this.collector = null; + this.meshBuilder = null; + this.material = null; + this.handler = null; + } + + public ColorProvider getColorProvider(Fluid fluid) { + var override = this.colorProviderRegistry.getColorProvider(fluid); + + if (override != null) { + return override; + } + + return ForgeColorProviders.adapt(handler); + } + + public void render() { + this.renderer.render(this.level, this.fluidState, this.blockPos, this.offset, this.collector, this.meshBuilder, this.material, + getColorProvider(fluidState.getType()), FluidSpriteCache.getFluidSprites(level, blockPos, fluidState)); + } + } +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/render/ForgeColorProviders.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/render/ForgeColorProviders.java new file mode 100644 index 0000000000..d5b87ea234 --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/render/ForgeColorProviders.java @@ -0,0 +1,30 @@ +package net.caffeinemc.mods.sodium.neoforge.render; + +import net.caffeinemc.mods.sodium.api.util.ColorARGB; +import net.caffeinemc.mods.sodium.client.model.color.ColorProvider; +import net.caffeinemc.mods.sodium.client.model.quad.ModelQuadView; +import net.caffeinemc.mods.sodium.client.world.LevelSlice; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.material.FluidState; +import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; + +import java.util.Arrays; + +public class ForgeColorProviders { + public static ColorProvider adapt(IClientFluidTypeExtensions handler) { + return new ForgeFluidAdapter(handler); + } + + private static class ForgeFluidAdapter implements ColorProvider { + private final IClientFluidTypeExtensions handler; + + public ForgeFluidAdapter(IClientFluidTypeExtensions handler) { + this.handler = handler; + } + + @Override + public void getColors(LevelSlice slice, BlockPos pos, FluidState state, ModelQuadView quad, int[] output) { + Arrays.fill(output, ColorARGB.withAlpha(this.handler.getTintColor(state, slice, pos), 255)); + } + } +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/texture/BlockSpriteFinder.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/texture/BlockSpriteFinder.java new file mode 100644 index 0000000000..0f52313bb9 --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/texture/BlockSpriteFinder.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.caffeinemc.mods.sodium.neoforge.texture; + +import net.caffeinemc.mods.sodium.client.SodiumClientMod; +import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.resources.ResourceLocation; + +import java.util.Map; +import java.util.function.Consumer; + +/** + * Indexes an atlas sprite to allow fast lookup of Sprites from + * baked vertex coordinates. Implementation is a straightforward + * quad tree. Other options that were considered were linear search + * (slow) and direct indexing of fixed-size cells. Direct indexing + * would be fastest but would be memory-intensive for large atlases + * and unsuitable for any atlas that isn't consistently aligned to + * a fixed cell size. + */ +public class BlockSpriteFinder { + private final Node root; + private final TextureAtlas spriteAtlasTexture; + private int badSpriteCount = 0; + + public BlockSpriteFinder(Map sprites, TextureAtlas spriteAtlasTexture) { + root = new Node(0.5f, 0.5f, 0.25f); + this.spriteAtlasTexture = spriteAtlasTexture; + sprites.values().forEach(root::add); + } + + public TextureAtlasSprite find(float u, float v) { + return root.find(u, v); + } + + private class Node { + static final float EPS = 0.00001f; + final float midU; + final float midV; + final float cellRadius; + Object lowLow = null; + Object lowHigh = null; + Object highLow = null; + Object highHigh = null; + + Node(float midU, float midV, float radius) { + this.midU = midU; + this.midV = midV; + cellRadius = radius; + } + + void add(TextureAtlasSprite sprite) { + if (sprite.getU0() < 0 - EPS || sprite.getU1() > 1 + EPS || sprite.getV0() < 0 - EPS || sprite.getV1() > 1 + EPS) { + // Sprite has broken bounds. This SHOULD NOT happen, but in the past some mods have broken this. + // Prefer failing with a log warning rather than risking a stack overflow. + if (badSpriteCount++ < 5) { + String errorMessage = "SpriteFinderImpl: Skipping sprite {} with broken bounds [{}, {}]x[{}, {}]. Sprite bounds should be between 0 and 1."; + SodiumClientMod.logger().error(errorMessage, sprite.contents().name(), sprite.getU0(), sprite.getU1(), sprite.getV0(), sprite.getV1()); + } + + return; + } + + final boolean lowU = sprite.getU0() < midU - EPS; + final boolean highU = sprite.getU1() > midU + EPS; + final boolean lowV = sprite.getV0() < midV - EPS; + final boolean highV = sprite.getV1() > midV + EPS; + + if (lowU && lowV) { + addInner(sprite, lowLow, -1, -1, q -> lowLow = q); + } + + if (lowU && highV) { + addInner(sprite, lowHigh, -1, 1, q -> lowHigh = q); + } + + if (highU && lowV) { + addInner(sprite, highLow, 1, -1, q -> highLow = q); + } + + if (highU && highV) { + addInner(sprite, highHigh, 1, 1, q -> highHigh = q); + } + } + + private void addInner(TextureAtlasSprite sprite, Object quadrant, int uStep, int vStep, Consumer setter) { + if (quadrant == null) { + setter.accept(sprite); + } else if (quadrant instanceof Node) { + ((Node) quadrant).add(sprite); + } else { + Node n = new Node(midU + cellRadius * uStep, midV + cellRadius * vStep, cellRadius * 0.5f); + + if (quadrant instanceof TextureAtlasSprite) { + n.add((TextureAtlasSprite) quadrant); + } + + n.add(sprite); + setter.accept(n); + } + } + + private TextureAtlasSprite find(float u, float v) { + if (u < midU) { + return v < midV ? findInner(lowLow, u, v) : findInner(lowHigh, u, v); + } else { + return v < midV ? findInner(highLow, u, v) : findInner(highHigh, u, v); + } + } + + private TextureAtlasSprite findInner(Object quadrant, float u, float v) { + if (quadrant instanceof TextureAtlasSprite) { + return (TextureAtlasSprite) quadrant; + } else if (quadrant instanceof Node) { + return ((Node) quadrant).find(u, v); + } else { + return spriteAtlasTexture.getSprite(MissingTextureAtlasSprite.getLocation()); + } + } + } +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/texture/NeoForgeTextureAccess.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/texture/NeoForgeTextureAccess.java new file mode 100644 index 0000000000..57753f147c --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/texture/NeoForgeTextureAccess.java @@ -0,0 +1,11 @@ +package net.caffeinemc.mods.sodium.neoforge.texture; + +import net.caffeinemc.mods.sodium.client.services.PlatformTextureAccess; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; + +public class NeoForgeTextureAccess implements PlatformTextureAccess { + @Override + public TextureAtlasSprite findInBlockAtlas(float u, float v) { + return SpriteFinderCache.forBlockAtlas().find(u, v); + } +} diff --git a/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/texture/SpriteFinderCache.java b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/texture/SpriteFinderCache.java new file mode 100644 index 0000000000..f3ac9b189c --- /dev/null +++ b/neoforge/src/main/java/net/caffeinemc/mods/sodium/neoforge/texture/SpriteFinderCache.java @@ -0,0 +1,37 @@ +package net.caffeinemc.mods.sodium.neoforge.texture; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.resources.model.ModelManager; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.ResourceManagerReloadListener; + +/** + * Caches {@link BlockSpriteFinder}s for maximum efficiency. They must be refreshed after each resource reload. + * + *

This class should not be used during a resource reload, as returned SpriteFinders may be null or outdated. + */ +public class SpriteFinderCache { + private static BlockSpriteFinder blockAtlasSpriteFinder; + + public static BlockSpriteFinder forBlockAtlas() { + return blockAtlasSpriteFinder; + } + + public static class ReloadListener implements ResourceManagerReloadListener { + public static final ResourceLocation ID = ResourceLocation.fromNamespaceAndPath("sodium", "sprite_finder_cache"); + public static final ReloadListener INSTANCE = new ReloadListener(); + + private ReloadListener() { + } + + // BakedModelManager#getAtlas only returns correct results after the BakedModelManager is done reloading + @Override + public void onResourceManagerReload(ResourceManager manager) { + ModelManager modelManager = Minecraft.getInstance().getModelManager(); + TextureAtlas atlas = modelManager.getAtlas(TextureAtlas.LOCATION_BLOCKS); + blockAtlasSpriteFinder = new BlockSpriteFinder(atlas.getTextures(), atlas); + } + } +} diff --git a/neoforge/src/main/resources/META-INF/accesstransformer.cfg b/neoforge/src/main/resources/META-INF/accesstransformer.cfg new file mode 100644 index 0000000000..62d286afca --- /dev/null +++ b/neoforge/src/main/resources/META-INF/accesstransformer.cfg @@ -0,0 +1,20 @@ +public net.minecraft.client.model.geom.ModelPart$Vertex +public net.minecraft.client.model.geom.ModelPart$Polygon +public net.minecraft.client.renderer.texture.SpriteContents$InterpolationData +public net.minecraft.client.renderer.texture.SpriteContents$AnimatedTexture +public net.minecraft.client.renderer.texture.SpriteContents$FrameInfo +public net.minecraft.client.renderer.texture.SpriteContents$Ticker +public net.minecraft.world.level.chunk.PalettedContainer$Data +public net.minecraft.world.level.chunk.PalettedContainer$Configuration +public net.minecraft.client.renderer.FogRenderer$FogData +public net.minecraft.client.renderer.FogRenderer$MobEffectFogFunction +public net.minecraft.client.renderer.texture.Stitcher$Holder +public net.minecraft.world.level.biome.Biome$ClimateSettings +public net.minecraft.client.renderer.SectionBufferBuilderPool (Ljava/util/List;)V + +public com.mojang.blaze3d.vertex.PoseStack$Pose (Lorg/joml/Matrix4f;Lorg/joml/Matrix3f;)V +public com.mojang.blaze3d.vertex.PoseStack$Pose trustedNormals # trustedNormals + +public net.minecraft.world.level.GrassColor pixels +public net.minecraft.world.level.FoliageColor pixels +public net.minecraft.client.renderer.FogRenderer getPriorityFogFunction(Lnet/minecraft/world/entity/Entity;F)Lnet/minecraft/client/renderer/FogRenderer$MobEffectFogFunction; \ No newline at end of file diff --git a/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/neoforge/src/main/resources/META-INF/neoforge.mods.toml new file mode 100644 index 0000000000..e2977ede51 --- /dev/null +++ b/neoforge/src/main/resources/META-INF/neoforge.mods.toml @@ -0,0 +1,43 @@ +modLoader = "javafml" +loaderVersion = "*" +license = "Polyform-Shield-1.0" + +[[mods]] +modId = "sodium" + +version = "${version}" +displayName = "Sodium" + +logoFile = "sodium-icon.png" #optional + +authors = "JellySquid" + +description = ''' +Sodium is a powerful rendering engine for Minecraft which improves frame rates and reduces lag spikes. +''' + +provides = ["indium"] + +[modproperties.sodium] +"fabric-renderer-api-v1:contains_renderer" = true + +[[dependencies.sodium]] +modId = "minecraft" +type = "required" +versionRange = "[1.20.4,1.21.1)" +ordering = "NONE" +side = "CLIENT" + +[[dependencies.sodium]] +modId = "embeddium" +type = "incompatible" +reason = "Sodium and Embeddium cannot be used together. Please remove Embeddium." +versionRange = "[0.0.1,)" +ordering = "NONE" +side = "CLIENT" + +[[mixins]] +config = "sodium.mixins.json" + +[[mixins]] +config = "sodium-forge.mixins.json" \ No newline at end of file diff --git a/neoforge/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.data.config.MixinConfig b/neoforge/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.data.config.MixinConfig new file mode 100644 index 0000000000..0852e576fc --- /dev/null +++ b/neoforge/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.data.config.MixinConfig @@ -0,0 +1 @@ +net.caffeinemc.mods.sodium.neoforge.MixinConfigImpl \ No newline at end of file diff --git a/neoforge/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformBlockAccess b/neoforge/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformBlockAccess new file mode 100644 index 0000000000..6b4deab3b3 --- /dev/null +++ b/neoforge/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformBlockAccess @@ -0,0 +1 @@ +net.caffeinemc.mods.sodium.neoforge.block.NeoForgeBlockAccess \ No newline at end of file diff --git a/neoforge/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformInfoAccess b/neoforge/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformInfoAccess new file mode 100644 index 0000000000..ff72f97178 --- /dev/null +++ b/neoforge/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformInfoAccess @@ -0,0 +1 @@ +net.caffeinemc.mods.sodium.neoforge.NeoForgeInfoAccess \ No newline at end of file diff --git a/neoforge/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformLevelAccess b/neoforge/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformLevelAccess new file mode 100644 index 0000000000..e072e8ff3e --- /dev/null +++ b/neoforge/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformLevelAccess @@ -0,0 +1 @@ +net.caffeinemc.mods.sodium.neoforge.level.NeoForgeLevelAccess \ No newline at end of file diff --git a/neoforge/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformModelAccess b/neoforge/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformModelAccess new file mode 100644 index 0000000000..c7786003cd --- /dev/null +++ b/neoforge/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformModelAccess @@ -0,0 +1 @@ +net.caffeinemc.mods.sodium.neoforge.model.NeoForgeModelAccess \ No newline at end of file diff --git a/neoforge/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformTextureAccess b/neoforge/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformTextureAccess new file mode 100644 index 0000000000..2e64e919fd --- /dev/null +++ b/neoforge/src/main/resources/META-INF/services/net.caffeinemc.mods.sodium.client.services.PlatformTextureAccess @@ -0,0 +1 @@ +net.caffeinemc.mods.sodium.neoforge.texture.NeoForgeTextureAccess \ No newline at end of file diff --git a/neoforge/src/main/resources/sodium-forge.mixins.json b/neoforge/src/main/resources/sodium-forge.mixins.json new file mode 100644 index 0000000000..bfdb75a52e --- /dev/null +++ b/neoforge/src/main/resources/sodium-forge.mixins.json @@ -0,0 +1,25 @@ +{ + "package" : "net.caffeinemc.mods.sodium.neoforge.mixin", + "required" : true, + "compatibilityLevel" : "JAVA_17", + "refmap" : "sodium.refmap.json", + "injectors" : { + "defaultRequire" : 1 + }, + "overwrites" : { + "conformVisibility" : true + }, + "client" : [ + "core.model.quad.BakedQuadMixin", + "features.model.MultiPartBakedModelMixin", + "features.model.WeightedBakedModelMixin", + "features.render.model.block.ModelBlockRendererMixin", + "AbstractBlockRenderContextMixin", + "ChunkRenderTypeSetAccessor", + "ClientHooksMixin", + "LevelSliceMixin", + "ModelDataMixin", + "ResourcePackLoaderMixin", + "SimpleBakedModelAccessor" + ] +} \ No newline at end of file diff --git a/neoforge/src/service/java/net/caffeinemc/mods/sodium/service/SodiumWorkarounds.java b/neoforge/src/service/java/net/caffeinemc/mods/sodium/service/SodiumWorkarounds.java new file mode 100644 index 0000000000..1d6876b8e2 --- /dev/null +++ b/neoforge/src/service/java/net/caffeinemc/mods/sodium/service/SodiumWorkarounds.java @@ -0,0 +1,28 @@ +package net.caffeinemc.mods.sodium.service; + +import net.caffeinemc.mods.sodium.client.compatibility.checks.PreLaunchChecks; +import net.caffeinemc.mods.sodium.client.compatibility.environment.probe.GraphicsAdapterProbe; +import net.caffeinemc.mods.sodium.client.compatibility.workarounds.Workarounds; +import net.caffeinemc.mods.sodium.client.compatibility.workarounds.nvidia.NvidiaWorkarounds; +import net.neoforged.neoforgespi.earlywindow.GraphicsBootstrapper; + +public class SodiumWorkarounds implements GraphicsBootstrapper { + @Override + public String name() { + return "sodium"; + } + + @Override + public void bootstrap(String[] arguments) { + PreLaunchChecks.beforeLWJGLInit(); + GraphicsAdapterProbe.findAdapters(); + PreLaunchChecks.onGameInit(); + Workarounds.init(); + final boolean applyNvidiaWorkarounds = Workarounds.isWorkaroundEnabled(Workarounds.Reference.NVIDIA_THREADED_OPTIMIZATIONS); + + if (applyNvidiaWorkarounds) { + System.out.println("[Sodium] Applying NVIDIA workarounds earlier on Forge."); + NvidiaWorkarounds.install(); + } + } +} diff --git a/neoforge/src/service/resources/META-INF/services/net.neoforged.neoforgespi.earlywindow.GraphicsBootstrapper b/neoforge/src/service/resources/META-INF/services/net.neoforged.neoforgespi.earlywindow.GraphicsBootstrapper new file mode 100644 index 0000000000..fdbd1636ac --- /dev/null +++ b/neoforge/src/service/resources/META-INF/services/net.neoforged.neoforgespi.earlywindow.GraphicsBootstrapper @@ -0,0 +1 @@ +net.caffeinemc.mods.sodium.service.SodiumWorkarounds \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 41d020a56f..304b9d9281 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,11 +2,12 @@ rootProject.name = "sodium" pluginManagement { repositories { - maven("https://maven.fabricmc.net/") { - name = "Fabric" - } - - mavenCentral() + maven { url = uri("https://maven.fabricmc.net/") } + maven { url = uri("https://maven.neoforged.net/releases/") } gradlePluginPortal() } -} \ No newline at end of file +} + +include("common") +include("fabric") +include("neoforge") \ No newline at end of file diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/ConsoleSink.java b/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/ConsoleSink.java deleted file mode 100644 index c2c347acec..0000000000 --- a/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/ConsoleSink.java +++ /dev/null @@ -1,9 +0,0 @@ -package net.caffeinemc.mods.sodium.client.gui.console; - -import net.caffeinemc.mods.sodium.client.gui.console.message.MessageLevel; -import net.minecraft.network.chat.Component; -import org.jetbrains.annotations.NotNull; - -public interface ConsoleSink { - void logMessage(@NotNull MessageLevel level, @NotNull Component text, double duration); -} diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/message/Message.java b/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/message/Message.java deleted file mode 100644 index 8425899645..0000000000 --- a/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/message/Message.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.caffeinemc.mods.sodium.client.gui.console.message; - -import net.minecraft.network.chat.Component; - -public record Message(MessageLevel level, Component text, double duration) { - -} diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/message/MessageLevel.java b/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/message/MessageLevel.java deleted file mode 100644 index 569373d1c1..0000000000 --- a/src/main/java/net/caffeinemc/mods/sodium/client/gui/console/message/MessageLevel.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.caffeinemc.mods.sodium.client.gui.console.message; - -public enum MessageLevel { - INFO, - WARN, - SEVERE -} diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/model/ModelCuboidAccessor.java b/src/main/java/net/caffeinemc/mods/sodium/client/model/ModelCuboidAccessor.java deleted file mode 100644 index c7aa736f20..0000000000 --- a/src/main/java/net/caffeinemc/mods/sodium/client/model/ModelCuboidAccessor.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.caffeinemc.mods.sodium.client.model; - -import net.caffeinemc.mods.sodium.client.render.immediate.model.ModelCuboid; - -public interface ModelCuboidAccessor { - ModelCuboid sodium$copy(); -} diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderer.java b/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderer.java deleted file mode 100644 index 22371d3e72..0000000000 --- a/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/BlockRenderer.java +++ /dev/null @@ -1,180 +0,0 @@ -package net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline; - -import net.caffeinemc.mods.sodium.client.model.color.ColorProvider; -import net.caffeinemc.mods.sodium.client.model.color.ColorProviderRegistry; -import net.caffeinemc.mods.sodium.client.model.light.LightMode; -import net.caffeinemc.mods.sodium.client.model.light.LightPipeline; -import net.caffeinemc.mods.sodium.client.model.light.LightPipelineProvider; -import net.caffeinemc.mods.sodium.client.model.light.data.QuadLightData; -import net.caffeinemc.mods.sodium.client.model.quad.BakedQuadView; -import net.caffeinemc.mods.sodium.client.model.quad.properties.ModelQuadFacing; -import net.caffeinemc.mods.sodium.client.model.quad.properties.ModelQuadOrientation; -import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildBuffers; -import net.caffeinemc.mods.sodium.client.render.chunk.compile.buffers.ChunkModelBuilder; -import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.DefaultMaterials; -import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.Material; -import net.caffeinemc.mods.sodium.client.render.chunk.vertex.format.ChunkVertexEncoder; -import net.caffeinemc.mods.sodium.client.util.DirectionUtil; -import net.caffeinemc.mods.sodium.api.util.ColorABGR; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.block.model.BakedQuad; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.core.Direction; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.SingleThreadedRandomSource; -import net.minecraft.world.phys.Vec3; -import java.util.Arrays; -import java.util.List; - -public class BlockRenderer { - private final RandomSource random = new SingleThreadedRandomSource(42L); - - private final ColorProviderRegistry colorProviderRegistry; - private final BlockOcclusionCache occlusionCache; - - private final QuadLightData quadLightData = new QuadLightData(); - - private final LightPipelineProvider lighters; - - private final ChunkVertexEncoder.Vertex[] vertices = ChunkVertexEncoder.Vertex.uninitializedQuad(); - - private final boolean useAmbientOcclusion; - - private final int[] quadColors = new int[4]; - - public BlockRenderer(ColorProviderRegistry colorRegistry, LightPipelineProvider lighters) { - this.colorProviderRegistry = colorRegistry; - this.lighters = lighters; - - this.occlusionCache = new BlockOcclusionCache(); - this.useAmbientOcclusion = Minecraft.useAmbientOcclusion(); - } - - public void renderModel(BlockRenderContext ctx, ChunkBuildBuffers buffers) { - var material = DefaultMaterials.forBlockState(ctx.state()); - var meshBuilder = buffers.get(material); - - ColorProvider colorizer = this.colorProviderRegistry.getColorProvider(ctx.state().getBlock()); - - LightPipeline lighter = this.lighters.getLighter(this.getLightingMode(ctx.state(), ctx.model())); - Vec3 renderOffset; - - if (ctx.state().hasOffsetFunction()) { - renderOffset = ctx.state().getOffset(ctx.slice(), ctx.pos()); - } else { - renderOffset = Vec3.ZERO; - } - - for (Direction face : DirectionUtil.ALL_DIRECTIONS) { - List quads = this.getGeometry(ctx, face); - - if (!quads.isEmpty() && this.isFaceVisible(ctx, face)) { - this.renderQuadList(ctx, material, lighter, colorizer, renderOffset, meshBuilder, quads, face); - } - } - - List all = this.getGeometry(ctx, null); - - if (!all.isEmpty()) { - this.renderQuadList(ctx, material, lighter, colorizer, renderOffset, meshBuilder, all, null); - } - } - - private List getGeometry(BlockRenderContext ctx, Direction face) { - var random = this.random; - random.setSeed(ctx.seed()); - - return ctx.model().getQuads(ctx.state(), face, random); - } - - private boolean isFaceVisible(BlockRenderContext ctx, Direction face) { - return this.occlusionCache.shouldDrawSide(ctx.state(), ctx.slice(), ctx.pos(), face); - } - - private void renderQuadList(BlockRenderContext ctx, Material material, LightPipeline lighter, ColorProvider colorizer, Vec3 offset, - ChunkModelBuilder builder, List quads, Direction cullFace) { - - // This is a very hot allocation, iterate over it manually - // noinspection ForLoopReplaceableByForEach - for (int i = 0, quadsSize = quads.size(); i < quadsSize; i++) { - BakedQuadView quad = (BakedQuadView) quads.get(i); - - final var lightData = this.getVertexLight(ctx, lighter, cullFace, quad); - final var vertexColors = this.getVertexColors(ctx, colorizer, quad); - - this.writeGeometry(ctx, builder, offset, material, quad, vertexColors, lightData); - - TextureAtlasSprite sprite = quad.getSprite(); - - if (sprite != null) { - builder.addSprite(sprite); - } - } - } - - private QuadLightData getVertexLight(BlockRenderContext ctx, LightPipeline lighter, Direction cullFace, BakedQuadView quad) { - QuadLightData light = this.quadLightData; - lighter.calculate(quad, ctx.pos(), light, cullFace, quad.getLightFace(), quad.hasShade()); - - return light; - } - - private int[] getVertexColors(BlockRenderContext ctx, ColorProvider colorProvider, BakedQuadView quad) { - final int[] vertexColors = this.quadColors; - - if (colorProvider != null && quad.hasColor()) { - colorProvider.getColors(ctx.slice(), ctx.pos(), ctx.state(), quad, vertexColors); - } else { - Arrays.fill(vertexColors, 0xFFFFFFFF); - } - - return vertexColors; - } - - private void writeGeometry(BlockRenderContext ctx, - ChunkModelBuilder builder, - Vec3 offset, - Material material, - BakedQuadView quad, - int[] colors, - QuadLightData light) - { - ModelQuadOrientation orientation = ModelQuadOrientation.orientByBrightness(light.br, light.lm); - var vertices = this.vertices; - - ModelQuadFacing normalFace = quad.getNormalFace(); - - for (int dstIndex = 0; dstIndex < 4; dstIndex++) { - int srcIndex = orientation.getVertexIndex(dstIndex); - - var out = vertices[dstIndex]; - out.x = ctx.origin().x() + quad.getX(srcIndex) + (float) offset.x(); - out.y = ctx.origin().y() + quad.getY(srcIndex) + (float) offset.y(); - out.z = ctx.origin().z() + quad.getZ(srcIndex) + (float) offset.z(); - - out.color = ColorABGR.withAlpha(colors != null ? colors[srcIndex] : 0xFFFFFFFF, light.br[srcIndex]); - - out.u = quad.getTexU(srcIndex); - out.v = quad.getTexV(srcIndex); - - out.light = light.lm[srcIndex]; - } - - if (material.isTranslucent() && ctx.collector != null) { - ctx.collector.appendQuad(quad.getNormal(), vertices, normalFace); - } - - var vertexBuffer = builder.getVertexBuffer(normalFace); - vertexBuffer.push(vertices, material); - } - - private LightMode getLightingMode(BlockState state, BakedModel model) { - if (this.useAmbientOcclusion && model.useAmbientOcclusion() && state.getLightEmission() == 0) { - return LightMode.SMOOTH; - } else { - return LightMode.FLAT; - } - } -} diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/ModelPartData.java b/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/ModelPartData.java deleted file mode 100644 index 21737f6464..0000000000 --- a/src/main/java/net/caffeinemc/mods/sodium/client/render/immediate/model/ModelPartData.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.caffeinemc.mods.sodium.client.render.immediate.model; - -import net.minecraft.client.model.geom.ModelPart; - -public interface ModelPartData { - static ModelPartData from(ModelPart part) { - return (ModelPartData) (Object) part; - } - - ModelCuboid[] getCuboids(); - ModelPart[] getChildren(); - - boolean isVisible(); - boolean isHidden(); -} diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/world/biome/BiomeColorSource.java b/src/main/java/net/caffeinemc/mods/sodium/client/world/biome/BiomeColorSource.java deleted file mode 100644 index c8c13129dd..0000000000 --- a/src/main/java/net/caffeinemc/mods/sodium/client/world/biome/BiomeColorSource.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.caffeinemc.mods.sodium.client.world.biome; - -import net.minecraft.client.renderer.BiomeColors; -import net.minecraft.world.level.ColorResolver; - -public enum BiomeColorSource { - GRASS, - FOLIAGE, - WATER; - - public static final BiomeColorSource[] VALUES = BiomeColorSource.values(); - public static final int COUNT = VALUES.length; - - public static BiomeColorSource from(ColorResolver resolver) { - if (resolver == BiomeColors.GRASS_COLOR_RESOLVER) { - return GRASS; - } else if (resolver == BiomeColors.FOLIAGE_COLOR_RESOLVER) { - return FOLIAGE; - } else if (resolver == BiomeColors.WATER_COLOR_RESOLVER) { - return WATER; - } - - throw new UnsupportedOperationException(); - } -} diff --git a/src/main/java/net/caffeinemc/mods/sodium/client/world/biome/BiomeColorView.java b/src/main/java/net/caffeinemc/mods/sodium/client/world/biome/BiomeColorView.java deleted file mode 100644 index e064e75476..0000000000 --- a/src/main/java/net/caffeinemc/mods/sodium/client/world/biome/BiomeColorView.java +++ /dev/null @@ -1,5 +0,0 @@ -package net.caffeinemc.mods.sodium.client.world.biome; - -public interface BiomeColorView { - int getColor(BiomeColorSource resolver, int blockX, int blockY, int blockZ); -} diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/MainTargetMixin.java b/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/MainTargetMixin.java deleted file mode 100644 index 0b2fc9e511..0000000000 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/debug/checks/MainTargetMixin.java +++ /dev/null @@ -1,17 +0,0 @@ -package net.caffeinemc.mods.sodium.mixin.debug.checks; - -import com.mojang.blaze3d.pipeline.MainTarget; -import net.caffeinemc.mods.sodium.client.render.util.RenderAsserts; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(MainTarget.class) -public class MainTargetMixin { - @Redirect(method = { - "" - }, at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;isOnRenderThread()Z")) - private boolean validateCurrentThread$init() { - return RenderAsserts.validateCurrentThread(); - } -} diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/CubeMixin.java b/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/CubeMixin.java deleted file mode 100644 index 5417d831c1..0000000000 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/CubeMixin.java +++ /dev/null @@ -1,31 +0,0 @@ -package net.caffeinemc.mods.sodium.mixin.features.render.entity; - -import net.caffeinemc.mods.sodium.client.model.ModelCuboidAccessor; -import net.caffeinemc.mods.sodium.client.render.immediate.model.ModelCuboid; -import net.minecraft.client.model.geom.ModelPart; -import net.minecraft.core.Direction; -import org.objectweb.asm.Opcodes; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.Set; - -@Mixin(ModelPart.Cube.class) -public class CubeMixin implements ModelCuboidAccessor { - @Unique - private ModelCuboid sodium$cuboid; - - // Inject at the start of the function, so we don't capture modified locals - @Inject(method = "", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/client/model/geom/ModelPart$Cube;polygons:[Lnet/minecraft/client/model/geom/ModelPart$Polygon;", ordinal = 0)) - private void onInit(int u, int v, float x, float y, float z, float sizeX, float sizeY, float sizeZ, float extraX, float extraY, float extraZ, boolean mirror, float textureWidth, float textureHeight, Set renderDirections, CallbackInfo ci) { - this.sodium$cuboid = new ModelCuboid(u, v, x, y, z, sizeX, sizeY, sizeZ, extraX, extraY, extraZ, mirror, textureWidth, textureHeight, renderDirections); - } - - @Override - public ModelCuboid sodium$copy() { - return this.sodium$cuboid; - } -} diff --git a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/ModelPartMixin.java b/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/ModelPartMixin.java deleted file mode 100644 index c22553ab10..0000000000 --- a/src/main/java/net/caffeinemc/mods/sodium/mixin/features/render/entity/ModelPartMixin.java +++ /dev/null @@ -1,136 +0,0 @@ -package net.caffeinemc.mods.sodium.mixin.features.render.entity; - -import net.caffeinemc.mods.sodium.api.util.ColorARGB; -import net.caffeinemc.mods.sodium.client.model.ModelCuboidAccessor; -import net.caffeinemc.mods.sodium.client.render.immediate.model.EntityRenderer; -import net.caffeinemc.mods.sodium.client.render.immediate.model.ModelCuboid; -import net.caffeinemc.mods.sodium.client.render.immediate.model.ModelPartData; -import net.caffeinemc.mods.sodium.client.render.vertex.VertexConsumerUtils; -import net.caffeinemc.mods.sodium.api.math.MatrixHelper; -import net.caffeinemc.mods.sodium.api.util.ColorABGR; -import net.caffeinemc.mods.sodium.api.vertex.buffer.VertexBufferWriter; -import net.minecraft.client.model.geom.ModelPart; -import org.spongepowered.asm.mixin.*; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -@Mixin(ModelPart.class) -public class ModelPartMixin implements ModelPartData { - @Shadow - public float x; - @Shadow - public float y; - @Shadow - public float z; - - @Shadow - public float xScale; - @Shadow - public float yScale; - @Shadow - public float zScale; - - @Shadow - public float yRot; - @Shadow - public float xRot; - @Shadow - public float zRot; - - @Shadow - public boolean visible; - @Shadow - public boolean skipDraw; - - @Mutable - @Shadow - @Final - private List cubes; - - @Mutable - @Shadow - @Final - private Map children; - - @Unique - private ModelPart[] sodium$children; - - @Unique - private ModelCuboid[] sodium$cuboids; - - @Inject(method = "", at = @At("RETURN")) - private void onInit(List cuboids, Map children, CallbackInfo ci) { - var copies = new ModelCuboid[cuboids.size()]; - - for (int i = 0; i < cuboids.size(); i++) { - var accessor = (ModelCuboidAccessor) cuboids.get(i); - copies[i] = accessor.sodium$copy(); - } - - this.sodium$cuboids = copies; - this.sodium$children = children.values() - .toArray(ModelPart[]::new); - - // Try to catch errors caused by mods touching the collections after we've copied everything. - this.cubes = Collections.unmodifiableList(this.cubes); - this.children = Collections.unmodifiableMap(this.children); - } - - @Inject(method = "render(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;III)V", at = @At("HEAD"), cancellable = true) - private void onRender(PoseStack matrices, VertexConsumer vertices, int light, int overlay, int argb, CallbackInfo ci) { - VertexBufferWriter writer = VertexConsumerUtils.convertOrLog(vertices); - - if (writer == null) { - return; - } - - ci.cancel(); - - EntityRenderer.render(matrices, writer, (ModelPart) (Object) this, light, overlay, ColorARGB.toABGR(argb)); - } - - /** - * @author JellySquid - * @reason Apply transform more quickly - */ - @Overwrite - public void translateAndRotate(PoseStack matrixStack) { - if (this.x != 0.0F || this.y != 0.0F || this.z != 0.0F) { - matrixStack.translate(this.x * (1.0f / 16.0f), this.y * (1.0f / 16.0f), this.z * (1.0f / 16.0f)); - } - - if (this.xRot != 0.0F || this.yRot != 0.0F || this.zRot != 0.0F) { - MatrixHelper.rotateZYX(matrixStack.last(), this.zRot, this.yRot, this.xRot); - } - - if (this.xScale != 1.0F || this.yScale != 1.0F || this.zScale != 1.0F) { - matrixStack.scale(this.xScale, this.yScale, this.zScale); - } - } - - @Override - public ModelCuboid[] getCuboids() { - return this.sodium$cuboids; - } - - @Override - public boolean isVisible() { - return this.visible; - } - - @Override - public boolean isHidden() { - return this.skipDraw; - } - - @Override - public ModelPart[] getChildren() { - return this.sodium$children; - } -} diff --git a/src/main/resources/assets/sodium/shaders/include/chunk_vertex.glsl b/src/main/resources/assets/sodium/shaders/include/chunk_vertex.glsl deleted file mode 100644 index 3f3b9e3225..0000000000 --- a/src/main/resources/assets/sodium/shaders/include/chunk_vertex.glsl +++ /dev/null @@ -1,74 +0,0 @@ -// The position of the vertex around the model origin -vec3 _vert_position; - -// The block texture coordinate of the vertex -vec2 _vert_tex_diffuse_coord; - -// The light texture coordinate of the vertex -vec2 _vert_tex_light_coord; - -// The color of the vertex -vec4 _vert_color; - -// The index of the draw command which this vertex belongs to -uint _draw_id; - -// The material bits for the primitive -uint _material_params; - -const int POSITION_BITS = 20; -const int TEXTURE_BITS = 15; -const int LIGHT_BITS = 8; - -const float POSITION_MAX_COORD = 1 << POSITION_BITS; -const float TEXTURE_MAX_COORD = 1 << TEXTURE_BITS; -const float LIGHT_MAX_COORD = 1 << LIGHT_BITS; - -const float MODEL_SCALE = 32.0 / POSITION_MAX_COORD; -const float MODEL_TRANSLATION = -8.0; - -const float TEXTURE_FUZZ_AMOUNT = 1.0 / 64.0; -const float TEXTURE_GROW_FACTOR = (1.0 - TEXTURE_FUZZ_AMOUNT) / TEXTURE_MAX_COORD; - -in vec3 a_PositionHi; // 3x Unsigned 10-bit integer -in vec3 a_PositionLo; // ... -in vec4 a_Color; // 4x Unsigned 8-bit integer (normalized) -in uvec2 a_TexCoord; // 2x Signed 16-bit integer -in uvec4 a_LightAndData; // 4x Unsigned 8-bit integer - -vec3 _decode_position(vec3 hi, vec3 lo) { - // The 2.10.10.10 vertex formats do not support being interpreted as integer data within the shader. - // Because of this, we need to emulate the bitwise ops with floating-point arithmetic. There is probably no - // performance penalty to doing this (other than making things uglier) since GPUs typically have the same - // throughput for Fp32 mul/add and Int32 shl/or operations. - - vec3 interleaved = (hi * (1 << 10)) + lo; // (hi << 10) | lo - vec3 normalized = (interleaved * MODEL_SCALE) + MODEL_TRANSLATION; - - return normalized; -} - -vec2 _decode_texcoord(uvec2 value) { - // Normalize the texture coordinate, shifting out the LSB which stores the bias value. - vec2 coord = vec2(value >> 1) / TEXTURE_MAX_COORD; - - // Using the LSB, identify the sign of the bias (-1.0 or +1.0) - vec2 bias = mix(vec2(-TEXTURE_GROW_FACTOR), vec2(+TEXTURE_GROW_FACTOR), bvec2(value & 1u)); - - return coord + bias; -} - -vec2 _decode_light(uvec2 value) { - return vec2(value) * (1.0 / LIGHT_MAX_COORD); -} - -void _vert_init() { - _vert_position = _decode_position(a_PositionHi, a_PositionLo); - _vert_color = a_Color; - _vert_tex_diffuse_coord = _decode_texcoord(a_TexCoord); - - _vert_tex_light_coord = _decode_light(a_LightAndData.xy); - - _material_params = a_LightAndData[2]; - _draw_id = a_LightAndData[3]; -} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json deleted file mode 100644 index 2b55cd7c14..0000000000 --- a/src/main/resources/fabric.mod.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "schemaVersion": 1, - "id": "sodium", - "version": "${version}", - "name": "Sodium", - "description": "Sodium is a powerful rendering engine for Minecraft which greatly improves frame rates and micro-stutter, while fixing many graphical issues", - "authors": [ - { - "name": "@jellysquid3", - "contact": { - "email": "jellysquid@pm.me", - "homepage": "https://jellysquid.me" - } - } - ], - "contributors": [ - "@IMS212", - "@bytzo", - "@PepperCode1", - "@FlashyReese", - "@altrisi", - "@Grayray75", - "@Madis0", - "@Johni0702", - "@comp500", - "@coderbot16", - "@Moulberry", - "@MCRcortex", - "@Altirix", - "@embeddedt", - "@pajicadvance", - "@Kroppeb", - "@douira", - "@burgerindividual", - "@TwistedZero", - "@Leo40Git", - "@haykam821" - ], - "contact": { - "homepage": "https://github.com/CaffeineMC/sodium-fabric", - "sources": "https://github.com/CaffeineMC/sodium-fabric", - "issues": "https://github.com/CaffeineMC/sodium-fabric/issues" - }, - "license": "Polyform-Shield-1.0.0", - "icon": "assets/sodium/icon.png", - "environment": "client", - "entrypoints": { - "client": [ - "net.caffeinemc.mods.sodium.client.SodiumClientMod" - ], - "preLaunch": [ - "net.caffeinemc.mods.sodium.client.SodiumPreLaunch" - ] - }, - "custom": { - "fabric-renderer-api-v1:contains_renderer": true, - "modmenu": { - "links": { - "modmenu.donate": "https://caffeinemc.net/donate", - "modmenu.discord": "https://caffeinemc.net/discord", - "modmenu.github_releases": "https://github.com/CaffeineMC/sodium-fabric/releases", - "modmenu.kofi": "https://caffeinemc.net/donate", - "modmenu.modrinth": "https://modrinth.com/mod/sodium" - } - } - }, - "accessWidener": "sodium.accesswidener", - "mixins": [ - "sodium.mixins.json" - ], - "depends": { - "fabricloader": ">=0.12.0", - "fabric-block-view-api-v2": "*", - "fabric-renderer-api-v1": "*", - "fabric-rendering-data-attachment-v1": "*", - "fabric-rendering-fluids-v1": ">=2.0.0", - "fabric-resource-loader-v0": "*", - "minecraft": "1.21" - }, - "breaks": { - "optifabric": "*", - "canvas": "*", - "sodium-blendingregistry": "*", - "ocrenderfix_sodium": "*", - "betterfpsdist": "<1.20.1-3.8", - "bobby": "<5.0.1", - "cauldron_dyeing": "<1.0.11", - "cullleaves": "<=3.1.0", - "custom_hud": "<=3.1.0+1.20", - "dashloader": "<5.0.0-beta.2", - "farsight": "<1.20.1-4.0", - "fluidvoidfading": "<1.1.2", - "iceberg": "<1.1.14", - "iris": "<=1.6.14", - "immersive_portals": "<=5.1.3", - "indium": "<=1.0.28", - "notenoughcrashes": "<4.4.6", - "noxesium": "<1.0.2", - "rayon": "<=1.7.2+1.20.1", - "reeses-sodium-options": "<1.7.1", - "sodium-extra": "<0.5.4", - "sspb": "<3.2.0", - "supplementaries": "<=1.20-2.7.32" - } -}