From edd0ce33efd43d1175034b297eea16f04b3537ef Mon Sep 17 00:00:00 2001 From: mcrcortex <18544518+MCRcortex@users.noreply.github.com> Date: Sun, 14 Dec 2025 18:03:54 +1000 Subject: [PATCH] update mods 1.21.11 --- .../voxy/client/config/IConfigPageSetter.java | 8 + .../client/config/ModMenuIntegration.java | 19 +- .../client/config/SodiumConfigBuilder.java | 367 ++++++++++++++++++ .../voxy/client/config/VoxyConfigMenu.java | 149 +++++++ .../client/config/VoxyConfigScreenPages.java | 3 +- .../voxy/client/core/model/TextureUtils.java | 11 +- .../iris/IrisVoxyRenderPipelineData.java | 17 +- .../sodium/MixinDefaultChunkRenderer.java | 7 +- .../sodium/MixinRenderRegionManager.java | 29 ++ .../mixin/sodium/MixinSodiumOptionsGUI.java | 27 -- .../sodium/MixinVideoSettingsScreen.java | 34 ++ .../resources/assets/voxy/lang/en_us.json | 3 + src/main/resources/client.voxy.mixins.json | 3 +- src/main/resources/fabric.mod.json | 3 + 14 files changed, 625 insertions(+), 55 deletions(-) create mode 100644 src/main/java/me/cortex/voxy/client/config/IConfigPageSetter.java create mode 100644 src/main/java/me/cortex/voxy/client/config/SodiumConfigBuilder.java create mode 100644 src/main/java/me/cortex/voxy/client/config/VoxyConfigMenu.java create mode 100644 src/main/java/me/cortex/voxy/client/mixin/sodium/MixinRenderRegionManager.java delete mode 100644 src/main/java/me/cortex/voxy/client/mixin/sodium/MixinSodiumOptionsGUI.java create mode 100644 src/main/java/me/cortex/voxy/client/mixin/sodium/MixinVideoSettingsScreen.java diff --git a/src/main/java/me/cortex/voxy/client/config/IConfigPageSetter.java b/src/main/java/me/cortex/voxy/client/config/IConfigPageSetter.java new file mode 100644 index 00000000..81c6ed4b --- /dev/null +++ b/src/main/java/me/cortex/voxy/client/config/IConfigPageSetter.java @@ -0,0 +1,8 @@ +package me.cortex.voxy.client.config; + +import net.caffeinemc.mods.sodium.client.config.structure.OptionPage; +import net.caffeinemc.mods.sodium.client.config.structure.Page; + +public interface IConfigPageSetter { + void voxy$setPageJump(OptionPage page); +} diff --git a/src/main/java/me/cortex/voxy/client/config/ModMenuIntegration.java b/src/main/java/me/cortex/voxy/client/config/ModMenuIntegration.java index 73ca3c41..9df2e093 100644 --- a/src/main/java/me/cortex/voxy/client/config/ModMenuIntegration.java +++ b/src/main/java/me/cortex/voxy/client/config/ModMenuIntegration.java @@ -4,25 +4,18 @@ import com.terraformersmc.modmenu.api.ConfigScreenFactory; import com.terraformersmc.modmenu.api.ModMenuApi; import me.cortex.voxy.common.Logger; import me.cortex.voxy.commonImpl.VoxyCommon; -import net.caffeinemc.mods.sodium.client.gui.SodiumOptionsGUI; +import net.caffeinemc.mods.sodium.client.config.ConfigManager; +import net.caffeinemc.mods.sodium.client.config.structure.OptionPage; +import net.caffeinemc.mods.sodium.client.gui.VideoSettingsScreen; public class ModMenuIntegration implements ModMenuApi { @Override public ConfigScreenFactory getModConfigScreenFactory() { return parent -> { if (VoxyCommon.isAvailable()) { - var screen = (SodiumOptionsGUI) SodiumOptionsGUI.createScreen(parent); - //Sorry jelly and douira, please dont hurt me - try { - //We cant use .setPage() as that invokes rebuildGui, however the screen hasnt been initalized yet - // causing things to crash - var field = SodiumOptionsGUI.class.getDeclaredField("currentPage"); - field.setAccessible(true); - field.set(screen, VoxyConfigScreenPages.voxyOptionPage); - field.setAccessible(false); - } catch (Exception e) { - Logger.error("Failed to set the current page to voxy", e); - } + var screen = (VideoSettingsScreen)VideoSettingsScreen.createScreen(parent); + var page = (OptionPage) ConfigManager.CONFIG.getModOptions().stream().filter(a->a.configId().equals("voxy")).findFirst().get().pages().get(0); + ((IConfigPageSetter)screen).voxy$setPageJump(page); return screen; } else { return null; diff --git a/src/main/java/me/cortex/voxy/client/config/SodiumConfigBuilder.java b/src/main/java/me/cortex/voxy/client/config/SodiumConfigBuilder.java new file mode 100644 index 00000000..ea731aab --- /dev/null +++ b/src/main/java/me/cortex/voxy/client/config/SodiumConfigBuilder.java @@ -0,0 +1,367 @@ +package me.cortex.voxy.client.config; + +import me.cortex.voxy.common.util.Pair; +import net.caffeinemc.mods.sodium.api.config.ConfigState; +import net.caffeinemc.mods.sodium.api.config.StorageEventHandler; +import net.caffeinemc.mods.sodium.api.config.option.ControlValueFormatter; +import net.caffeinemc.mods.sodium.api.config.option.OptionFlag; +import net.caffeinemc.mods.sodium.api.config.option.Range; +import net.caffeinemc.mods.sodium.api.config.structure.*; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.contents.TranslatableContents; +import net.minecraft.resources.Identifier; +import org.jetbrains.annotations.Nullable; + +import java.util.*; +import java.util.function.*; + +public class SodiumConfigBuilder { + + private static record Enabler(Predicate tester, Identifier[] dependencies) { + public Enabler(Predicate tester, String[] dependencies) { + this(tester, mapIds(dependencies)); + } + } + + public abstract static class Enableable > { + private @Nullable Enabler prevEnabler; + protected @Nullable Enabler enabler; + + private TYPE setEnabler0(Enabler enabler) { + this.prevEnabler = this.enabler; + this.enabler = enabler; + { + var children = this.getEnablerChildren(); + if (children != null) { + for (var child : children) { + if (child.enabler == null || child.enabler == this.prevEnabler) { + child.setEnabler0(this.enabler); + } + } + } + } + + return (TYPE) this; + } + + public TYPE setEnabler(Predicate enabler, String... dependencies) { + return this.setEnabler0(new Enabler(enabler, dependencies)); + } + + public TYPE setEnabler(String enabler) { + if (enabler == null) { + return this.setEnabler(s->true); + } + var id = Identifier.parse(enabler); + return this.setEnabler(s->s.readBooleanOption(id), enabler); + } + + public TYPE setEnablerAND(String... enablers) { + var enablersId = mapIds(enablers); + return this.setEnabler0(new Enabler(s->{ + for (var id : enablersId) { + if (!s.readBooleanOption(id)) { + return false; + } + } + return true; + }, enablersId)); + } + + protected Enableable[] getEnablerChildren() { + return null; + } + } + + public static class Page extends Enableable { + protected Component name; + protected Group[] groups; + public Page(Component name, Group... groups) { + this.name = name; + this.groups = groups; + } + + protected OptionPageBuilder create(ConfigBuilder builder, BuildCtx ctx) { + var page = builder.createOptionPage(); + page.setName(this.name); + for (var group : this.groups) { + page.addOptionGroup(group.create(builder, ctx)); + } + return page; + } + + @Override + protected Enableable[] getEnablerChildren() { + return this.groups; + } + } + + public static class Group extends Enableable { + protected Option[] options; + public Group(Option... options) { + this.options = options; + } + + protected OptionGroupBuilder create(ConfigBuilder builder, BuildCtx ctx) { + var group = builder.createOptionGroup(); + for (var option : this.options) { + group.addOption(option.create(builder, ctx)); + } + return group; + } + + @Override + protected Enableable[] getEnablerChildren() { + return this.options; + } + } + + public static abstract class Option , STYPE extends StatefulOptionBuilder> extends Enableable> { + //Setter returns a post save update set + protected String id; + protected Component name; + protected Component tooltip; + protected Supplier getter; + protected Consumer setter; + public Option(String id, Component name, Component tooltip, Supplier getter, Consumer setter) { + this.id = id; + this.name = name; + this.tooltip = tooltip; + this.getter = getter; + this.setter = setter; + } + + public Option(String id, Component name, Supplier getter, Consumer setter) { + this.id = id; + this.name = name; + this.getter = getter; + this.setter = setter; + if (name.getContents() instanceof TranslatableContents tc) { + this.tooltip = Component.translatable(tc.getKey() + ".tooltip"); + } else { + this.tooltip = name; + } + } + + + protected BiConsumer postRunner; + protected String[] postRunnerConflicts; + protected String[] postChangeFlags; + public OPTION setPostChangeRunner(BiConsumer postRunner, String... dontRunIfChangedVars) { + if (this.postChangeFlags != null) { + throw new IllegalStateException(); + } + this.postRunner = postRunner; + this.postRunnerConflicts = dontRunIfChangedVars; + return (OPTION) this; + } + + public OPTION setPostChangeFlags(String... flags) { + if (this.postRunner != null) { + throw new IllegalStateException(); + } + this.postChangeFlags = flags; + return (OPTION) this; + } + + protected abstract STYPE createType(ConfigBuilder builder); + + protected STYPE create(ConfigBuilder builder, BuildCtx ctx) { + var option = this.createType(builder); + option.setName(this.name); + option.setTooltip(this.tooltip); + + Consumer setter = this.setter; + if (this.postRunner != null) { + var pSetter = setter; + var getter = this.getter; + Object[] oldValue = new Object[1]; + var id = Identifier.parse(this.id).getPath(); + var flagAdder = ctx.addFlag; + setter = v->{ + oldValue[0] = getter.get(); + pSetter.accept(v); + flagAdder.accept(id); + }; + var runner = this.postRunner; + ctx.postRunner.register(id, ()->{ + var old = (TYPE) oldValue[0]; + var cur = getter.get(); + if (old != cur) { + runner.accept(old, cur); + } + oldValue[0] = null; + }, this.postRunnerConflicts); + } else if (this.postChangeFlags != null) { + List flags = new ArrayList<>(); + List oFlags = new ArrayList<>(); + for (var flag : this.postChangeFlags) { + if (flag.equalsIgnoreCase("RENDERER_RELOAD")) { + oFlags.add(OptionFlag.REQUIRES_RENDERER_RELOAD); + } + flags.add(flag); + } + + option.setFlags(oFlags.toArray(OptionFlag[]::new)); + + if (!flags.isEmpty()) { + var pSetter = setter; + var flagAdder = ctx.addFlag; + var sflags = flags.toArray(new String[0]); + setter = v -> { + pSetter.accept(v); + for (var flag : sflags) { + flagAdder.accept(flag); + } + }; + } + } + + + option.setBinding(setter, this.getter); + if (this.enabler != null) { + var pred = this.enabler.tester; + option.setEnabledProvider(s->pred.test(s), this.enabler.dependencies); + } + + option.setStorageHandler(ctx.saveHandler); + + option.setDefaultValue(this.getter.get()); + + return option; + } + } + + public static class IntOption extends Option { + protected Function rangeProvider; + protected String[] rangeDependencies; + protected ControlValueFormatter formatter = v->Component.literal(Integer.toString(v)); + + public IntOption(String id, Component name, Component tooltip, Supplier getter, Consumer setter, Range range) { + super(id, name, tooltip, getter, setter); + this.rangeProvider = s->range; + } + + public IntOption(String id, Component name, Supplier getter, Consumer setter, Range range) { + super(id, name, getter, setter); + this.rangeProvider = s->range; + } + + public IntOption setFormatter(IntFunction formatter) { + this.formatter = v->formatter.apply(v); + return this; + } + + @Override + protected IntegerOptionBuilder createType(ConfigBuilder builder) { + return builder.createIntegerOption(Identifier.parse(this.id)); + } + + @Override + protected IntegerOptionBuilder create(ConfigBuilder builder, BuildCtx ctx) { + var option = super.create(builder, ctx); + if (this.rangeDependencies == null || this.rangeDependencies.length == 0) { + option.setRange(this.rangeProvider.apply(null)); + } else { + option.setRangeProvider(this.rangeProvider, mapIds(this.rangeDependencies)); + } + option.setValueFormatter(this.formatter); + return option; + } + } + + public static class BoolOption extends Option { + public BoolOption(String id, Component name, Component tooltip, Supplier getter, Consumer setter) { + super(id, name, tooltip, getter, setter); + } + + public BoolOption(String id, Component name, Supplier getter, Consumer setter) { + super(id, name, getter, setter); + } + + @Override + protected BooleanOptionBuilder createType(ConfigBuilder builder) { + return builder.createBooleanOption(Identifier.parse(this.id)); + } + } + + private static T[] map(F[] from, Function mapper, Function factory) { + T[] arr = factory.apply(from.length); + for (int i = 0; i < from.length; i++) { + arr[i] = mapper.apply(from[i]); + } + return arr; + } + + private static Identifier[] mapIds(String[] strings) { + return map(strings, Identifier::parse, Identifier[]::new); + } + + + public static class PostApplyOps { + private Map> conflicts = new LinkedHashMap<>(); + private Map executors = new LinkedHashMap<>(); + private LinkedHashSet localFlagChanges = new LinkedHashSet<>(); + + public void register(String name, Runnable postRunner, String... conflicts) { + this.conflicts.put(name, new LinkedHashSet<>(List.of(conflicts))); + this.executors.put(name, postRunner); + } + + protected void build() { + boolean changed = false; + do { + changed = false; + for (var value : this.conflicts.values()) { + for (var ref : new LinkedHashSet<>(value)) { + changed |= value.addAll(this.conflicts.getOrDefault(ref, Collections.EMPTY_SET)); + } + } + } while (changed); + } + + protected void addFlag(String flag) { + this.localFlagChanges.add(flag); + } + + protected void run() { + if (this.localFlagChanges.isEmpty()) return; + var original = new HashSet<>(this.localFlagChanges); + var iter = this.localFlagChanges.iterator(); + while (iter.hasNext()) { + var flag = iter.next(); + if (!Collections.disjoint(this.conflicts.getOrDefault(flag, Collections.EMPTY_SET), original)) { + iter.remove(); + } + } + + for (var flag : this.localFlagChanges) { + var exec = this.executors.get(flag); + if (exec != null) exec.run(); + } + + this.localFlagChanges.clear(); + } + } + + + private static final class BuildCtx { + public PostApplyOps postRunner = new PostApplyOps(); + public Consumer addFlag = this.postRunner::addFlag; + public StorageEventHandler saveHandler; + } + + public static void buildToSodium(ConfigBuilder builder, ModOptionsBuilder options, Runnable saveHandler, Consumer registerOps, Page... pages) { + var ctx = new BuildCtx(); + registerOps.accept(ctx.postRunner); + var post = ctx.postRunner; + ctx.saveHandler = ()->{ + saveHandler.run(); + post.run(); + }; + for (var page : pages) { + options.addPage(page.create(builder, ctx)); + } + post.build(); + } +} diff --git a/src/main/java/me/cortex/voxy/client/config/VoxyConfigMenu.java b/src/main/java/me/cortex/voxy/client/config/VoxyConfigMenu.java new file mode 100644 index 00000000..4b5b7949 --- /dev/null +++ b/src/main/java/me/cortex/voxy/client/config/VoxyConfigMenu.java @@ -0,0 +1,149 @@ +package me.cortex.voxy.client.config; + +import me.cortex.voxy.client.RenderStatistics; +import me.cortex.voxy.client.config.SodiumConfigBuilder.*; +import me.cortex.voxy.client.VoxyClient; +import me.cortex.voxy.client.VoxyClientInstance; +import me.cortex.voxy.client.core.IGetVoxyRenderSystem; +import me.cortex.voxy.common.util.cpu.CpuLayout; +import me.cortex.voxy.commonImpl.VoxyCommon; +import net.caffeinemc.mods.sodium.api.config.ConfigEntryPoint; +import net.caffeinemc.mods.sodium.api.config.option.OptionFlag; +import net.caffeinemc.mods.sodium.api.config.option.OptionImpact; +import net.caffeinemc.mods.sodium.api.config.option.Range; +import net.caffeinemc.mods.sodium.api.config.structure.ConfigBuilder; +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.Identifier; + +public class VoxyConfigMenu implements ConfigEntryPoint { + @Override + public void registerConfigLate(ConfigBuilder B) { + var CFG = VoxyConfig.CONFIG; + + var cc = B.registerModOptions("voxy", "Voxy", VoxyCommon.MOD_VERSION) + .setIcon(Identifier.parse("voxy:icon.png")); + + SodiumConfigBuilder.buildToSodium(B, cc, CFG::save, postOp->{ + postOp.register("updateThreads", ()->{ + var instance = VoxyCommon.getInstance(); + if (instance != null) { + instance.updateDedicatedThreads(); + } + }, "enabled"); + }, + new Page(Component.translatable("voxy.config.general"), + new Group( + new BoolOption( + "voxy:enabled", + Component.translatable("voxy.config.general.enabled"), + ()->CFG.enabled, v->CFG.enabled=v) + .setPostChangeRunner((p,c)->{ + if (c) { + if (VoxyClientInstance.isInGame) { + VoxyCommon.createInstance(); + var vrsh = (IGetVoxyRenderSystem) Minecraft.getInstance().levelRenderer; + if (vrsh != null && CFG.enableRendering) { + vrsh.createRenderer(); + } + } + } else { + var vrsh = (IGetVoxyRenderSystem) Minecraft.getInstance().levelRenderer; + if (vrsh != null) { + vrsh.shutdownRenderer(); + } + VoxyCommon.shutdownInstance(); + } + }).setEnabler(null) + ), new Group( + new IntOption( + "voxy:thread_count", + Component.translatable("voxy.config.general.serviceThreads"), + ()->CFG.serviceThreads, v->CFG.serviceThreads=v, + new Range(1, CpuLayout.getCoreCount(), 1)) + .setPostChangeFlags("updateThreads"), + new BoolOption( + "voxy:use_sodium_threads", + Component.translatable("voxy.config.general.useSodiumBuilder"), + ()->!CFG.dontUseSodiumBuilderThreads, v->CFG.dontUseSodiumBuilderThreads=!v) + .setPostChangeFlags("updateThreads") + ), new Group( + new BoolOption( + "voxy:ingest_enabled", + Component.translatable("voxy.config.general.ingest"), + ()->CFG.ingestEnabled, v->CFG.ingestEnabled=v) + ) + ).setEnabler("voxy:enabled"), + new Page(Component.translatable("voxy.config.rendering"), + new Group( + new BoolOption( + "voxy:rendering", + Component.translatable("voxy.config.general.rendering"), + ()->CFG.enableRendering, v->CFG.enableRendering=v) + .setPostChangeRunner((p,c)->{ + var vrsh = (IGetVoxyRenderSystem)Minecraft.getInstance().levelRenderer; + if (vrsh != null) { + if (c) { + vrsh.createRenderer(); + } else { + vrsh.shutdownRenderer(); + } + } + },"enabled", "renderer_reload") + .setEnabler("voxy:enabled") + ), new Group( + new IntOption( + "voxy:subdivsize", + Component.translatable("voxy.config.general.subDivisionSize"), + ()->subDiv2ln(CFG.subDivisionSize), v->CFG.subDivisionSize=ln2subDiv(v), + new Range(0, SUBDIV_IN_MAX, 1)) + .setFormatter(v->Component.literal(Integer.toString(Math.round(ln2subDiv(v))))), + new IntOption( + "voxy:render_distance", + Component.translatable("voxy.config.general.renderDistance"), + ()->CFG.sectionRenderDistance, v->CFG.sectionRenderDistance=v, + new Range(2, 64, 1)) + .setFormatter(v->Component.literal(Integer.toString(v*32)))//Top level rd == 32 chunks + .setPostChangeRunner((p,c)->{ + var vrsh = (IGetVoxyRenderSystem)Minecraft.getInstance().levelRenderer; + if (vrsh != null) { + var vrs = vrsh.getVoxyRenderSystem(); + if (vrs != null) { + vrs.setRenderDistance(c); + } + } + }, "rendering", "renderer_reload") + ), new Group( + new BoolOption( + "voxy:eviromental_fog", + Component.translatable("voxy.config.general.environmental_fog"), + ()->CFG.useEnvironmentalFog, v->CFG.useEnvironmentalFog=v) + .setPostChangeFlags("renderer_reload") + ), new Group( + new BoolOption( + "voxy:render_debug", + Component.translatable("voxy.config.general.render_statistics"), + ()-> RenderStatistics.enabled, v->RenderStatistics.enabled=v) + .setPostChangeFlags("renderer_reload")) + ).setEnablerAND("voxy:enabled", "voxy:rendering")); + + } + + + private static final int SUBDIV_IN_MAX = 100; + private static final double SUBDIV_MIN = 28; + private static final double SUBDIV_MAX = 256; + private static final double SUBDIV_CONST = Math.log(SUBDIV_MAX/SUBDIV_MIN)/Math.log(2); + + //In range is 0->200 + //Out range is 28->256 + private static float ln2subDiv(int in) { + return (float) (SUBDIV_MIN*Math.pow(2, SUBDIV_CONST*((double)in/SUBDIV_IN_MAX))); + } + + //In range is ... any? + //Out range is 0->200 + private static int subDiv2ln(float in) { + return (int) (((Math.log(((double)in)/SUBDIV_MIN)/Math.log(2))/SUBDIV_CONST)*SUBDIV_IN_MAX); + } +} diff --git a/src/main/java/me/cortex/voxy/client/config/VoxyConfigScreenPages.java b/src/main/java/me/cortex/voxy/client/config/VoxyConfigScreenPages.java index 641e3a26..0fd19dbf 100644 --- a/src/main/java/me/cortex/voxy/client/config/VoxyConfigScreenPages.java +++ b/src/main/java/me/cortex/voxy/client/config/VoxyConfigScreenPages.java @@ -15,7 +15,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.network.chat.Component; import java.util.ArrayList; import java.util.List; - +/* public abstract class VoxyConfigScreenPages { private VoxyConfigScreenPages(){} @@ -181,3 +181,4 @@ public abstract class VoxyConfigScreenPages { } } +*/ \ No newline at end of file diff --git a/src/main/java/me/cortex/voxy/client/core/model/TextureUtils.java b/src/main/java/me/cortex/voxy/client/core/model/TextureUtils.java index 64bcaabf..af56bca4 100644 --- a/src/main/java/me/cortex/voxy/client/core/model/TextureUtils.java +++ b/src/main/java/me/cortex/voxy/client/core/model/TextureUtils.java @@ -208,8 +208,9 @@ public class TextureUtils { public static int mipColours(int one, int two, int three, int four) { - if (true) { - return MipmapGenerator.alphaBlend(one, two, three, four, false); + if (false) { + return 0; + //return MipmapGenerator.alphaBlend(one, two, three, four, false); } else { return weightedAverageColor(weightedAverageColor(one, two), weightedAverageColor(three, four)); } @@ -220,9 +221,11 @@ public class TextureUtils { //We specifically want the entire other component if the alpha is zero // this prevents black mips from generating due to A) non filled colours, and B) when the sampler samples everything it doesnt detonate if ((a&0xFF000000) == 0) { + //return (b&0x00FFFFFF)|((b>>>2)&0x3FC00000); return b; } if ((b&0xFF000000) == 0) { + //return (a&0x00FFFFFF)|((a>>>2)&0x3FC00000); return a; } @@ -234,6 +237,10 @@ public class TextureUtils { a>>>24); } + + + + { int A = (a>>>24); int B = (a>>>24); diff --git a/src/main/java/me/cortex/voxy/client/iris/IrisVoxyRenderPipelineData.java b/src/main/java/me/cortex/voxy/client/iris/IrisVoxyRenderPipelineData.java index fa17dd7d..e7acfa32 100644 --- a/src/main/java/me/cortex/voxy/client/iris/IrisVoxyRenderPipelineData.java +++ b/src/main/java/me/cortex/voxy/client/iris/IrisVoxyRenderPipelineData.java @@ -406,7 +406,7 @@ public class IrisVoxyRenderPipelineData { return uniforms; } - private record TextureWSampler(String name, IntSupplier texture, int sampler) { } + private record TextureWSampler(String name, IntSupplier texture, IntSupplier sampler) { } public record ImageSet(String layout, IntConsumer bindingFunction) { } @@ -437,27 +437,27 @@ public class IrisVoxyRenderPipelineData { } @Override - public boolean addDefaultSampler(TextureType type, IntSupplier texture, ValueUpdateNotifier notifier, GlSampler sampler, String... names) { + public boolean addDefaultSampler(TextureType type, IntSupplier texture, ValueUpdateNotifier notifier, Supplier sampler, String... names) { Logger.error("Unsupported default sampler"); return false; } @Override - public boolean addDynamicSampler(TextureType type, IntSupplier texture, GlSampler sampler, String... names) { + public boolean addDynamicSampler(TextureType type, IntSupplier texture, Supplier sampler, String... names) { return this.addDynamicSampler(type, texture, null, sampler, names); } @Override - public boolean addDynamicSampler(TextureType type, IntSupplier texture, ValueUpdateNotifier notifier, GlSampler sampler, String... names) { + public boolean addDynamicSampler(TextureType type, IntSupplier texture, ValueUpdateNotifier notifier, Supplier sampler, String... names) { if (!this.hasSampler(names)) return false; - samplerSet.add(new TextureWSampler(this.name(names), texture, sampler!=null?sampler.getId():-1)); + samplerSet.add(new TextureWSampler(this.name(names), texture, sampler!=null?()->sampler.get().getId():()->-1)); return true; } @Override public void addExternalSampler(int texture, String... names) { if (!this.hasSampler(names)) return; - samplerSet.add(new TextureWSampler(this.name(names), ()->texture, -1)); + samplerSet.add(new TextureWSampler(this.name(names), ()->texture, ()->-1)); } }; @@ -500,8 +500,9 @@ public class IrisVoxyRenderPipelineData { int unit = j+base; var ts = samplers[j]; glBindTextureUnit(unit, ts.texture.getAsInt()); - if (ts.sampler != -1) { - glBindSampler(unit, ts.sampler); + int sampler = ts.sampler.getAsInt(); + if (sampler != -1) { + glBindSampler(unit, sampler); }//TODO: might need to bind sampler 0 } }; diff --git a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinDefaultChunkRenderer.java b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinDefaultChunkRenderer.java index 1f54da16..f2fff4f5 100644 --- a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinDefaultChunkRenderer.java +++ b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinDefaultChunkRenderer.java @@ -1,5 +1,6 @@ package me.cortex.voxy.client.mixin.sodium; +import com.mojang.blaze3d.textures.GpuSampler; import me.cortex.voxy.client.VoxyClient; import me.cortex.voxy.client.core.IGetVoxyRenderSystem; import me.cortex.voxy.client.core.rendering.Viewport; @@ -31,9 +32,9 @@ public abstract class MixinDefaultChunkRenderer extends ShaderChunkRenderer { } @Inject(method = "render", at = @At(value = "HEAD"), cancellable = true) - private void cancelThingie(ChunkRenderMatrices matrices, CommandList commandList, ChunkRenderListIterable renderLists, TerrainRenderPass renderPass, CameraTransform camera, FogParameters fogParameters, boolean indexedRenderingEnabled, CallbackInfo ci) { + private void cancelThingie(ChunkRenderMatrices matrices, CommandList commandList, ChunkRenderListIterable renderLists, TerrainRenderPass renderPass, CameraTransform camera, FogParameters fogParameters, boolean indexedRenderingEnabled, GpuSampler terrainSampler, CallbackInfo ci) { if (VoxyClient.disableSodiumChunkRender()) { - super.begin(renderPass, fogParameters); + super.begin(renderPass, fogParameters, terrainSampler); this.doRender(matrices, renderPass, camera, fogParameters); super.end(renderPass); ci.cancel(); @@ -41,7 +42,7 @@ public abstract class MixinDefaultChunkRenderer extends ShaderChunkRenderer { } @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/ShaderChunkRenderer;end(Lnet/caffeinemc/mods/sodium/client/render/chunk/terrain/TerrainRenderPass;)V", shift = At.Shift.BEFORE)) - private void injectRender(ChunkRenderMatrices matrices, CommandList commandList, ChunkRenderListIterable renderLists, TerrainRenderPass renderPass, CameraTransform camera, FogParameters fogParameters, boolean indexedRenderingEnabled, CallbackInfo ci) { + private void injectRender(ChunkRenderMatrices matrices, CommandList commandList, ChunkRenderListIterable renderLists, TerrainRenderPass renderPass, CameraTransform camera, FogParameters fogParameters, boolean indexedRenderingEnabled, GpuSampler terrainSampler, CallbackInfo ci) { this.doRender(matrices, renderPass, camera, fogParameters); } diff --git a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinRenderRegionManager.java b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinRenderRegionManager.java new file mode 100644 index 00000000..7b308a6f --- /dev/null +++ b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinRenderRegionManager.java @@ -0,0 +1,29 @@ +package me.cortex.voxy.client.mixin.sodium; + +import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import me.cortex.voxy.client.config.VoxyConfig; +import me.cortex.voxy.client.core.IGetVoxyRenderSystem; +import me.cortex.voxy.commonImpl.VoxyCommon; +import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection; +import net.caffeinemc.mods.sodium.client.render.chunk.region.RenderRegionManager; +import net.minecraft.client.Minecraft; +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.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(value = RenderRegionManager.class, remap = false) +public class MixinRenderRegionManager { + @Redirect(method = "uploadResults(Lnet/caffeinemc/mods/sodium/client/gl/device/CommandList;Lnet/caffeinemc/mods/sodium/client/render/chunk/region/RenderRegion;Ljava/util/Collection;)V", at = @At(value = "INVOKE", target = "Ljava/lang/Math;toIntExact(J)I"), remap = false) + private int voxy$cancelFade(long time) { + var vrs = ((IGetVoxyRenderSystem)(Minecraft.getInstance().levelRenderer)).getVoxyRenderSystem(); + if (vrs!=null) { + return -2; + } else { + return Math.toIntExact(time); + } + } +} \ No newline at end of file diff --git a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinSodiumOptionsGUI.java b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinSodiumOptionsGUI.java deleted file mode 100644 index d9070984..00000000 --- a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinSodiumOptionsGUI.java +++ /dev/null @@ -1,27 +0,0 @@ -package me.cortex.voxy.client.mixin.sodium; - -import me.cortex.voxy.client.config.VoxyConfigScreenPages; -import me.cortex.voxy.commonImpl.VoxyCommon; -import net.caffeinemc.mods.sodium.client.gui.SodiumOptionsGUI; -import net.caffeinemc.mods.sodium.client.gui.options.OptionPage; -import net.minecraft.client.gui.screens.Screen; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.List; - -@Mixin(SodiumOptionsGUI.class) -public class MixinSodiumOptionsGUI { - @Shadow(remap = false) @Final private List pages; - - @Inject(method = "", at = @At("TAIL")) - private void voxy$addConfigPage(Screen prevScreen, CallbackInfo ci) { - if (VoxyCommon.isAvailable()) { - this.pages.add(VoxyConfigScreenPages.voxyOptionPage = VoxyConfigScreenPages.page()); - } - } -} diff --git a/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinVideoSettingsScreen.java b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinVideoSettingsScreen.java new file mode 100644 index 00000000..0c0e1592 --- /dev/null +++ b/src/main/java/me/cortex/voxy/client/mixin/sodium/MixinVideoSettingsScreen.java @@ -0,0 +1,34 @@ +package me.cortex.voxy.client.mixin.sodium; + +import me.cortex.voxy.client.config.IConfigPageSetter; +import net.caffeinemc.mods.sodium.client.config.structure.OptionPage; +import net.caffeinemc.mods.sodium.client.config.structure.Page; +import net.caffeinemc.mods.sodium.client.gui.VideoSettingsScreen; +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(value = VideoSettingsScreen.class, remap = false) +public abstract class MixinVideoSettingsScreen implements IConfigPageSetter { + @Shadow public abstract void jumpToPage(OptionPage page); + + @Shadow protected abstract void onSectionFocused(Page page); + + @Unique + private OptionPage voxyJumpPage; + + public void voxy$setPageJump(OptionPage page) { + this.voxyJumpPage = page; + } + + @Inject(method = "rebuild", at = @At("TAIL")) + private void voxy$jumpPages(CallbackInfo ci) { + if (this.voxyJumpPage != null) { + this.jumpToPage(this.voxyJumpPage); + this.onSectionFocused(this.voxyJumpPage); + } + } +} diff --git a/src/main/resources/assets/voxy/lang/en_us.json b/src/main/resources/assets/voxy/lang/en_us.json index 9530bf64..cb707b93 100644 --- a/src/main/resources/assets/voxy/lang/en_us.json +++ b/src/main/resources/assets/voxy/lang/en_us.json @@ -1,6 +1,9 @@ { "voxy.config.title": "Voxy", + "voxy.config.general": "General", + "voxy.config.rendering": "Rendering", + "voxy.config.general.enabled": "Enable Voxy", "voxy.config.general.enabled.tooltip": "Fully enables or disables voxy", diff --git a/src/main/resources/client.voxy.mixins.json b/src/main/resources/client.voxy.mixins.json index 662108fe..7fc41118 100644 --- a/src/main/resources/client.voxy.mixins.json +++ b/src/main/resources/client.voxy.mixins.json @@ -32,9 +32,10 @@ "sodium.AccessorSodiumWorldRenderer", "sodium.MixinChunkJobQueue", "sodium.MixinDefaultChunkRenderer", + "sodium.MixinRenderRegionManager", "sodium.MixinRenderSectionManager", - "sodium.MixinSodiumOptionsGUI", "sodium.MixinSodiumWorldRenderer", + "sodium.MixinVideoSettingsScreen", "minecraft.MixinLayerLightSectionStorage" ], "injectors": { diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 0bedefc7..b63ed5d4 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -23,6 +23,9 @@ "modmenu": [ "me.cortex.voxy.client.config.ModMenuIntegration" ], + "sodium:config_api_user": [ + "me.cortex.voxy.client.config.VoxyConfigMenu" + ], "main": [ "me.cortex.voxy.commonImpl.VoxyCommon" ]