From 3e028882e8efa6624d6e2ef7d0615fab13ca09f8 Mon Sep 17 00:00:00 2001 From: Yao Chung Hu <30311066+FlashyReese@users.noreply.github.com> Date: Thu, 30 Jun 2022 00:08:45 +0800 Subject: [PATCH 1/4] change: Clean up --- .github/workflows/gradle.yml | 46 ++-- .gitignore | 236 +++++++++--------- LICENSE.txt | 42 ++-- jitpack.yml | 3 - settings.gradle | 16 +- .../client/gui/SodiumVideoOptionsScreen.java | 2 +- .../client/gui/frame/BasicFrame.java | 134 +++++----- .../gui/frame/OptionPageScrollFrame.java | 4 +- .../client/gui/frame/tab/Tab.java | 27 +- .../client/gui/frame/tab/TabFrame.java | 17 +- .../client/gui/frame/tab/TabOption.java | 7 - .../mixin/sodium/MixinControlElement.java | 56 ++--- .../sodium/MixinCyclingControlElement.java | 72 +++--- .../sodium/MixinSliderControlElement.java | 129 +++++----- 14 files changed, 392 insertions(+), 399 deletions(-) delete mode 100644 jitpack.yml delete mode 100644 src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/tab/TabOption.java diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 631a649d..aabde413 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -1,23 +1,23 @@ -name: Java CI with Gradle - -on: [ pull_request, push ] - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 17 - uses: actions/setup-java@v1 - with: - java-version: 17 - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - name: Build with Gradle - run: ./gradlew build - - name: Upload build artifacts - uses: actions/upload-artifact@v1 - with: - name: build-artifacts - path: build/libs +name: Java CI with Gradle + +on: [ pull_request, push ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 17 + uses: actions/setup-java@v1 + with: + java-version: 17 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Build with Gradle + run: ./gradlew build + - name: Upload build artifacts + uses: actions/upload-artifact@v1 + with: + name: build-artifacts + path: build/libs diff --git a/.gitignore b/.gitignore index 3c37caf3..8f9956c5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,118 +1,118 @@ -# User-specific stuff -.idea/ - -*.iml -*.ipr -*.iws - -# IntelliJ -out/ -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* - -*~ - -# temporary files which can be created if a process still has a handle open of a deleted file -.fuse_hidden* - -# KDE directory preferences -.directory - -# Linux trash folder which might appear on any partition or disk -.Trash-* - -# .nfs files are created when an open file is removed but is still being accessed -.nfs* - -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -# Windows thumbnail cache files -Thumbs.db -Thumbs.db:encryptable -ehthumbs.db -ehthumbs_vista.db - -# Dump file -*.stackdump - -# Folder config file -[Dd]esktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msix -*.msm -*.msp - -# Windows shortcuts -*.lnk - -.gradle -build/ - -# Ignore Gradle GUI config -gradle-app.setting - -# Cache of project -.gradletasknamecache - -**/build/ - -# Common working directory -run/ - -# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) -!gradle-wrapper.jar +# User-specific stuff +.idea/ + +*.iml +*.ipr +*.iws + +# IntelliJ +out/ +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +.gradle +build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Cache of project +.gradletasknamecache + +**/build/ + +# Common working directory +run/ + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar diff --git a/LICENSE.txt b/LICENSE.txt index 4ccecdba..e02faf18 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,21 +1,21 @@ -The MIT License (MIT) - -Copyright (c) 2021 FlashyReese - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +The MIT License (MIT) + +Copyright (c) 2021 FlashyReese + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/jitpack.yml b/jitpack.yml deleted file mode 100644 index f5aaa710..00000000 --- a/jitpack.yml +++ /dev/null @@ -1,3 +0,0 @@ -before_install: - - wget https://github.com/sormuras/bach/raw/master/install-jdk.sh - - source install-jdk.sh --feature 16 \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 2875cdef..c4bb92c7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,9 +1,9 @@ -pluginManagement { - repositories { - maven { - name = 'Fabric' - url = 'https://maven.fabricmc.net/' - } - gradlePluginPortal() - } +pluginManagement { + repositories { + maven { + name = 'Fabric' + url = 'https://maven.fabricmc.net/' + } + gradlePluginPortal() + } } \ No newline at end of file diff --git a/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/SodiumVideoOptionsScreen.java b/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/SodiumVideoOptionsScreen.java index 1ba207c2..d831d1ea 100644 --- a/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/SodiumVideoOptionsScreen.java +++ b/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/SodiumVideoOptionsScreen.java @@ -104,7 +104,7 @@ public BasicFrame.Builder parentBasicFrameBuilder(Dim2i parentBasicFrameDim, Dim .addChild(parentDim -> TabFrame.createBuilder() .setDimension(tabFrameDim) .shouldRenderOutline(false) - .addTabs(tabs -> this.pages.stream().filter(page -> !page.getGroups().isEmpty()).forEach(page -> tabs.add(dim -> Tab.createBuilder().from(page, dim)))) + .addTabs(tabs -> this.pages.stream().filter(page -> !page.getGroups().isEmpty()).forEach(page -> tabs.add(Tab.createBuilder().from(page)))) .build() ); } diff --git a/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/BasicFrame.java b/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/BasicFrame.java index e000b735..b08cca28 100644 --- a/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/BasicFrame.java +++ b/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/BasicFrame.java @@ -1,68 +1,68 @@ -package me.flashyreese.mods.reeses_sodium_options.client.gui.frame; - -import me.jellysquid.mods.sodium.client.gui.widgets.AbstractWidget; -import me.jellysquid.mods.sodium.client.util.Dim2i; -import net.minecraft.client.util.math.MatrixStack; -import org.apache.commons.lang3.Validate; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - -public class BasicFrame extends AbstractFrame { - - protected List> functions; - - public BasicFrame(Dim2i dim, boolean renderOutline, List> functions) { - super(dim, renderOutline); - this.functions = functions; - this.buildFrame(); - } - - public static Builder createBuilder() { - return new Builder(); - } - - @Override - public void buildFrame() { - this.children.clear(); - this.drawable.clear(); - this.controlElements.clear(); - - this.functions.forEach(function -> this.children.add(function.apply(dim))); - - super.buildFrame(); - } - - @Override - public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { - super.render(matrices, mouseX, mouseY, delta); - } - - public static class Builder { - private final List> functions = new ArrayList<>(); - private Dim2i dim; - private boolean renderOutline; - - public Builder setDimension(Dim2i dim) { - this.dim = dim; - return this; - } - - public Builder shouldRenderOutline(boolean renderOutline) { - this.renderOutline = renderOutline; - return this; - } - - public Builder addChild(Function function) { - this.functions.add(function); - return this; - } - - public BasicFrame build() { - Validate.notNull(this.dim, "Dimension must be specified"); - - return new BasicFrame(this.dim, this.renderOutline, this.functions); - } - } +package me.flashyreese.mods.reeses_sodium_options.client.gui.frame; + +import me.jellysquid.mods.sodium.client.gui.widgets.AbstractWidget; +import me.jellysquid.mods.sodium.client.util.Dim2i; +import net.minecraft.client.util.math.MatrixStack; +import org.apache.commons.lang3.Validate; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +public class BasicFrame extends AbstractFrame { + + protected List> functions; + + public BasicFrame(Dim2i dim, boolean renderOutline, List> functions) { + super(dim, renderOutline); + this.functions = functions; + this.buildFrame(); + } + + public static Builder createBuilder() { + return new Builder(); + } + + @Override + public void buildFrame() { + this.children.clear(); + this.drawable.clear(); + this.controlElements.clear(); + + this.functions.forEach(function -> this.children.add(function.apply(dim))); + + super.buildFrame(); + } + + @Override + public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { + super.render(matrices, mouseX, mouseY, delta); + } + + public static class Builder { + private final List> functions = new ArrayList<>(); + private Dim2i dim; + private boolean renderOutline; + + public Builder setDimension(Dim2i dim) { + this.dim = dim; + return this; + } + + public Builder shouldRenderOutline(boolean renderOutline) { + this.renderOutline = renderOutline; + return this; + } + + public Builder addChild(Function function) { + this.functions.add(function); + return this; + } + + public BasicFrame build() { + Validate.notNull(this.dim, "Dimension must be specified"); + + return new BasicFrame(this.dim, this.renderOutline, this.functions); + } + } } \ No newline at end of file diff --git a/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/OptionPageScrollFrame.java b/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/OptionPageScrollFrame.java index ec744e71..35160a67 100644 --- a/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/OptionPageScrollFrame.java +++ b/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/OptionPageScrollFrame.java @@ -97,7 +97,9 @@ public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { .filter(ControlElement::isHovered) .findFirst() .orElse(null); + matrices.push(); this.applyScissor(this.dim.getOriginX(), this.dim.getOriginY(), this.dim.getWidth(), this.dim.getHeight(), () -> super.render(matrices, mouseX, mouseY, delta)); + matrices.pop(); if (this.canScroll) { this.scrollBar.render(matrices, mouseX, mouseY, delta); } @@ -212,7 +214,7 @@ public Builder setDimension(Dim2i dim) { public Builder shouldRenderOutline(boolean renderOutline) { this.renderOutline = renderOutline; - return this; + return this; } public Builder setOptionPage(OptionPage page) { diff --git a/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/tab/Tab.java b/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/tab/Tab.java index 733238f6..bbb5d8e0 100644 --- a/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/tab/Tab.java +++ b/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/tab/Tab.java @@ -7,13 +7,15 @@ import net.minecraft.text.LiteralText; import net.minecraft.text.Text; -public class Tab implements TabOption { +import java.util.function.Function; + +public class Tab { private final Text title; - private final T frame; + private final Function frameFunction; - public Tab(Text title, T frame) { + public Tab(Text title, Function frameFunction) { this.title = title; - this.frame = frame; + this.frameFunction = frameFunction; } public static Tab.Builder createBuilder() { @@ -24,31 +26,30 @@ public Text getTitle() { return title; } - @Override - public T getFrame() { - return this.frame; + public Function getFrameFunction() { + return this.frameFunction; } public static class Builder { private Text title; - private T frame; + private Function frameFunction; public Builder setTitle(Text title) { this.title = title; return this; } - public Builder setFrame(T frame) { - this.frame = frame; + public Builder setFrameFunction(Function frameFunction) { + this.frameFunction = frameFunction; return this; } public Tab build() { - return new Tab(this.title, this.frame); + return new Tab(this.title, this.frameFunction); } - public Tab from(OptionPage page, Dim2i dim) { - return new Tab<>(new LiteralText(page.getName()), OptionPageScrollFrame.createBuilder().setDimension(dim).shouldRenderOutline(false).setOptionPage(page).build()); + public Tab from(OptionPage page) { + return new Tab<>(new LiteralText(page.getName()), dim2i -> OptionPageScrollFrame.createBuilder().setDimension(dim2i).shouldRenderOutline(false).setOptionPage(page).build()); } } } \ No newline at end of file diff --git a/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/tab/TabFrame.java b/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/tab/TabFrame.java index e56f12b5..12a64e2d 100644 --- a/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/tab/TabFrame.java +++ b/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/tab/TabFrame.java @@ -11,7 +11,6 @@ import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; -import java.util.function.Function; public class TabFrame extends AbstractFrame { @@ -21,12 +20,13 @@ public class TabFrame extends AbstractFrame { private final List> tabs = new ArrayList<>(); private ScrollBarComponent tabSectionScrollBar = null; private Tab selectedTab; + private AbstractFrame selectedFrame; - public TabFrame(Dim2i dim, boolean renderOutline, List>> functions) { + public TabFrame(Dim2i dim, boolean renderOutline, List> functions) { super(dim, renderOutline); this.tabSection = new Dim2i(this.dim.getOriginX(), this.dim.getOriginY(), (int) (this.dim.getWidth() * 0.35D), this.dim.getHeight()); this.frameSection = new Dim2i(this.tabSection.getLimitX(), this.dim.getOriginY(), this.dim.getWidth() - this.tabSection.getWidth(), this.dim.getHeight()); - functions.forEach(function -> this.tabs.add(function.apply(this.frameSection))); + this.tabs.addAll(functions); int tabSectionY = this.tabs.size() * 18; this.tabSectionCanScroll = tabSectionY > this.tabSection.getHeight(); @@ -74,12 +74,12 @@ public void buildFrame() { public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { this.applyScissor(this.dim.getOriginX(), this.dim.getOriginY(), this.dim.getWidth(), this.dim.getHeight(), () -> { for (AbstractWidget widget: this.children) { - if (widget != this.selectedTab.getFrame()){ + if (widget != this.selectedFrame){ widget.render(matrices, mouseX, mouseY, delta); } } }); - this.selectedTab.getFrame().render(matrices, mouseX, mouseY, delta); + this.selectedFrame.render(matrices, mouseX, mouseY, delta); if (this.tabSectionCanScroll) { this.tabSectionScrollBar.render(matrices, mouseX, mouseY, delta); } @@ -148,15 +148,16 @@ private void rebuildTabs() { private void rebuildTabFrame() { if (this.selectedTab == null) return; - AbstractFrame frame = this.selectedTab.getFrame(); + AbstractFrame frame = this.selectedTab.getFrameFunction().apply(this.frameSection); if (frame != null) { + this.selectedFrame = frame; frame.buildFrame(); this.children.add(frame); } } public static class Builder { - private final List>> functions = new ArrayList<>(); + private final List> functions = new ArrayList<>(); private Dim2i dim; private boolean renderOutline; @@ -170,7 +171,7 @@ public Builder shouldRenderOutline(boolean renderOutline) { return this; } - public Builder addTabs(Consumer>>> tabs) { + public Builder addTabs(Consumer>> tabs) { tabs.accept(this.functions); return this; } diff --git a/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/tab/TabOption.java b/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/tab/TabOption.java deleted file mode 100644 index 33fd0386..00000000 --- a/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/tab/TabOption.java +++ /dev/null @@ -1,7 +0,0 @@ -package me.flashyreese.mods.reeses_sodium_options.client.gui.frame.tab; - -import me.flashyreese.mods.reeses_sodium_options.client.gui.frame.AbstractFrame; - -public interface TabOption { - T getFrame(); -} diff --git a/src/main/java/me/flashyreese/mods/reeses_sodium_options/mixin/sodium/MixinControlElement.java b/src/main/java/me/flashyreese/mods/reeses_sodium_options/mixin/sodium/MixinControlElement.java index e9bb0463..0638c0fa 100644 --- a/src/main/java/me/flashyreese/mods/reeses_sodium_options/mixin/sodium/MixinControlElement.java +++ b/src/main/java/me/flashyreese/mods/reeses_sodium_options/mixin/sodium/MixinControlElement.java @@ -1,28 +1,28 @@ -package me.flashyreese.mods.reeses_sodium_options.mixin.sodium; - -import me.jellysquid.mods.sodium.client.gui.options.control.ControlElement; -import me.jellysquid.mods.sodium.client.gui.widgets.AbstractWidget; -import me.jellysquid.mods.sodium.client.util.Dim2i; -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.Redirect; - -@Mixin(ControlElement.class) -public abstract class MixinControlElement extends AbstractWidget { - - @Shadow - @Final - protected Dim2i dim; - - @Redirect(method = "render", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/util/Dim2i;containsCursor(DD)Z")) - public boolean render(Dim2i dim2i, double x, double y) { - return this.isMouseOver(x, y); - } - - @Override - public boolean isMouseOver(double mouseX, double mouseY) { - return this.dim.containsCursor(mouseX, mouseY); - } -} +package me.flashyreese.mods.reeses_sodium_options.mixin.sodium; + +import me.jellysquid.mods.sodium.client.gui.options.control.ControlElement; +import me.jellysquid.mods.sodium.client.gui.widgets.AbstractWidget; +import me.jellysquid.mods.sodium.client.util.Dim2i; +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.Redirect; + +@Mixin(ControlElement.class) +public abstract class MixinControlElement extends AbstractWidget { + + @Shadow + @Final + protected Dim2i dim; + + @Redirect(method = "render", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/util/Dim2i;containsCursor(DD)Z")) + public boolean render(Dim2i dim2i, double x, double y) { + return this.isMouseOver(x, y); + } + + @Override + public boolean isMouseOver(double mouseX, double mouseY) { + return this.dim.containsCursor(mouseX, mouseY); + } +} diff --git a/src/main/java/me/flashyreese/mods/reeses_sodium_options/mixin/sodium/MixinCyclingControlElement.java b/src/main/java/me/flashyreese/mods/reeses_sodium_options/mixin/sodium/MixinCyclingControlElement.java index 34ebb530..1396d246 100644 --- a/src/main/java/me/flashyreese/mods/reeses_sodium_options/mixin/sodium/MixinCyclingControlElement.java +++ b/src/main/java/me/flashyreese/mods/reeses_sodium_options/mixin/sodium/MixinCyclingControlElement.java @@ -1,36 +1,36 @@ -package me.flashyreese.mods.reeses_sodium_options.mixin.sodium; - -import me.jellysquid.mods.sodium.client.gui.options.Option; -import me.jellysquid.mods.sodium.client.gui.options.control.ControlElement; -import me.jellysquid.mods.sodium.client.util.Dim2i; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(targets = "me.jellysquid.mods.sodium.client.gui.options.control.CyclingControl$CyclingControlElement") -public abstract class MixinCyclingControlElement> extends ControlElement { - - @Shadow - private int currentIndex; - - @Shadow - @Final - private T[] allowedValues; - - public MixinCyclingControlElement(Option option, Dim2i dim) { - super(option, dim); - } - - @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (this.option.isAvailable() && this.dim.containsCursor(mouseX, mouseY) && (button == 0 || button == 1)) { - this.currentIndex = Math.floorMod(this.option.getValue().ordinal() + (button == 0 ? 1 : -1), this.allowedValues.length); - this.option.setValue(this.allowedValues[this.currentIndex]); - this.playClickSound(); - - return true; - } - - return false; - } -} +package me.flashyreese.mods.reeses_sodium_options.mixin.sodium; + +import me.jellysquid.mods.sodium.client.gui.options.Option; +import me.jellysquid.mods.sodium.client.gui.options.control.ControlElement; +import me.jellysquid.mods.sodium.client.util.Dim2i; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(targets = "me.jellysquid.mods.sodium.client.gui.options.control.CyclingControl$CyclingControlElement") +public abstract class MixinCyclingControlElement> extends ControlElement { + + @Shadow + private int currentIndex; + + @Shadow + @Final + private T[] allowedValues; + + public MixinCyclingControlElement(Option option, Dim2i dim) { + super(option, dim); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (this.option.isAvailable() && this.dim.containsCursor(mouseX, mouseY) && (button == 0 || button == 1)) { + this.currentIndex = Math.floorMod(this.option.getValue().ordinal() + (button == 0 ? 1 : -1), this.allowedValues.length); + this.option.setValue(this.allowedValues[this.currentIndex]); + this.playClickSound(); + + return true; + } + + return false; + } +} diff --git a/src/main/java/me/flashyreese/mods/reeses_sodium_options/mixin/sodium/MixinSliderControlElement.java b/src/main/java/me/flashyreese/mods/reeses_sodium_options/mixin/sodium/MixinSliderControlElement.java index 78b63b70..e7ec1f82 100644 --- a/src/main/java/me/flashyreese/mods/reeses_sodium_options/mixin/sodium/MixinSliderControlElement.java +++ b/src/main/java/me/flashyreese/mods/reeses_sodium_options/mixin/sodium/MixinSliderControlElement.java @@ -1,66 +1,65 @@ -package me.flashyreese.mods.reeses_sodium_options.mixin.sodium; - -import me.jellysquid.mods.sodium.client.gui.options.Option; -import me.jellysquid.mods.sodium.client.gui.options.control.ControlElement; -import me.jellysquid.mods.sodium.client.gui.options.control.ControlValueFormatter; -import me.jellysquid.mods.sodium.client.util.Dim2i; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.util.math.Rect2i; -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; - -@Mixin(targets = "me.jellysquid.mods.sodium.client.gui.options.control.SliderControl$Button") -public abstract class MixinSliderControlElement extends ControlElement { - - @Shadow - @Final - private int interval; - - @Shadow - private double thumbPosition; - - @Shadow - @Final - private int min; - - private int max; - - @Shadow - @Final - private Rect2i sliderBounds; - - public MixinSliderControlElement(Option option, Dim2i dim) { - super(option, dim); - } - - @Shadow - public abstract double getThumbPositionForValue(int value); - - - @Inject(method = "", at = @At(value = "TAIL")) - public void postInit(Option option, Dim2i dim, int min, int max, int interval, ControlValueFormatter formatter, CallbackInfo ci) { - this.max = max; - } - - private void setValueFromMouseScroll(double amount) { - if (this.option.getValue() + this.interval * (int) amount <= this.max && this.option.getValue() + this.interval * (int) amount >= this.min) { - this.option.setValue(this.option.getValue() + this.interval * (int) amount); - this.thumbPosition = this.getThumbPositionForValue(this.option.getValue()); - } - } - - @Override - public boolean mouseScrolled(double mouseX, double mouseY, double amount) { - if (this.option.isAvailable() && this.sliderBounds.contains((int) mouseX, (int) mouseY) && Screen.hasShiftDown()) { - this.setValueFromMouseScroll(amount); - - return true; - } - - return false; - } +package me.flashyreese.mods.reeses_sodium_options.mixin.sodium; + +import me.jellysquid.mods.sodium.client.gui.options.Option; +import me.jellysquid.mods.sodium.client.gui.options.control.ControlElement; +import me.jellysquid.mods.sodium.client.gui.options.control.ControlValueFormatter; +import me.jellysquid.mods.sodium.client.util.Dim2i; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.util.math.Rect2i; +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; + +@Mixin(targets = "me.jellysquid.mods.sodium.client.gui.options.control.SliderControl$Button") +public abstract class MixinSliderControlElement extends ControlElement { + + @Shadow + @Final + private int interval; + + @Shadow + private double thumbPosition; + + @Shadow + @Final + private int min; + + private int max; + + @Shadow + @Final + private Rect2i sliderBounds; + + public MixinSliderControlElement(Option option, Dim2i dim) { + super(option, dim); + } + + @Shadow + public abstract double getThumbPositionForValue(int value); + + @Inject(method = "", at = @At(value = "TAIL")) + public void postInit(Option option, Dim2i dim, int min, int max, int interval, ControlValueFormatter formatter, CallbackInfo ci) { + this.max = max; + } + + private void setValueFromMouseScroll(double amount) { + if (this.option.getValue() + this.interval * (int) amount <= this.max && this.option.getValue() + this.interval * (int) amount >= this.min) { + this.option.setValue(this.option.getValue() + this.interval * (int) amount); + this.thumbPosition = this.getThumbPositionForValue(this.option.getValue()); + } + } + + @Override + public boolean mouseScrolled(double mouseX, double mouseY, double amount) { + if (this.option.isAvailable() && this.sliderBounds.contains((int) mouseX, (int) mouseY) && Screen.hasShiftDown()) { + this.setValueFromMouseScroll(amount); + + return true; + } + + return false; + } } \ No newline at end of file From e3e7bf1672794c00e5c0944c1f944ea23b504e75 Mon Sep 17 00:00:00 2001 From: Yao Chung Hu <30311066+FlashyReese@users.noreply.github.com> Date: Thu, 30 Jun 2022 00:21:28 +0800 Subject: [PATCH 2/4] new: Dynamic scale left align tabs --- .../client/gui/FlatButtonWidgetExtended.java | 7 +++ .../client/gui/frame/tab/TabFrame.java | 12 +++-- .../mixin/sodium/MixinFlatButtonWidget.java | 52 +++++++++++++++++++ .../reeses-sodium-options.mixins.json | 1 + 4 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/FlatButtonWidgetExtended.java create mode 100644 src/main/java/me/flashyreese/mods/reeses_sodium_options/mixin/sodium/MixinFlatButtonWidget.java diff --git a/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/FlatButtonWidgetExtended.java b/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/FlatButtonWidgetExtended.java new file mode 100644 index 00000000..1a930c2a --- /dev/null +++ b/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/FlatButtonWidgetExtended.java @@ -0,0 +1,7 @@ +package me.flashyreese.mods.reeses_sodium_options.client.gui; + +public interface FlatButtonWidgetExtended { + boolean isLeftAligned(); + + void setLeftAligned(boolean leftAligned); +} diff --git a/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/tab/TabFrame.java b/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/tab/TabFrame.java index 12a64e2d..b6e67d2b 100644 --- a/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/tab/TabFrame.java +++ b/src/main/java/me/flashyreese/mods/reeses_sodium_options/client/gui/frame/tab/TabFrame.java @@ -1,5 +1,6 @@ package me.flashyreese.mods.reeses_sodium_options.client.gui.frame.tab; +import me.flashyreese.mods.reeses_sodium_options.client.gui.FlatButtonWidgetExtended; import me.flashyreese.mods.reeses_sodium_options.client.gui.frame.AbstractFrame; import me.flashyreese.mods.reeses_sodium_options.client.gui.frame.components.ScrollBarComponent; import me.jellysquid.mods.sodium.client.gui.widgets.AbstractWidget; @@ -10,6 +11,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.function.Consumer; public class TabFrame extends AbstractFrame { @@ -22,11 +24,14 @@ public class TabFrame extends AbstractFrame { private Tab selectedTab; private AbstractFrame selectedFrame; - public TabFrame(Dim2i dim, boolean renderOutline, List> functions) { + public TabFrame(Dim2i dim, boolean renderOutline, List> tabs) { super(dim, renderOutline); - this.tabSection = new Dim2i(this.dim.getOriginX(), this.dim.getOriginY(), (int) (this.dim.getWidth() * 0.35D), this.dim.getHeight()); + + Optional result = tabs.stream().map(tab -> this.getStringWidth(tab.getTitle().getString())).max(Integer::compareTo); + + this.tabSection = new Dim2i(this.dim.getOriginX(), this.dim.getOriginY(), result.map(integer -> (int) (integer * 2.5)).orElseGet(() -> (int) (this.dim.getWidth() * 0.35D)), this.dim.getHeight()); this.frameSection = new Dim2i(this.tabSection.getLimitX(), this.dim.getOriginY(), this.dim.getWidth() - this.tabSection.getWidth(), this.dim.getHeight()); - this.tabs.addAll(functions); + this.tabs.addAll(tabs); int tabSectionY = this.tabs.size() * 18; this.tabSectionCanScroll = tabSectionY > this.tabSection.getHeight(); @@ -140,6 +145,7 @@ private void rebuildTabs() { FlatButtonWidget button = new FlatButtonWidget(tabDim, tab.getTitle().asString(), () -> this.setTab(tab)); button.setSelected(this.selectedTab == tab); + ((FlatButtonWidgetExtended) button).setLeftAligned(true); this.children.add(button); offsetY += 18; diff --git a/src/main/java/me/flashyreese/mods/reeses_sodium_options/mixin/sodium/MixinFlatButtonWidget.java b/src/main/java/me/flashyreese/mods/reeses_sodium_options/mixin/sodium/MixinFlatButtonWidget.java new file mode 100644 index 00000000..08a5a6ae --- /dev/null +++ b/src/main/java/me/flashyreese/mods/reeses_sodium_options/mixin/sodium/MixinFlatButtonWidget.java @@ -0,0 +1,52 @@ +package me.flashyreese.mods.reeses_sodium_options.mixin.sodium; + +import me.flashyreese.mods.reeses_sodium_options.client.gui.FlatButtonWidgetExtended; +import me.jellysquid.mods.sodium.client.gui.widgets.AbstractWidget; +import me.jellysquid.mods.sodium.client.gui.widgets.FlatButtonWidget; +import me.jellysquid.mods.sodium.client.util.Dim2i; +import net.minecraft.client.util.math.MatrixStack; +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.Redirect; + +@Mixin(FlatButtonWidget.class) +public abstract class MixinFlatButtonWidget extends AbstractWidget implements FlatButtonWidgetExtended { + + @Shadow + @Final + private Dim2i dim; + + @Unique + private boolean leftAligned; + + @Redirect(method = "render", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/gui/widgets/FlatButtonWidget;drawString(Lnet/minecraft/client/util/math/MatrixStack;Ljava/lang/String;III)V")) + public void redirectDrawString(FlatButtonWidget instance, MatrixStack matrixStack, String text, int x, int y, int color) { + if (this.leftAligned) { + this.drawString(matrixStack, text, this.dim.getOriginX() + 10, y, color); + } else { + this.drawString(matrixStack, text, x, y, color); + } + } + + @Redirect(method = "render", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/gui/widgets/FlatButtonWidget;drawRect(DDDDI)V", ordinal = 1)) + public void redirectDrawRect(FlatButtonWidget instance, double x1, double y1, double x2, double y2, int color) { + if (this.leftAligned) { + this.drawRect(x1, this.dim.getOriginY(), x1 + 1, y2, color); + } else { + this.drawRect(x1, y1, x2, y2, color); + } + } + + @Override + public boolean isLeftAligned() { + return this.leftAligned; + } + + @Override + public void setLeftAligned(boolean leftAligned) { + this.leftAligned = leftAligned; + } +} diff --git a/src/main/resources/reeses-sodium-options.mixins.json b/src/main/resources/reeses-sodium-options.mixins.json index e2e87919..6e1ae11d 100644 --- a/src/main/resources/reeses-sodium-options.mixins.json +++ b/src/main/resources/reeses-sodium-options.mixins.json @@ -6,6 +6,7 @@ "client": [ "sodium.MixinControlElement", "sodium.MixinCyclingControlElement", + "sodium.MixinFlatButtonWidget", "sodium.MixinSliderControlElement", "sodium.MixinSodiumOptionsGUI" ], From 172966f0d7d5d6c2e0c5e814a4d8eb3abfbe1952 Mon Sep 17 00:00:00 2001 From: Yao Chung Hu <30311066+FlashyReese@users.noreply.github.com> Date: Thu, 21 Jul 2022 19:26:17 +0800 Subject: [PATCH 3/4] change: Bump gradle wrapper --- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew.bat | 178 +++++++++++------------ 2 files changed, 90 insertions(+), 90 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aa991fce..8049c684 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew.bat b/gradlew.bat index 107acd32..ac1b06f9 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,89 +1,89 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega From 0a20ec895a6d7a6d894e47120db844d727b26d3f Mon Sep 17 00:00:00 2001 From: Yao Chung Hu <30311066+FlashyReese@users.noreply.github.com> Date: Thu, 21 Jul 2022 19:29:14 +0800 Subject: [PATCH 4/4] change: Bump for release --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index e8cedc72..a81938e6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ org.gradle.jvmargs=-Xmx1G yarn_mappings=1.16.5+build.10 loader_version=0.13.3 # Mod Properties - mod_version=1.4.3 + mod_version=1.4.4 maven_group=me.flashyreese.mods archives_base_name=reeses_sodium_options