update mods 1.21.11
This commit is contained in:
@@ -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);
|
||||||
|
}
|
||||||
@@ -4,25 +4,18 @@ import com.terraformersmc.modmenu.api.ConfigScreenFactory;
|
|||||||
import com.terraformersmc.modmenu.api.ModMenuApi;
|
import com.terraformersmc.modmenu.api.ModMenuApi;
|
||||||
import me.cortex.voxy.common.Logger;
|
import me.cortex.voxy.common.Logger;
|
||||||
import me.cortex.voxy.commonImpl.VoxyCommon;
|
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 {
|
public class ModMenuIntegration implements ModMenuApi {
|
||||||
@Override
|
@Override
|
||||||
public ConfigScreenFactory<?> getModConfigScreenFactory() {
|
public ConfigScreenFactory<?> getModConfigScreenFactory() {
|
||||||
return parent -> {
|
return parent -> {
|
||||||
if (VoxyCommon.isAvailable()) {
|
if (VoxyCommon.isAvailable()) {
|
||||||
var screen = (SodiumOptionsGUI) SodiumOptionsGUI.createScreen(parent);
|
var screen = (VideoSettingsScreen)VideoSettingsScreen.createScreen(parent);
|
||||||
//Sorry jelly and douira, please dont hurt me
|
var page = (OptionPage) ConfigManager.CONFIG.getModOptions().stream().filter(a->a.configId().equals("voxy")).findFirst().get().pages().get(0);
|
||||||
try {
|
((IConfigPageSetter)screen).voxy$setPageJump(page);
|
||||||
//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);
|
|
||||||
}
|
|
||||||
return screen;
|
return screen;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -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<ConfigState> tester, Identifier[] dependencies) {
|
||||||
|
public Enabler(Predicate<ConfigState> tester, String[] dependencies) {
|
||||||
|
this(tester, mapIds(dependencies));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract static class Enableable <TYPE extends Enableable<TYPE>> {
|
||||||
|
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<ConfigState> 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<Page> {
|
||||||
|
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<Group> {
|
||||||
|
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 <TYPE, OPTION extends Option<TYPE,OPTION,STYPE>, STYPE extends StatefulOptionBuilder<TYPE>> extends Enableable<Option<TYPE,OPTION,STYPE>> {
|
||||||
|
//Setter returns a post save update set
|
||||||
|
protected String id;
|
||||||
|
protected Component name;
|
||||||
|
protected Component tooltip;
|
||||||
|
protected Supplier<TYPE> getter;
|
||||||
|
protected Consumer<TYPE> setter;
|
||||||
|
public Option(String id, Component name, Component tooltip, Supplier<TYPE> getter, Consumer<TYPE> setter) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.tooltip = tooltip;
|
||||||
|
this.getter = getter;
|
||||||
|
this.setter = setter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Option(String id, Component name, Supplier<TYPE> getter, Consumer<TYPE> 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<TYPE, TYPE> postRunner;
|
||||||
|
protected String[] postRunnerConflicts;
|
||||||
|
protected String[] postChangeFlags;
|
||||||
|
public OPTION setPostChangeRunner(BiConsumer<TYPE, TYPE> 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<TYPE> 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<String> flags = new ArrayList<>();
|
||||||
|
List<OptionFlag> 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<Integer, IntOption, IntegerOptionBuilder> {
|
||||||
|
protected Function<ConfigState, Range> rangeProvider;
|
||||||
|
protected String[] rangeDependencies;
|
||||||
|
protected ControlValueFormatter formatter = v->Component.literal(Integer.toString(v));
|
||||||
|
|
||||||
|
public IntOption(String id, Component name, Component tooltip, Supplier<Integer> getter, Consumer<Integer> setter, Range range) {
|
||||||
|
super(id, name, tooltip, getter, setter);
|
||||||
|
this.rangeProvider = s->range;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntOption(String id, Component name, Supplier<Integer> getter, Consumer<Integer> setter, Range range) {
|
||||||
|
super(id, name, getter, setter);
|
||||||
|
this.rangeProvider = s->range;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntOption setFormatter(IntFunction<Component> 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<Boolean, BoolOption, BooleanOptionBuilder> {
|
||||||
|
public BoolOption(String id, Component name, Component tooltip, Supplier<Boolean> getter, Consumer<Boolean> setter) {
|
||||||
|
super(id, name, tooltip, getter, setter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoolOption(String id, Component name, Supplier<Boolean> getter, Consumer<Boolean> setter) {
|
||||||
|
super(id, name, getter, setter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected BooleanOptionBuilder createType(ConfigBuilder builder) {
|
||||||
|
return builder.createBooleanOption(Identifier.parse(this.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <F,T> T[] map(F[] from, Function<F,T> mapper, Function<Integer,T[]> 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<String, Set<String>> conflicts = new LinkedHashMap<>();
|
||||||
|
private Map<String, Runnable> executors = new LinkedHashMap<>();
|
||||||
|
private LinkedHashSet<String> 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<String> addFlag = this.postRunner::addFlag;
|
||||||
|
public StorageEventHandler saveHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void buildToSodium(ConfigBuilder builder, ModOptionsBuilder options, Runnable saveHandler, Consumer<PostApplyOps> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
149
src/main/java/me/cortex/voxy/client/config/VoxyConfigMenu.java
Normal file
149
src/main/java/me/cortex/voxy/client/config/VoxyConfigMenu.java
Normal file
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ import net.minecraft.client.Minecraft;
|
|||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
/*
|
||||||
public abstract class VoxyConfigScreenPages {
|
public abstract class VoxyConfigScreenPages {
|
||||||
private VoxyConfigScreenPages(){}
|
private VoxyConfigScreenPages(){}
|
||||||
|
|
||||||
@@ -181,3 +181,4 @@ public abstract class VoxyConfigScreenPages {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
@@ -208,8 +208,9 @@ public class TextureUtils {
|
|||||||
|
|
||||||
|
|
||||||
public static int mipColours(int one, int two, int three, int four) {
|
public static int mipColours(int one, int two, int three, int four) {
|
||||||
if (true) {
|
if (false) {
|
||||||
return MipmapGenerator.alphaBlend(one, two, three, four, false);
|
return 0;
|
||||||
|
//return MipmapGenerator.alphaBlend(one, two, three, four, false);
|
||||||
} else {
|
} else {
|
||||||
return weightedAverageColor(weightedAverageColor(one, two), weightedAverageColor(three, four));
|
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
|
//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
|
// 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) {
|
if ((a&0xFF000000) == 0) {
|
||||||
|
//return (b&0x00FFFFFF)|((b>>>2)&0x3FC00000);
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
if ((b&0xFF000000) == 0) {
|
if ((b&0xFF000000) == 0) {
|
||||||
|
//return (a&0x00FFFFFF)|((a>>>2)&0x3FC00000);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,6 +237,10 @@ public class TextureUtils {
|
|||||||
a>>>24);
|
a>>>24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
int A = (a>>>24);
|
int A = (a>>>24);
|
||||||
int B = (a>>>24);
|
int B = (a>>>24);
|
||||||
|
|||||||
@@ -406,7 +406,7 @@ public class IrisVoxyRenderPipelineData {
|
|||||||
return uniforms;
|
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) {
|
public record ImageSet(String layout, IntConsumer bindingFunction) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -437,27 +437,27 @@ public class IrisVoxyRenderPipelineData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addDefaultSampler(TextureType type, IntSupplier texture, ValueUpdateNotifier notifier, GlSampler sampler, String... names) {
|
public boolean addDefaultSampler(TextureType type, IntSupplier texture, ValueUpdateNotifier notifier, Supplier<GlSampler> sampler, String... names) {
|
||||||
Logger.error("Unsupported default sampler");
|
Logger.error("Unsupported default sampler");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addDynamicSampler(TextureType type, IntSupplier texture, GlSampler sampler, String... names) {
|
public boolean addDynamicSampler(TextureType type, IntSupplier texture, Supplier<GlSampler> sampler, String... names) {
|
||||||
return this.addDynamicSampler(type, texture, null, sampler, names);
|
return this.addDynamicSampler(type, texture, null, sampler, names);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addDynamicSampler(TextureType type, IntSupplier texture, ValueUpdateNotifier notifier, GlSampler sampler, String... names) {
|
public boolean addDynamicSampler(TextureType type, IntSupplier texture, ValueUpdateNotifier notifier, Supplier<GlSampler> sampler, String... names) {
|
||||||
if (!this.hasSampler(names)) return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addExternalSampler(int texture, String... names) {
|
public void addExternalSampler(int texture, String... names) {
|
||||||
if (!this.hasSampler(names)) return;
|
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;
|
int unit = j+base;
|
||||||
var ts = samplers[j];
|
var ts = samplers[j];
|
||||||
glBindTextureUnit(unit, ts.texture.getAsInt());
|
glBindTextureUnit(unit, ts.texture.getAsInt());
|
||||||
if (ts.sampler != -1) {
|
int sampler = ts.sampler.getAsInt();
|
||||||
glBindSampler(unit, ts.sampler);
|
if (sampler != -1) {
|
||||||
|
glBindSampler(unit, sampler);
|
||||||
}//TODO: might need to bind sampler 0
|
}//TODO: might need to bind sampler 0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package me.cortex.voxy.client.mixin.sodium;
|
package me.cortex.voxy.client.mixin.sodium;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.textures.GpuSampler;
|
||||||
import me.cortex.voxy.client.VoxyClient;
|
import me.cortex.voxy.client.VoxyClient;
|
||||||
import me.cortex.voxy.client.core.IGetVoxyRenderSystem;
|
import me.cortex.voxy.client.core.IGetVoxyRenderSystem;
|
||||||
import me.cortex.voxy.client.core.rendering.Viewport;
|
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)
|
@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()) {
|
if (VoxyClient.disableSodiumChunkRender()) {
|
||||||
super.begin(renderPass, fogParameters);
|
super.begin(renderPass, fogParameters, terrainSampler);
|
||||||
this.doRender(matrices, renderPass, camera, fogParameters);
|
this.doRender(matrices, renderPass, camera, fogParameters);
|
||||||
super.end(renderPass);
|
super.end(renderPass);
|
||||||
ci.cancel();
|
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))
|
@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);
|
this.doRender(matrices, renderPass, camera, fogParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<OptionPage> pages;
|
|
||||||
|
|
||||||
@Inject(method = "<init>", at = @At("TAIL"))
|
|
||||||
private void voxy$addConfigPage(Screen prevScreen, CallbackInfo ci) {
|
|
||||||
if (VoxyCommon.isAvailable()) {
|
|
||||||
this.pages.add(VoxyConfigScreenPages.voxyOptionPage = VoxyConfigScreenPages.page());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
{
|
{
|
||||||
"voxy.config.title": "Voxy",
|
"voxy.config.title": "Voxy",
|
||||||
|
|
||||||
|
"voxy.config.general": "General",
|
||||||
|
"voxy.config.rendering": "Rendering",
|
||||||
|
|
||||||
"voxy.config.general.enabled": "Enable Voxy",
|
"voxy.config.general.enabled": "Enable Voxy",
|
||||||
"voxy.config.general.enabled.tooltip": "Fully enables or disables voxy",
|
"voxy.config.general.enabled.tooltip": "Fully enables or disables voxy",
|
||||||
|
|
||||||
|
|||||||
@@ -32,9 +32,10 @@
|
|||||||
"sodium.AccessorSodiumWorldRenderer",
|
"sodium.AccessorSodiumWorldRenderer",
|
||||||
"sodium.MixinChunkJobQueue",
|
"sodium.MixinChunkJobQueue",
|
||||||
"sodium.MixinDefaultChunkRenderer",
|
"sodium.MixinDefaultChunkRenderer",
|
||||||
|
"sodium.MixinRenderRegionManager",
|
||||||
"sodium.MixinRenderSectionManager",
|
"sodium.MixinRenderSectionManager",
|
||||||
"sodium.MixinSodiumOptionsGUI",
|
|
||||||
"sodium.MixinSodiumWorldRenderer",
|
"sodium.MixinSodiumWorldRenderer",
|
||||||
|
"sodium.MixinVideoSettingsScreen",
|
||||||
"minecraft.MixinLayerLightSectionStorage"
|
"minecraft.MixinLayerLightSectionStorage"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
|
|||||||
@@ -23,6 +23,9 @@
|
|||||||
"modmenu": [
|
"modmenu": [
|
||||||
"me.cortex.voxy.client.config.ModMenuIntegration"
|
"me.cortex.voxy.client.config.ModMenuIntegration"
|
||||||
],
|
],
|
||||||
|
"sodium:config_api_user": [
|
||||||
|
"me.cortex.voxy.client.config.VoxyConfigMenu"
|
||||||
|
],
|
||||||
"main": [
|
"main": [
|
||||||
"me.cortex.voxy.commonImpl.VoxyCommon"
|
"me.cortex.voxy.commonImpl.VoxyCommon"
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user