Skip to content

Commit

Permalink
Add support for editing Sodium core shaders in resource packs
Browse files Browse the repository at this point in the history
  • Loading branch information
Aeltumn committed Jul 25, 2024
1 parent ede0253 commit 8d54e4b
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 4 deletions.
72 changes: 72 additions & 0 deletions fabric/src/main/java/com/noxcrew/noxesium/NoxesiumMod.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.noxcrew.noxesium;

import com.google.common.base.Preconditions;
import com.mojang.blaze3d.shaders.Program;
import com.noxcrew.noxesium.api.protocol.ClientSettings;
import com.noxcrew.noxesium.api.protocol.ProtocolVersion;
import com.noxcrew.noxesium.config.NoxesiumConfig;
Expand All @@ -24,17 +25,27 @@
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.fabricmc.fabric.api.resource.SimpleResourceReloadListener;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.resources.Resource;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.util.profiling.ProfilerFiller;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;

/**
* The main file for the client-side implementation of Noxesium.
Expand Down Expand Up @@ -62,6 +73,12 @@ public class NoxesiumMod implements ClientModInitializer {
*/
private boolean initialized = false;

/**
* The mapping of cached shaders.
*/
@Nullable
private GameRenderer.ResourceCache cachedShaders = null;

private final NoxesiumConfig config = NoxesiumConfig.load();
private final Logger logger = LoggerFactory.getLogger("Noxesium");

Expand All @@ -86,6 +103,14 @@ public NoxesiumConfig getConfig() {
return config;
}

/**
* Returns a cache with all shaders in the Sodium namespace.
*/
@Nullable
public GameRenderer.ResourceCache getCachedShaders() {
return cachedShaders;
}

