From 92785bee0d243e0bc8ded7a6be991d3baf74930f Mon Sep 17 00:00:00 2001 From: your-github-username Date: Sun, 16 Aug 2026 03:48:30 +0000 Subject: [PATCH] Fall back to owning mod's jar when a shader isn't found in VulkanMod's own jar ShaderLoadUtil.getShaderSource(Identifier, ShaderType) discards the Identifier's namespace and only ever looks inside VulkanMod's own jar (RESOURCES_PATH is hardcoded to /assets/vulkanmod). Any mod that registers a custom RenderPipeline pointing at shaders bundled in its own jar -- e.g. malilib's legacy terrain pipelines, used by Litematica for schematic rendering -- silently fails to resolve, breaking compilation of that pipeline (manifests as blank/miscolored schematics under VulkanMod). This adds a fallback: when the in-jar lookup misses, resolve the Identifier's namespace to its actual owning mod via Fabric Loader's ModContainer API and read the shader from that mod's real resource root, using the same two-tier path/name.ext -> path.ext lookup order already used for VulkanMod's own shaders. Tested against Litematica + malilib on 1.21.11: schematic rendering that was previously blank now renders correctly with VulkanMod enabled. --- .../render/shader/ShaderLoadUtil.java | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/vulkanmod/render/shader/ShaderLoadUtil.java b/src/main/java/net/vulkanmod/render/shader/ShaderLoadUtil.java index 93b5db820..e2a4f6554 100644 --- a/src/main/java/net/vulkanmod/render/shader/ShaderLoadUtil.java +++ b/src/main/java/net/vulkanmod/render/shader/ShaderLoadUtil.java @@ -5,6 +5,8 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.mojang.blaze3d.shaders.ShaderType; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; import net.minecraft.resources.Identifier; import net.vulkanmod.vulkan.shader.SpirvCompiler; import org.apache.commons.io.IOUtils; @@ -12,11 +14,13 @@ import java.io.*; import java.net.URI; import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; +import java.util.Optional; import java.util.Set; public abstract class ShaderLoadUtil { @@ -127,7 +131,11 @@ public static String getShaderSource(Identifier resourceLocation, ShaderType typ } if (stream == null) { - return null; + // Not found in VulkanMod's own jar. This RenderPipeline may belong to + // another mod (e.g. malilib's custom terrain pipelines used by Litematica), + // with its shader bundled in that mod's own jar. Resolve the Identifier's + // namespace to its actual owning mod and look there instead of giving up. + return getShaderSourceFromOwningMod(resourceLocation, shaderName, shaderExtension); } String source = IOUtils.toString(new BufferedReader(new InputStreamReader(stream))); @@ -139,6 +147,43 @@ public static String getShaderSource(Identifier resourceLocation, ShaderType typ } } + /** + * Fallback for {@link #getShaderSource(Identifier, ShaderType)} when a shader isn't + * found inside VulkanMod's own jar. Resolves {@code resourceLocation}'s namespace to its + * owning mod via Fabric Loader and reads the shader straight from that mod's real + * resource root (works the same in a dev environment or a packaged jar), mirroring the + * same two-tier {@code path/name.ext} -> {@code path.ext} lookup order used above. + */ + private static String getShaderSourceFromOwningMod(Identifier resourceLocation, String shaderName, String shaderExtension) { + String namespace = resourceLocation.getNamespace(); + String path = resourceLocation.getPath(); + + Optional container = FabricLoader.getInstance().getModContainer(namespace); + + if (container.isEmpty()) { + return null; + } + + String[] candidates = { + "assets/%s/shaders/%s/%s".formatted(namespace, path, shaderName), + "assets/%s/shaders/%s%s".formatted(namespace, path, shaderExtension) + }; + + for (String candidate : candidates) { + Optional found = container.get().findPath(candidate); + + if (found.isPresent() && Files.isRegularFile(found.get())) { + try { + return Files.readString(found.get(), StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + return null; + } + public static String getShaderSource(String path, ShaderType type) { String shaderExtension = switch (type) { case VERTEX -> ".vsh";