/**
* Adds a new module to the list of modules that should have
* their hooks called. Available for other mods to use.
Expand Down Expand Up @@ -177,6 +202,53 @@ public void onInitializeClient() {
// Trigger registration of all server and entity rules
Object ignored = ServerRules.DISABLE_SPIN_ATTACK_COLLISIONS;
ignored = ExtraEntityData.DISABLE_BUBBLES;

// Listen to shaders that are loaded and cache them
ResourceManagerHelper
.get(PackType.CLIENT_RESOURCES)
.registerReloadListener(
new SimpleResourceReloadListener<Void>() {
@Override
public ResourceLocation getFabricId() {
return ResourceLocation.fromNamespaceAndPath(ProtocolVersion.NAMESPACE, "shaders");
}

@Override
public CompletableFuture<Void> load(ResourceManager manager, ProfilerFiller profiler, Executor executor) {
return CompletableFuture.supplyAsync(() -> {
var map = manager.listResources(
"shaders",
folder -> {
// We include all namespaces because you need to be able to import shaders from elsewhere!
var s = folder.getPath();
return s.endsWith(".json")
|| s.endsWith(Program.Type.FRAGMENT.getExtension())
|| s.endsWith(Program.Type.VERTEX.getExtension())
|| s.endsWith(".glsl");
}
);
var map1 = new HashMap<ResourceLocation, Resource>();
map.forEach((key, value) -> {
try (InputStream inputstream = value.open()) {
byte[] abyte = inputstream.readAllBytes();
map1.put(ResourceLocation.fromNamespaceAndPath(key.getNamespace(), key.getPath().substring("shaders/".length())), new Resource(value.source(), () -> new ByteArrayInputStream(abyte)));
} catch (Exception exception) {
getLogger().warn("Failed to read resource {}", key, exception);
}
});

// Save the shaders here instead of in apply so we go before any other resource re-loader!
cachedShaders = new GameRenderer.ResourceCache(manager, map1);
return null;
});
}

@Override
public CompletableFuture<Void> apply(Void data, ResourceManager manager, ProfilerFiller profiler, Executor executor) {
return CompletableFuture.completedFuture(null);
}
}
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.noxcrew.noxesium.feature.rule;

import com.mojang.blaze3d.systems.RenderSystem;
import com.noxcrew.noxesium.NoxesiumMod;
import com.noxcrew.noxesium.api.protocol.rule.ServerRuleIndices;
import com.noxcrew.noxesium.feature.rule.impl.BooleanServerRule;
Expand Down Expand Up @@ -89,7 +90,13 @@ public class ServerRules {
public static OptionalEnumServerRule<GraphicsStatus> OVERRIDE_GRAPHICS_MODE = register(new OptionalEnumServerRule<>(ServerRuleIndices.OVERRIDE_GRAPHICS_MODE, GraphicsStatus.class, Optional.empty(), () -> {
// We need to call this whenever we change the display type.
if (Minecraft.getInstance().levelRenderer != null) {
Minecraft.getInstance().levelRenderer.allChanged();
if (RenderSystem.isOnRenderThread()) {
Minecraft.getInstance().levelRenderer.allChanged();
} else {
RenderSystem.recordRenderCall(() -> {
Minecraft.getInstance().levelRenderer.allChanged();
});
}
}
}));

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.noxcrew.noxesium.mixin.sodium;

import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.noxcrew.noxesium.NoxesiumMod;
import me.jellysquid.mods.sodium.client.gl.shader.ShaderLoader;
import net.minecraft.resources.ResourceLocation;
import org.apache.commons.io.IOUtils;
import org.spongepowered.asm.mixin.Mixin;

import java.nio.charset.StandardCharsets;

/**
* Based on <a href="https://github.com/lni-dev/SodiumCoreShaderSupport/blob/1.20.6/src/main/java/de/linusdev/mixin/MixinShaderLoader.java">Sodium Core Shader Support</a>.
* <p>
* Sodium has indicated they do not want to add core shader support natively, the discussion of why is best left to other places.
* But in practice this leaves server developers that want to use core shaders with half their players being unable to see them. So, Noxesium
* lets you edit the shaders but acknowledges that it is entirely the responsibility of the server developer to fix any issues that occur.
* <p>
* Using Sodium's core shaders on a public server is irresponsible and entirely your problem if it causes issues. This system is meant for
* private servers where you can guarantee the version clients are using. But I'm a code comment, not a cop, I can't stop you.
*/
@Mixin(value = ShaderLoader.class, remap = false)
public class SodiumShaderLoaderMixin {

@WrapMethod(method = "getShaderSource")
private static String noxesium$getShaderSource(ResourceLocation name, Operation<String> original) {
// Determine if this shader is being provided by some resource pack, we fall back to Sodium
// if anything goes wrong while doing so!
var cache = NoxesiumMod.getInstance().getCachedShaders();
var resource = cache != null ? cache.cache().get(name) : null;
if (resource != null) {
try {
return IOUtils.toString(resource.open(), StandardCharsets.UTF_8);
} catch (Exception x) {
NoxesiumMod.getInstance().getLogger().error("Exception while reading shader for source {} from resource pack", name);
}
}
return original.call(name);
}
}
5 changes: 3 additions & 2 deletions fabric/src/main/resources/noxesium-sodium.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
"package": "com.noxcrew.noxesium.mixin.sodium",
"compatibilityLevel": "JAVA_17",
"client": [
"SodiumOptionImplMixin",
"SodiumRenderSectionManagerMixin",
"SodiumVideoSettingsMenuMixin",
"SodiumOptionImplMixin"
"SodiumShaderLoaderMixin",
"SodiumVideoSettingsMenuMixin"
],
"injectors": {
"defaultRequire": 1
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ loader_version=0.15.11
# Fabric API
fabric_version=0.100.1+1.21
# Mod Properties
mod_version=2.1.2
mod_version=2.1.3

# Mod dependencies
sodium = mc1.21-0.5.9
Expand Down

0 comments on commit 8d54e4b

Please sign in to comment.