A builder-based configuration library for Minecraft.
Yet Another Config Lib, like, what were you expecting?
Why does this mod even exist?
This mod was made to fill a gap in the area of Fabric modding. The existing main config libraries don't achieve what I want from them:
Cloth Config API: It's stale. The developer of cloth has clarified that they are likely not going to add any more features. They don't want to touch it.
SpruceUI: It isn't designed for configuration. In essence, the design feels cluttered.
MidnightLib: It has cosmetics among other utilities. Some players wouldn't want cosmetics out of nowhere.
OwoLib: It's content focused. It does a lot of other things as well as config, adding to the size.
As you can see, there are drawbacks with all of them and this is where YetAnotherConfigLib comes in.
How is YACL better?
YACL has the favor of hindsight. Whilst developing this fresh library, I can make sure that it does everything right:
Easy API. YACL takes inspiration from Sodium's internal configuration library.
It's styled to fit in Minecraft. YACL's GUI is designed to fit right in.
Usage
The wiki contains a full documentation on how to use YACL.
- Added a visual hint to the scrollable tab bar when there are more tabs than can fit on the screen.
- New 1.21.9 Fabric target
- Rewrote a significant portion of the OptionList widget to make it compatible with 1.21.9 and future versions.
- Added a visual hint to the scrollable tab bar when there are more tabs than can fit on the screen.
- New 1.21.9 Fabric target
- Rewrote a significant portion of the OptionList widget to make it compatible with 1.21.9 and future versions.
- Added a visual hint to the scrollable tab bar when there are more tabs than can fit on the screen.
- New 1.21.9 Fabric target
- Rewrote a significant portion of the OptionList widget to make it compatible with 1.21.9 and future versions.
- Added a visual hint to the scrollable tab bar when there are more tabs than can fit on the screen.
- New 1.21.9 Fabric target
- Rewrote a significant portion of the OptionList widget to make it compatible with 1.21.9 and future versions.
- Added a visual hint to the scrollable tab bar when there are more tabs than can fit on the screen.
- New 1.21.9 Fabric target
- Rewrote a significant portion of the OptionList widget to make it compatible with 1.21.9 and future versions.
- Added a visual hint to the scrollable tab bar when there are more tabs than can fit on the screen.
- New 1.21.9 Fabric target
- Rewrote a significant portion of the OptionList widget to make it compatible with 1.21.9 and future versions.
- Added a visual hint to the scrollable tab bar when there are more tabs than can fit on the screen.
- New 1.21.9 Fabric target
- Rewrote a significant portion of the OptionList widget to make it compatible with 1.21.9 and future versions.
- Added a visual hint to the scrollable tab bar when there are more tabs than can fit on the screen.
- New 1.21.9 Fabric target
- Rewrote a significant portion of the OptionList widget to make it compatible with 1.21.9 and future versions.
- Added a visual hint to the scrollable tab bar when there are more tabs than can fit on the screen.
- New 1.21.9 Fabric target
- Rewrote a significant portion of the OptionList widget to make it compatible with 1.21.9 and future versions.
- Added a visual hint to the scrollable tab bar when there are more tabs than can fit on the screen.
- New 1.21.9 Fabric target
- Rewrote a significant portion of the OptionList widget to make it compatible with 1.21.9 and future versions.
- Added a visual hint to the scrollable tab bar when there are more tabs than can fit on the screen.
- New 1.21.9 Fabric target
- Rewrote a significant portion of the OptionList widget to make it compatible with 1.21.9 and future versions.
- Added a visual hint to the scrollable tab bar when there are more tabs than can fit on the screen.
- New 1.21.9 Fabric target
- Rewrote a significant portion of the OptionList widget to make it compatible with 1.21.9 and future versions.
- Fix crash on some Neoforge targets when opening the colour picker
- Fix improper rendering of the colour picker
- Fix option group collapse button not being visible unless hovered
- Fix crash on some Neoforge targets when opening the colour picker
- Fix improper rendering of the colour picker
- Fix option group collapse button not being visible unless hovered
- Fix crash on some Neoforge targets when opening the colour picker
- Fix improper rendering of the colour picker
- Fix option group collapse button not being visible unless hovered
- Fix crash on some Neoforge targets when opening the colour picker
- Fix improper rendering of the colour picker
- Fix option group collapse button not being visible unless hovered
- Fix crash on some Neoforge targets when opening the colour picker
- Fix improper rendering of the colour picker
- Fix option group collapse button not being visible unless hovered
- Fix crash on some Neoforge targets when opening the colour picker
- Fix improper rendering of the colour picker
- Fix option group collapse button not being visible unless hovered
- Fix crash on some Neoforge targets when opening the colour picker
- Fix improper rendering of the colour picker
- Fix option group collapse button not being visible unless hovered
- Fix crash on some Neoforge targets when opening the colour picker
- Fix improper rendering of the colour picker
- Fix option group collapse button not being visible unless hovered
- Fix crash on some Neoforge targets when opening the colour picker
- Fix improper rendering of the colour picker
- Fix option group collapse button not being visible unless hovered
- Fix crash on some Neoforge targets when opening the colour picker
- Fix improper rendering of the colour picker
- Fix option group collapse button not being visible unless hovered
- Fix crash on some Neoforge targets when opening the colour picker
- Fix improper rendering of the colour picker
- Fix option group collapse button not being visible unless hovered
- Fix crash on some Neoforge targets when opening the colour picker
- Fix improper rendering of the colour picker
- Fix option group collapse button not being visible unless hovered
- Fix crash on some Neoforge targets when opening the colour picker
- Fix improper rendering of the colour picker
- Fix option group collapse button not being visible unless hovered
- Add toggle to prevent loading .webp and .gif at resource reload.
- When disabled, the images will be loaded on-demand when a YACL screen is opened.
- It is disabled by default now. This should improve startup time with mods that use such images.
- You can now set the default collapsed state in option groups via the Kotlin DSL. You could already do this via Java.
## Changes
- Add 1.21.6 target
- Removed all the 1.20.x targets.
- YACL now only supports 1.21.1 and later.
- Allow the use of horizontal mouse scrolling in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
## Bug fixes
- Fixes related to the colour picker widget
- The YACLScreen now continues to tick when the colour picker is open.
- Clicking outside the colour picker now closes it (without the click being consumed by the screen)
- Fix requiring a double click to open a colour picker after it has been closed.
- Fix the last option sometimes being cut off in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
- Fix NullPointerException when using `null` with `InstantStateManager`.
- Add toggle to prevent loading .webp and .gif at resource reload.
- When disabled, the images will be loaded on-demand when a YACL screen is opened.
- It is disabled by default now. This should improve startup time with mods that use such images.
- You can now set the default collapsed state in option groups via the Kotlin DSL. You could already do this via Java.
## Changes
- Add 1.21.6 target
- Removed all the 1.20.x targets.
- YACL now only supports 1.21.1 and later.
- Allow the use of horizontal mouse scrolling in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
## Bug fixes
- Fixes related to the colour picker widget
- The YACLScreen now continues to tick when the colour picker is open.
- Clicking outside the colour picker now closes it (without the click being consumed by the screen)
- Fix requiring a double click to open a colour picker after it has been closed.
- Fix the last option sometimes being cut off in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
- Fix NullPointerException when using `null` with `InstantStateManager`.
- Add toggle to prevent loading .webp and .gif at resource reload.
- When disabled, the images will be loaded on-demand when a YACL screen is opened.
- It is disabled by default now. This should improve startup time with mods that use such images.
- You can now set the default collapsed state in option groups via the Kotlin DSL. You could already do this via Java.
## Changes
- Add 1.21.6 target
- Removed all the 1.20.x targets.
- YACL now only supports 1.21.1 and later.
- Allow the use of horizontal mouse scrolling in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
## Bug fixes
- Fixes related to the colour picker widget
- The YACLScreen now continues to tick when the colour picker is open.
- Clicking outside the colour picker now closes it (without the click being consumed by the screen)
- Fix requiring a double click to open a colour picker after it has been closed.
- Fix the last option sometimes being cut off in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
- Fix NullPointerException when using `null` with `InstantStateManager`.
- Add toggle to prevent loading .webp and .gif at resource reload.
- When disabled, the images will be loaded on-demand when a YACL screen is opened.
- It is disabled by default now. This should improve startup time with mods that use such images.
- You can now set the default collapsed state in option groups via the Kotlin DSL. You could already do this via Java.
## Changes
- Add 1.21.6 target
- Removed all the 1.20.x targets.
- YACL now only supports 1.21.1 and later.
- Allow the use of horizontal mouse scrolling in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
## Bug fixes
- Fixes related to the colour picker widget
- The YACLScreen now continues to tick when the colour picker is open.
- Clicking outside the colour picker now closes it (without the click being consumed by the screen)
- Fix requiring a double click to open a colour picker after it has been closed.
- Fix the last option sometimes being cut off in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
- Fix NullPointerException when using `null` with `InstantStateManager`.
- Add toggle to prevent loading .webp and .gif at resource reload.
- When disabled, the images will be loaded on-demand when a YACL screen is opened.
- It is disabled by default now. This should improve startup time with mods that use such images.
- You can now set the default collapsed state in option groups via the Kotlin DSL. You could already do this via Java.
## Changes
- Add 1.21.6 target
- Removed all the 1.20.x targets.
- YACL now only supports 1.21.1 and later.
- Allow the use of horizontal mouse scrolling in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
## Bug fixes
- Fixes related to the colour picker widget
- The YACLScreen now continues to tick when the colour picker is open.
- Clicking outside the colour picker now closes it (without the click being consumed by the screen)
- Fix requiring a double click to open a colour picker after it has been closed.
- Fix the last option sometimes being cut off in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
- Fix NullPointerException when using `null` with `InstantStateManager`.
- Add toggle to prevent loading .webp and .gif at resource reload.
- When disabled, the images will be loaded on-demand when a YACL screen is opened.
- It is disabled by default now. This should improve startup time with mods that use such images.
- You can now set the default collapsed state in option groups via the Kotlin DSL. You could already do this via Java.
## Changes
- Add 1.21.6 target
- Removed all the 1.20.x targets.
- YACL now only supports 1.21.1 and later.
- Allow the use of horizontal mouse scrolling in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
## Bug fixes
- Fixes related to the colour picker widget
- The YACLScreen now continues to tick when the colour picker is open.
- Clicking outside the colour picker now closes it (without the click being consumed by the screen)
- Fix requiring a double click to open a colour picker after it has been closed.
- Fix the last option sometimes being cut off in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
- Fix NullPointerException when using `null` with `InstantStateManager`.
- Add toggle to prevent loading .webp and .gif at resource reload.
- When disabled, the images will be loaded on-demand when a YACL screen is opened.
- It is disabled by default now. This should improve startup time with mods that use such images.
- You can now set the default collapsed state in option groups via the Kotlin DSL. You could already do this via Java.
## Changes
- Add 1.21.6 target
- Removed all the 1.20.x targets.
- YACL now only supports 1.21.1 and later.
- Allow the use of horizontal mouse scrolling in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
## Bug fixes
- Fixes related to the colour picker widget
- The YACLScreen now continues to tick when the colour picker is open.
- Clicking outside the colour picker now closes it (without the click being consumed by the screen)
- Fix requiring a double click to open a colour picker after it has been closed.
- Fix the last option sometimes being cut off in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
- Fix NullPointerException when using `null` with `InstantStateManager`.
- Add toggle to prevent loading .webp and .gif at resource reload.
- When disabled, the images will be loaded on-demand when a YACL screen is opened.
- It is disabled by default now. This should improve startup time with mods that use such images.
- You can now set the default collapsed state in option groups via the Kotlin DSL. You could already do this via Java.
## Changes
- Add 1.21.6 target
- Removed all the 1.20.x targets.
- YACL now only supports 1.21.1 and later.
- Allow the use of horizontal mouse scrolling in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
## Bug fixes
- Fixes related to the colour picker widget
- The YACLScreen now continues to tick when the colour picker is open.
- Clicking outside the colour picker now closes it (without the click being consumed by the screen)
- Fix requiring a double click to open a colour picker after it has been closed.
- Fix the last option sometimes being cut off in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
- Fix NullPointerException when using `null` with `InstantStateManager`.
- Add toggle to prevent loading .webp and .gif at resource reload.
- When disabled, the images will be loaded on-demand when a YACL screen is opened.
- It is disabled by default now. This should improve startup time with mods that use such images.
- You can now set the default collapsed state in option groups via the Kotlin DSL. You could already do this via Java.
## Changes
- Add 1.21.6 target
- Removed all the 1.20.x targets.
- YACL now only supports 1.21.1 and later.
- Allow the use of horizontal mouse scrolling in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
## Bug fixes
- Fixes related to the colour picker widget
- The YACLScreen now continues to tick when the colour picker is open.
- Clicking outside the colour picker now closes it (without the click being consumed by the screen)
- Fix requiring a double click to open a colour picker after it has been closed.
- Fix the last option sometimes being cut off in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
- Fix NullPointerException when using `null` with `InstantStateManager`.
- Add toggle to prevent loading .webp and .gif at resource reload.
- When disabled, the images will be loaded on-demand when a YACL screen is opened.
- It is disabled by default now. This should improve startup time with mods that use such images.
- You can now set the default collapsed state in option groups via the Kotlin DSL. You could already do this via Java.
## Changes
- Add 1.21.6 target
- Removed all the 1.20.x targets.
- YACL now only supports 1.21.1 and later.
- Allow the use of horizontal mouse scrolling in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
## Bug fixes
- Fixes related to the colour picker widget
- The YACLScreen now continues to tick when the colour picker is open.
- Clicking outside the colour picker now closes it (without the click being consumed by the screen)
- Fix requiring a double click to open a colour picker after it has been closed.
- Fix the last option sometimes being cut off in the options list. ([kevinthegreat1`#271`](https://github.com/isXander/YetAnotherConfigLib/pull/271))
- Fix NullPointerException when using `null` with `InstantStateManager`.
- Update to support 1.21.4 (many thanks to Riflusso for this port)
- Add `groupIf` to `ConfigCategory.Builder` (thanks Kevin)
- Pass down middle-mouse clicks to widgets in ElementListWidgetExt (thanks Protonull)
- Fix Greek translation (many thanks to Darkhax for this)
- Update Kotlin to 2.0.21
- Update to support 1.21.4 (many thanks to Riflusso for this port)
- Add `groupIf` to `ConfigCategory.Builder` (thanks Kevin)
- Pass down middle-mouse clicks to widgets in ElementListWidgetExt (thanks Protonull)
- Fix Greek translation (many thanks to Darkhax for this)
- Update Kotlin to 2.0.21
- Update to support 1.21.4 (many thanks to Riflusso for this port)
- Add `groupIf` to `ConfigCategory.Builder` (thanks Kevin)
- Pass down middle-mouse clicks to widgets in ElementListWidgetExt (thanks Protonull)
- Fix Greek translation (many thanks to Darkhax for this)
- Update Kotlin to 2.0.21
- Update to support 1.21.4 (many thanks to Riflusso for this port)
- Add `groupIf` to `ConfigCategory.Builder` (thanks Kevin)
- Pass down middle-mouse clicks to widgets in ElementListWidgetExt (thanks Protonull)
- Fix Greek translation (many thanks to Darkhax for this)
- Update Kotlin to 2.0.21
- Update to support 1.21.4 (many thanks to Riflusso for this port)
- Add `groupIf` to `ConfigCategory.Builder` (thanks Kevin)
- Pass down middle-mouse clicks to widgets in ElementListWidgetExt (thanks Protonull)
- Fix Greek translation (many thanks to Darkhax for this)
- Update Kotlin to 2.0.21
- Update to support 1.21.4 (many thanks to Riflusso for this port)
- Add `groupIf` to `ConfigCategory.Builder` (thanks Kevin)
- Pass down middle-mouse clicks to widgets in ElementListWidgetExt (thanks Protonull)
- Fix Greek translation (many thanks to Darkhax for this)
- Update Kotlin to 2.0.21
- Update to support 1.21.4 (many thanks to Riflusso for this port)
- Add `groupIf` to `ConfigCategory.Builder` (thanks Kevin)
- Pass down middle-mouse clicks to widgets in ElementListWidgetExt (thanks Protonull)
- Fix Greek translation (many thanks to Darkhax for this)
- Update Kotlin to 2.0.21
- Update to support 1.21.4 (many thanks to Riflusso for this port)
- Add `groupIf` to `ConfigCategory.Builder` (thanks Kevin)
- Pass down middle-mouse clicks to widgets in ElementListWidgetExt (thanks Protonull)
- Fix Greek translation (many thanks to Darkhax for this)
- Update Kotlin to 2.0.21
- Update to support 1.21.4 (many thanks to Riflusso for this port)
- Add `groupIf` to `ConfigCategory.Builder` (thanks Kevin)
- Pass down middle-mouse clicks to widgets in ElementListWidgetExt (thanks Protonull)
- Fix Greek translation (many thanks to Darkhax for this)
- Update Kotlin to 2.0.21
- Update to support 1.21.4 (many thanks to Riflusso for this port)
- Add `groupIf` to `ConfigCategory.Builder` (thanks Kevin)
- Pass down middle-mouse clicks to widgets in ElementListWidgetExt (thanks Protonull)
- Fix Greek translation (many thanks to Darkhax for this)
- Update Kotlin to 2.0.21
- Update to support 1.21.4 (many thanks to Riflusso for this port)
- Add `groupIf` to `ConfigCategory.Builder` (thanks Kevin)
- Pass down middle-mouse clicks to widgets in ElementListWidgetExt (thanks Protonull)
- Fix Greek translation (many thanks to Darkhax for this)
- Update Kotlin to 2.0.21
- Update to support 1.21.4 (many thanks to Riflusso for this port)
- Add `groupIf` to `ConfigCategory.Builder` (thanks Kevin)
- Pass down middle-mouse clicks to widgets in ElementListWidgetExt (thanks Protonull)
- Fix Greek translation (many thanks to Darkhax for this)
- Update Kotlin to 2.0.21
- Add 1.21.2 build for NeoForge
- Fix not being able to type negative numbers into number field controllers ()
- Fix default range of floating point field controllers being 0-MAX instead of MIN-MAX ([#213](https://github.com/isXander/YetAnotherConfigLib/pull/213))
- Update translations
- Add 1.21.2 build for NeoForge
- Fix not being able to type negative numbers into number field controllers ()
- Fix default range of floating point field controllers being 0-MAX instead of MIN-MAX ([#213](https://github.com/isXander/YetAnotherConfigLib/pull/213))
- Update translations
- Add 1.21.2 build for NeoForge
- Fix not being able to type negative numbers into number field controllers ()
- Fix default range of floating point field controllers being 0-MAX instead of MIN-MAX ([#213](https://github.com/isXander/YetAnotherConfigLib/pull/213))
- Update translations
- Add 1.21.2 build for NeoForge
- Fix not being able to type negative numbers into number field controllers ()
- Fix default range of floating point field controllers being 0-MAX instead of MIN-MAX ([#213](https://github.com/isXander/YetAnotherConfigLib/pull/213))
- Update translations
- Add 1.21.2 build for NeoForge
- Fix not being able to type negative numbers into number field controllers ()
- Fix default range of floating point field controllers being 0-MAX instead of MIN-MAX ([#213](https://github.com/isXander/YetAnotherConfigLib/pull/213))
- Update translations
- Add 1.21.2 build for NeoForge
- Fix not being able to type negative numbers into number field controllers ()
- Fix default range of floating point field controllers being 0-MAX instead of MIN-MAX ([#213](https://github.com/isXander/YetAnotherConfigLib/pull/213))
- Update translations
- Add 1.21.2 build for NeoForge
- Fix not being able to type negative numbers into number field controllers ()
- Fix default range of floating point field controllers being 0-MAX instead of MIN-MAX ([#213](https://github.com/isXander/YetAnotherConfigLib/pull/213))
- Update translations
- Add 1.21.2 build for NeoForge
- Fix not being able to type negative numbers into number field controllers ()
- Fix default range of floating point field controllers being 0-MAX instead of MIN-MAX ([#213](https://github.com/isXander/YetAnotherConfigLib/pull/213))
- Update translations
- Add 1.21.2 build for NeoForge
- Fix not being able to type negative numbers into number field controllers ()
- Fix default range of floating point field controllers being 0-MAX instead of MIN-MAX ([#213](https://github.com/isXander/YetAnotherConfigLib/pull/213))
- Update translations
- Add 1.21.2 build for NeoForge
- Fix not being able to type negative numbers into number field controllers ()
- Fix default range of floating point field controllers being 0-MAX instead of MIN-MAX ([#213](https://github.com/isXander/YetAnotherConfigLib/pull/213))
- Update translations
Options now no longer hold their state themselves. This job is now delegated to the `StateManager`.
This change serves to allow multiple options to share the same state, but with different controllers, descriptions,
names, etc.
### Example
Take an example of how this might be useful:
You have a long range of gamepad bindings, utilising a custom YACL _controller_. They are sorted alphabetically in YACL.
You want a specific gamepad binding, let's call it 'Jump', to be featured at the top of the list, but also still
appear alphabetically in the list.
You add a second 'Jump' YACL _option_ and place it at the beginning of the _category_, you assign it an identical
_binding_.
This appears to work, but you discover a problem: you can modify the featured _option_ just fine, but when you hit
'Save Changes', you see an error in your log 'Option value mismatch' and your option defaults to the previous, now
unchanged value.
Why is this? Each instance of _`Option`_ holds its own _pending value_. Which is then applied to the _binding_ when you
click save. When you click save, YACL iterates over each option in-order and applies the pending value to the _binding._
Which leads to the following series of events:
1. YACL successfully applies the featured 'Jump' option to the binding, as it's first in the list.
2. YACL then finds the non-featured 'Jump' option, which retained the original default value because the
_pending value_ has not changed. From step 1, the binding's value has now changed to something none-default, so now
it sets the binding again to the pending value of THIS option, now the binding is back to its default state.
3. YACL finishes saving _options_, and checks over each one again. It checks that the _pending value_ matches the
_binding_. Because the featured 'Jump' option now doesn't match, it creates an error in your log:
'Option value mismatch' and assigns the _pending value_ to the _binding_ value.
### Solution
State managers essentially solve this by moving the _pending value_ into a separate object that can then be given to
multiple _options_. They ensure that each option's controller is kept up to date by emitting events upon the state's
change that controllers then listen to, to keep themselves up to date.
Here, instead of using a `.binding()`, you use a `.stateManager()`. Now both share and update the same state!
### Event Changes
Options that listen to events, `.listener((option, newValue) -> {})`, the syntax has slightly changed. The
aforementioned methods have been deprecated, replaced with `.addListener((option, event) -> {})`, you can retrieve the
new value with `option.pendingValue()`.
### Consolidation of .instant() behaviour
Because of this open-ness of how an option's pending value gets applied, users of YACL have a lot more power
on what happens with how an option's state is applied.
Options now no longer hold their state themselves. This job is now delegated to the `StateManager`.
This change serves to allow multiple options to share the same state, but with different controllers, descriptions,
names, etc.
### Example
Take an example of how this might be useful:
You have a long range of gamepad bindings, utilising a custom YACL _controller_. They are sorted alphabetically in YACL.
You want a specific gamepad binding, let's call it 'Jump', to be featured at the top of the list, but also still
appear alphabetically in the list.
You add a second 'Jump' YACL _option_ and place it at the beginning of the _category_, you assign it an identical
_binding_.
This appears to work, but you discover a problem: you can modify the featured _option_ just fine, but when you hit
'Save Changes', you see an error in your log 'Option value mismatch' and your option defaults to the previous, now
unchanged value.
Why is this? Each instance of _`Option`_ holds its own _pending value_. Which is then applied to the _binding_ when you
click save. When you click save, YACL iterates over each option in-order and applies the pending value to the _binding._
Which leads to the following series of events:
1. YACL successfully applies the featured 'Jump' option to the binding, as it's first in the list.
2. YACL then finds the non-featured 'Jump' option, which retained the original default value because the
_pending value_ has not changed. From step 1, the binding's value has now changed to something none-default, so now
it sets the binding again to the pending value of THIS option, now the binding is back to its default state.
3. YACL finishes saving _options_, and checks over each one again. It checks that the _pending value_ matches the
_binding_. Because the featured 'Jump' option now doesn't match, it creates an error in your log:
'Option value mismatch' and assigns the _pending value_ to the _binding_ value.
### Solution
State managers essentially solve this by moving the _pending value_ into a separate object that can then be given to
multiple _options_. They ensure that each option's controller is kept up to date by emitting events upon the state's
change that controllers then listen to, to keep themselves up to date.
Here, instead of using a `.binding()`, you use a `.stateManager()`. Now both share and update the same state!
### Event Changes
Options that listen to events, `.listener((option, newValue) -> {})`, the syntax has slightly changed. The
aforementioned methods have been deprecated, replaced with `.addListener((option, event) -> {})`, you can retrieve the
new value with `option.pendingValue()`.
### Consolidation of .instant() behaviour
Because of this open-ness of how an option's pending value gets applied, users of YACL have a lot more power
on what happens with how an option's state is applied.
Options now no longer hold their state themselves. This job is now delegated to the `StateManager`.
This change serves to allow multiple options to share the same state, but with different controllers, descriptions,
names, etc.
### Example
Take an example of how this might be useful:
You have a long range of gamepad bindings, utilising a custom YACL _controller_. They are sorted alphabetically in YACL.
You want a specific gamepad binding, let's call it 'Jump', to be featured at the top of the list, but also still
appear alphabetically in the list.
You add a second 'Jump' YACL _option_ and place it at the beginning of the _category_, you assign it an identical
_binding_.
This appears to work, but you discover a problem: you can modify the featured _option_ just fine, but when you hit
'Save Changes', you see an error in your log 'Option value mismatch' and your option defaults to the previous, now
unchanged value.
Why is this? Each instance of _`Option`_ holds its own _pending value_. Which is then applied to the _binding_ when you
click save. When you click save, YACL iterates over each option in-order and applies the pending value to the _binding._
Which leads to the following series of events:
1. YACL successfully applies the featured 'Jump' option to the binding, as it's first in the list.
2. YACL then finds the non-featured 'Jump' option, which retained the original default value because the
_pending value_ has not changed. From step 1, the binding's value has now changed to something none-default, so now
it sets the binding again to the pending value of THIS option, now the binding is back to its default state.
3. YACL finishes saving _options_, and checks over each one again. It checks that the _pending value_ matches the
_binding_. Because the featured 'Jump' option now doesn't match, it creates an error in your log:
'Option value mismatch' and assigns the _pending value_ to the _binding_ value.
### Solution
State managers essentially solve this by moving the _pending value_ into a separate object that can then be given to
multiple _options_. They ensure that each option's controller is kept up to date by emitting events upon the state's
change that controllers then listen to, to keep themselves up to date.
Here, instead of using a `.binding()`, you use a `.stateManager()`. Now both share and update the same state!
### Event Changes
Options that listen to events, `.listener((option, newValue) -> {})`, the syntax has slightly changed. The
aforementioned methods have been deprecated, replaced with `.addListener((option, event) -> {})`, you can retrieve the
new value with `option.pendingValue()`.
### Consolidation of .instant() behaviour
Because of this open-ness of how an option's pending value gets applied, users of YACL have a lot more power
on what happens with how an option's state is applied.
Options now no longer hold their state themselves. This job is now delegated to the `StateManager`.
This change serves to allow multiple options to share the same state, but with different controllers, descriptions,
names, etc.
### Example
Take an example of how this might be useful:
You have a long range of gamepad bindings, utilising a custom YACL _controller_. They are sorted alphabetically in YACL.
You want a specific gamepad binding, let's call it 'Jump', to be featured at the top of the list, but also still
appear alphabetically in the list.
You add a second 'Jump' YACL _option_ and place it at the beginning of the _category_, you assign it an identical
_binding_.
This appears to work, but you discover a problem: you can modify the featured _option_ just fine, but when you hit
'Save Changes', you see an error in your log 'Option value mismatch' and your option defaults to the previous, now
unchanged value.
Why is this? Each instance of _`Option`_ holds its own _pending value_. Which is then applied to the _binding_ when you
click save. When you click save, YACL iterates over each option in-order and applies the pending value to the _binding._
Which leads to the following series of events:
1. YACL successfully applies the featured 'Jump' option to the binding, as it's first in the list.
2. YACL then finds the non-featured 'Jump' option, which retained the original default value because the
_pending value_ has not changed. From step 1, the binding's value has now changed to something none-default, so now
it sets the binding again to the pending value of THIS option, now the binding is back to its default state.
3. YACL finishes saving _options_, and checks over each one again. It checks that the _pending value_ matches the
_binding_. Because the featured 'Jump' option now doesn't match, it creates an error in your log:
'Option value mismatch' and assigns the _pending value_ to the _binding_ value.
### Solution
State managers essentially solve this by moving the _pending value_ into a separate object that can then be given to
multiple _options_. They ensure that each option's controller is kept up to date by emitting events upon the state's
change that controllers then listen to, to keep themselves up to date.
Here, instead of using a `.binding()`, you use a `.stateManager()`. Now both share and update the same state!
### Event Changes
Options that listen to events, `.listener((option, newValue) -> {})`, the syntax has slightly changed. The
aforementioned methods have been deprecated, replaced with `.addListener((option, event) -> {})`, you can retrieve the
new value with `option.pendingValue()`.
### Consolidation of .instant() behaviour
Because of this open-ness of how an option's pending value gets applied, users of YACL have a lot more power
on what happens with how an option's state is applied.
Options now no longer hold their state themselves. This job is now delegated to the `StateManager`.
This change serves to allow multiple options to share the same state, but with different controllers, descriptions,
names, etc.
### Example
Take an example of how this might be useful:
You have a long range of gamepad bindings, utilising a custom YACL _controller_. They are sorted alphabetically in YACL.
You want a specific gamepad binding, let's call it 'Jump', to be featured at the top of the list, but also still
appear alphabetically in the list.
You add a second 'Jump' YACL _option_ and place it at the beginning of the _category_, you assign it an identical
_binding_.
This appears to work, but you discover a problem: you can modify the featured _option_ just fine, but when you hit
'Save Changes', you see an error in your log 'Option value mismatch' and your option defaults to the previous, now
unchanged value.
Why is this? Each instance of _`Option`_ holds its own _pending value_. Which is then applied to the _binding_ when you
click save. When you click save, YACL iterates over each option in-order and applies the pending value to the _binding._
Which leads to the following series of events:
1. YACL successfully applies the featured 'Jump' option to the binding, as it's first in the list.
2. YACL then finds the non-featured 'Jump' option, which retained the original default value because the
_pending value_ has not changed. From step 1, the binding's value has now changed to something none-default, so now
it sets the binding again to the pending value of THIS option, now the binding is back to its default state.
3. YACL finishes saving _options_, and checks over each one again. It checks that the _pending value_ matches the
_binding_. Because the featured 'Jump' option now doesn't match, it creates an error in your log:
'Option value mismatch' and assigns the _pending value_ to the _binding_ value.
### Solution
State managers essentially solve this by moving the _pending value_ into a separate object that can then be given to
multiple _options_. They ensure that each option's controller is kept up to date by emitting events upon the state's
change that controllers then listen to, to keep themselves up to date.
Here, instead of using a `.binding()`, you use a `.stateManager()`. Now both share and update the same state!
### Event Changes
Options that listen to events, `.listener((option, newValue) -> {})`, the syntax has slightly changed. The
aforementioned methods have been deprecated, replaced with `.addListener((option, event) -> {})`, you can retrieve the
new value with `option.pendingValue()`.
### Consolidation of .instant() behaviour
Because of this open-ness of how an option's pending value gets applied, users of YACL have a lot more power
on what happens with how an option's state is applied.
Options now no longer hold their state themselves. This job is now delegated to the `StateManager`.
This change serves to allow multiple options to share the same state, but with different controllers, descriptions,
names, etc.
### Example
Take an example of how this might be useful:
You have a long range of gamepad bindings, utilising a custom YACL _controller_. They are sorted alphabetically in YACL.
You want a specific gamepad binding, let's call it 'Jump', to be featured at the top of the list, but also still
appear alphabetically in the list.
You add a second 'Jump' YACL _option_ and place it at the beginning of the _category_, you assign it an identical
_binding_.
This appears to work, but you discover a problem: you can modify the featured _option_ just fine, but when you hit
'Save Changes', you see an error in your log 'Option value mismatch' and your option defaults to the previous, now
unchanged value.
Why is this? Each instance of _`Option`_ holds its own _pending value_. Which is then applied to the _binding_ when you
click save. When you click save, YACL iterates over each option in-order and applies the pending value to the _binding._
Which leads to the following series of events:
1. YACL successfully applies the featured 'Jump' option to the binding, as it's first in the list.
2. YACL then finds the non-featured 'Jump' option, which retained the original default value because the
_pending value_ has not changed. From step 1, the binding's value has now changed to something none-default, so now
it sets the binding again to the pending value of THIS option, now the binding is back to its default state.
3. YACL finishes saving _options_, and checks over each one again. It checks that the _pending value_ matches the
_binding_. Because the featured 'Jump' option now doesn't match, it creates an error in your log:
'Option value mismatch' and assigns the _pending value_ to the _binding_ value.
### Solution
State managers essentially solve this by moving the _pending value_ into a separate object that can then be given to
multiple _options_. They ensure that each option's controller is kept up to date by emitting events upon the state's
change that controllers then listen to, to keep themselves up to date.
Here, instead of using a `.binding()`, you use a `.stateManager()`. Now both share and update the same state!
### Event Changes
Options that listen to events, `.listener((option, newValue) -> {})`, the syntax has slightly changed. The
aforementioned methods have been deprecated, replaced with `.addListener((option, event) -> {})`, you can retrieve the
new value with `option.pendingValue()`.
### Consolidation of .instant() behaviour
Because of this open-ness of how an option's pending value gets applied, users of YACL have a lot more power
on what happens with how an option's state is applied.
Options now no longer hold their state themselves. This job is now delegated to the `StateManager`.
This change serves to allow multiple options to share the same state, but with different controllers, descriptions,
names, etc.
### Example
Take an example of how this might be useful:
You have a long range of gamepad bindings, utilising a custom YACL _controller_. They are sorted alphabetically in YACL.
You want a specific gamepad binding, let's call it 'Jump', to be featured at the top of the list, but also still
appear alphabetically in the list.
You add a second 'Jump' YACL _option_ and place it at the beginning of the _category_, you assign it an identical
_binding_.
This appears to work, but you discover a problem: you can modify the featured _option_ just fine, but when you hit
'Save Changes', you see an error in your log 'Option value mismatch' and your option defaults to the previous, now
unchanged value.
Why is this? Each instance of _`Option`_ holds its own _pending value_. Which is then applied to the _binding_ when you
click save. When you click save, YACL iterates over each option in-order and applies the pending value to the _binding._
Which leads to the following series of events:
1. YACL successfully applies the featured 'Jump' option to the binding, as it's first in the list.
2. YACL then finds the non-featured 'Jump' option, which retained the original default value because the
_pending value_ has not changed. From step 1, the binding's value has now changed to something none-default, so now
it sets the binding again to the pending value of THIS option, now the binding is back to its default state.
3. YACL finishes saving _options_, and checks over each one again. It checks that the _pending value_ matches the
_binding_. Because the featured 'Jump' option now doesn't match, it creates an error in your log:
'Option value mismatch' and assigns the _pending value_ to the _binding_ value.
### Solution
State managers essentially solve this by moving the _pending value_ into a separate object that can then be given to
multiple _options_. They ensure that each option's controller is kept up to date by emitting events upon the state's
change that controllers then listen to, to keep themselves up to date.
Here, instead of using a `.binding()`, you use a `.stateManager()`. Now both share and update the same state!
### Event Changes
Options that listen to events, `.listener((option, newValue) -> {})`, the syntax has slightly changed. The
aforementioned methods have been deprecated, replaced with `.addListener((option, event) -> {})`, you can retrieve the
new value with `option.pendingValue()`.
### Consolidation of .instant() behaviour
Because of this open-ness of how an option's pending value gets applied, users of YACL have a lot more power
on what happens with how an option's state is applied.
Options now no longer hold their state themselves. This job is now delegated to the `StateManager`.
This change serves to allow multiple options to share the same state, but with different controllers, descriptions,
names, etc.
### Example
Take an example of how this might be useful:
You have a long range of gamepad bindings, utilising a custom YACL _controller_. They are sorted alphabetically in YACL.
You want a specific gamepad binding, let's call it 'Jump', to be featured at the top of the list, but also still
appear alphabetically in the list.
You add a second 'Jump' YACL _option_ and place it at the beginning of the _category_, you assign it an identical
_binding_.
This appears to work, but you discover a problem: you can modify the featured _option_ just fine, but when you hit
'Save Changes', you see an error in your log 'Option value mismatch' and your option defaults to the previous, now
unchanged value.
Why is this? Each instance of _`Option`_ holds its own _pending value_. Which is then applied to the _binding_ when you
click save. When you click save, YACL iterates over each option in-order and applies the pending value to the _binding._
Which leads to the following series of events:
1. YACL successfully applies the featured 'Jump' option to the binding, as it's first in the list.
2. YACL then finds the non-featured 'Jump' option, which retained the original default value because the
_pending value_ has not changed. From step 1, the binding's value has now changed to something none-default, so now
it sets the binding again to the pending value of THIS option, now the binding is back to its default state.
3. YACL finishes saving _options_, and checks over each one again. It checks that the _pending value_ matches the
_binding_. Because the featured 'Jump' option now doesn't match, it creates an error in your log:
'Option value mismatch' and assigns the _pending value_ to the _binding_ value.
### Solution
State managers essentially solve this by moving the _pending value_ into a separate object that can then be given to
multiple _options_. They ensure that each option's controller is kept up to date by emitting events upon the state's
change that controllers then listen to, to keep themselves up to date.
Here, instead of using a `.binding()`, you use a `.stateManager()`. Now both share and update the same state!
### Event Changes
Options that listen to events, `.listener((option, newValue) -> {})`, the syntax has slightly changed. The
aforementioned methods have been deprecated, replaced with `.addListener((option, event) -> {})`, you can retrieve the
new value with `option.pendingValue()`.
### Consolidation of .instant() behaviour
Because of this open-ness of how an option's pending value gets applied, users of YACL have a lot more power
on what happens with how an option's state is applied.
Options now no longer hold their state themselves. This job is now delegated to the `StateManager`.
This change serves to allow multiple options to share the same state, but with different controllers, descriptions,
names, etc.
### Example
Take an example of how this might be useful:
You have a long range of gamepad bindings, utilising a custom YACL _controller_. They are sorted alphabetically in YACL.
You want a specific gamepad binding, let's call it 'Jump', to be featured at the top of the list, but also still
appear alphabetically in the list.
You add a second 'Jump' YACL _option_ and place it at the beginning of the _category_, you assign it an identical
_binding_.
This appears to work, but you discover a problem: you can modify the featured _option_ just fine, but when you hit
'Save Changes', you see an error in your log 'Option value mismatch' and your option defaults to the previous, now
unchanged value.
Why is this? Each instance of _`Option`_ holds its own _pending value_. Which is then applied to the _binding_ when you
click save. When you click save, YACL iterates over each option in-order and applies the pending value to the _binding._
Which leads to the following series of events:
1. YACL successfully applies the featured 'Jump' option to the binding, as it's first in the list.
2. YACL then finds the non-featured 'Jump' option, which retained the original default value because the
_pending value_ has not changed. From step 1, the binding's value has now changed to something none-default, so now
it sets the binding again to the pending value of THIS option, now the binding is back to its default state.
3. YACL finishes saving _options_, and checks over each one again. It checks that the _pending value_ matches the
_binding_. Because the featured 'Jump' option now doesn't match, it creates an error in your log:
'Option value mismatch' and assigns the _pending value_ to the _binding_ value.
### Solution
State managers essentially solve this by moving the _pending value_ into a separate object that can then be given to
multiple _options_. They ensure that each option's controller is kept up to date by emitting events upon the state's
change that controllers then listen to, to keep themselves up to date.
Here, instead of using a `.binding()`, you use a `.stateManager()`. Now both share and update the same state!
### Event Changes
Options that listen to events, `.listener((option, newValue) -> {})`, the syntax has slightly changed. The
aforementioned methods have been deprecated, replaced with `.addListener((option, event) -> {})`, you can retrieve the
new value with `option.pendingValue()`.
### Consolidation of .instant() behaviour
Because of this open-ness of how an option's pending value gets applied, users of YACL have a lot more power
on what happens with how an option's state is applied.
This update brings a new experimental config API that utilises Mojang's Codec for (de)serialization.
```java
public class CodecConfig extends JsonFileCodecConfig/*or*/CodecConfig {
public static final CodecConfig INSTANCE = new CodecConfig();
public final ConfigEntry<Integer> myInt =
register("my_int", 0, Codec.INT);
public final ReadonlyConfigEntry<InnerCodecConfig> myInnerConfig =
register("my_inner_config", InnerCodecConfig.INSTANCE);
public CodecConfig() {
super(path);
}
void test() {
loadFromFile(); // load like this
saveToFile(); // save like this
// or if you just extend CodecConfig instead of JsonFileConfig:
JsonElement element = null;
this.decode(element, JsonOps.INSTANCE); // load
DataResult<JsonElement> encoded = this.encodeStart(JsonOps.INSTANCE); // save
}
}
```
or in Kotlin...
```kotlin
object CodecConfig : JsonFileCodecConfig(path) {
val myInt by register<Int>(0, Codec.INT)
val myInnerConfig by register(InnerCodecConfig)
fun test() {
loadFromFile()
saveToFile()
// blah blah blah
}
}
```
## Rewritten Kotlin DSL
Completely rewrote the Kotlin DSL!
```kotlin
YetAnotherConfigLib("namespace") {
val category by categories.registering {
val option by rootOptions.registering<Int> {
controller = slider(range = 5..10)
binding(::thisProp, default)
val otherOption by categories["category"]["group"].futureRef<Boolean>()
otherOption.onReady { it.setAvailable(false) }
}
// translation key is generated automagically
val label by rootOptions.registeringLabel
val group by groups.registering {
val otherOption = options.register<Boolean>("otherOption") {
controller = tickBox()
}
}
}
}
```
## Changes
- Fix dropdown controllers erroneously showing their dropdown - Crendgrim
- Make cancel/reset and undo buttons public for accessing
- Add compatibility for 1.21
This update brings a new experimental config API that utilises Mojang's Codec for (de)serialization.
```java
public class CodecConfig extends JsonFileCodecConfig/*or*/CodecConfig {
public static final CodecConfig INSTANCE = new CodecConfig();
public final ConfigEntry<Integer> myInt =
register("my_int", 0, Codec.INT);
public final ReadonlyConfigEntry<InnerCodecConfig> myInnerConfig =
register("my_inner_config", InnerCodecConfig.INSTANCE);
public CodecConfig() {
super(path);
}
void test() {
loadFromFile(); // load like this
saveToFile(); // save like this
// or if you just extend CodecConfig instead of JsonFileConfig:
JsonElement element = null;
this.decode(element, JsonOps.INSTANCE); // load
DataResult<JsonElement> encoded = this.encodeStart(JsonOps.INSTANCE); // save
}
}
```
or in Kotlin...
```kotlin
object CodecConfig : JsonFileCodecConfig(path) {
val myInt by register<Int>(0, Codec.INT)
val myInnerConfig by register(InnerCodecConfig)
fun test() {
loadFromFile()
saveToFile()
// blah blah blah
}
}
```
## Rewritten Kotlin DSL
Completely rewrote the Kotlin DSL!
```kotlin
YetAnotherConfigLib("namespace") {
val category by categories.registering {
val option by rootOptions.registering<Int> {
controller = slider(range = 5..10)
binding(::thisProp, default)
val otherOption by categories["category"]["group"].futureRef<Boolean>()
otherOption.onReady { it.setAvailable(false) }
}
// translation key is generated automagically
val label by rootOptions.registeringLabel
val group by groups.registering {
val otherOption = options.register<Boolean>("otherOption") {
controller = tickBox()
}
}
}
}
```
## Changes
- Fix dropdown controllers erroneously showing their dropdown - Crendgrim
- Make cancel/reset and undo buttons public for accessing
- Add compatibility for 1.21
This update brings a new experimental config API that utilises Mojang's Codec for (de)serialization.
```java
public class CodecConfig extends JsonFileCodecConfig/*or*/CodecConfig {
public static final CodecConfig INSTANCE = new CodecConfig();
public final ConfigEntry<Integer> myInt =
register("my_int", 0, Codec.INT);
public final ReadonlyConfigEntry<InnerCodecConfig> myInnerConfig =
register("my_inner_config", InnerCodecConfig.INSTANCE);
public CodecConfig() {
super(path);
}
void test() {
loadFromFile(); // load like this
saveToFile(); // save like this
// or if you just extend CodecConfig instead of JsonFileConfig:
JsonElement element = null;
this.decode(element, JsonOps.INSTANCE); // load
DataResult<JsonElement> encoded = this.encodeStart(JsonOps.INSTANCE); // save
}
}
```
or in Kotlin...
```kotlin
object CodecConfig : JsonFileCodecConfig(path) {
val myInt by register<Int>(0, Codec.INT)
val myInnerConfig by register(InnerCodecConfig)
fun test() {
loadFromFile()
saveToFile()
// blah blah blah
}
}
```
## Rewritten Kotlin DSL
Completely rewrote the Kotlin DSL!
```kotlin
YetAnotherConfigLib("namespace") {
val category by categories.registering {
val option by rootOptions.registering<Int> {
controller = slider(range = 5..10)
binding(::thisProp, default)
val otherOption by categories["category"]["group"].futureRef<Boolean>()
otherOption.onReady { it.setAvailable(false) }
}
// translation key is generated automagically
val label by rootOptions.registeringLabel
val group by groups.registering {
val otherOption = options.register<Boolean>("otherOption") {
controller = tickBox()
}
}
}
}
```
## Changes
- Fix dropdown controllers erroneously showing their dropdown - Crendgrim
- Make cancel/reset and undo buttons public for accessing
- Add compatibility for 1.21
This update brings a new experimental config API that utilises Mojang's Codec for (de)serialization.
```java
public class CodecConfig extends JsonFileCodecConfig/*or*/CodecConfig {
public static final CodecConfig INSTANCE = new CodecConfig();
public final ConfigEntry<Integer> myInt =
register("my_int", 0, Codec.INT);
public final ReadonlyConfigEntry<InnerCodecConfig> myInnerConfig =
register("my_inner_config", InnerCodecConfig.INSTANCE);
public CodecConfig() {
super(path);
}
void test() {
loadFromFile(); // load like this
saveToFile(); // save like this
// or if you just extend CodecConfig instead of JsonFileConfig:
JsonElement element = null;
this.decode(element, JsonOps.INSTANCE); // load
DataResult<JsonElement> encoded = this.encodeStart(JsonOps.INSTANCE); // save
}
}
```
or in Kotlin...
```kotlin
object CodecConfig : JsonFileCodecConfig(path) {
val myInt by register<Int>(0, Codec.INT)
val myInnerConfig by register(InnerCodecConfig)
fun test() {
loadFromFile()
saveToFile()
// blah blah blah
}
}
```
## Rewritten Kotlin DSL
Completely rewrote the Kotlin DSL!
```kotlin
YetAnotherConfigLib("namespace") {
val category by categories.registering {
val option by rootOptions.registering<Int> {
controller = slider(range = 5..10)
binding(::thisProp, default)
val otherOption by categories["category"]["group"].futureRef<Boolean>()
otherOption.onReady { it.setAvailable(false) }
}
// translation key is generated automagically
val label by rootOptions.registeringLabel
val group by groups.registering {
val otherOption = options.register<Boolean>("otherOption") {
controller = tickBox()
}
}
}
}
```
## Changes
- Fix dropdown controllers erroneously showing their dropdown - Crendgrim
- Make cancel/reset and undo buttons public for accessing
- Add compatibility for 1.21
This update brings a new experimental config API that utilises Mojang's Codec for (de)serialization.
```java
public class CodecConfig extends JsonFileCodecConfig/*or*/CodecConfig {
public static final CodecConfig INSTANCE = new CodecConfig();
public final ConfigEntry<Integer> myInt =
register("my_int", 0, Codec.INT);
public final ReadonlyConfigEntry<InnerCodecConfig> myInnerConfig =
register("my_inner_config", InnerCodecConfig.INSTANCE);
public CodecConfig() {
super(path);
}
void test() {
loadFromFile(); // load like this
saveToFile(); // save like this
// or if you just extend CodecConfig instead of JsonFileConfig:
JsonElement element = null;
this.decode(element, JsonOps.INSTANCE); // load
DataResult<JsonElement> encoded = this.encodeStart(JsonOps.INSTANCE); // save
}
}
```
or in Kotlin...
```kotlin
object CodecConfig : JsonFileCodecConfig(path) {
val myInt by register<Int>(0, Codec.INT)
val myInnerConfig by register(InnerCodecConfig)
fun test() {
loadFromFile()
saveToFile()
// blah blah blah
}
}
```
## Rewritten Kotlin DSL
Completely rewrote the Kotlin DSL!
```kotlin
YetAnotherConfigLib("namespace") {
val category by categories.registering {
val option by rootOptions.registering<Int> {
controller = slider(range = 5..10)
binding(::thisProp, default)
val otherOption by categories["category"]["group"].futureRef<Boolean>()
otherOption.onReady { it.setAvailable(false) }
}
// translation key is generated automagically
val label by rootOptions.registeringLabel
val group by groups.registering {
val otherOption = options.register<Boolean>("otherOption") {
controller = tickBox()
}
}
}
}
```
## Changes
- Fix dropdown controllers erroneously showing their dropdown - Crendgrim
- Make cancel/reset and undo buttons public for accessing
- Add compatibility for 1.21
This update brings a new experimental config API that utilises Mojang's Codec for (de)serialization.
```java
public class CodecConfig extends JsonFileCodecConfig/*or*/CodecConfig {
public static final CodecConfig INSTANCE = new CodecConfig();
public final ConfigEntry<Integer> myInt =
register("my_int", 0, Codec.INT);
public final ReadonlyConfigEntry<InnerCodecConfig> myInnerConfig =
register("my_inner_config", InnerCodecConfig.INSTANCE);
public CodecConfig() {
super(path);
}
void test() {
loadFromFile(); // load like this
saveToFile(); // save like this
// or if you just extend CodecConfig instead of JsonFileConfig:
JsonElement element = null;
this.decode(element, JsonOps.INSTANCE); // load
DataResult<JsonElement> encoded = this.encodeStart(JsonOps.INSTANCE); // save
}
}
```
or in Kotlin...
```kotlin
object CodecConfig : JsonFileCodecConfig(path) {
val myInt by register<Int>(0, Codec.INT)
val myInnerConfig by register(InnerCodecConfig)
fun test() {
loadFromFile()
saveToFile()
// blah blah blah
}
}
```
## Rewritten Kotlin DSL
Completely rewrote the Kotlin DSL!
```kotlin
YetAnotherConfigLib("namespace") {
val category by categories.registering {
val option by rootOptions.registering<Int> {
controller = slider(range = 5..10)
binding(::thisProp, default)
val otherOption by categories["category"]["group"].futureRef<Boolean>()
otherOption.onReady { it.setAvailable(false) }
}
// translation key is generated automagically
val label by rootOptions.registeringLabel
val group by groups.registering {
val otherOption = options.register<Boolean>("otherOption") {
controller = tickBox()
}
}
}
}
```
## Changes
- Fix dropdown controllers erroneously showing their dropdown - Crendgrim
- Make cancel/reset and undo buttons public for accessing
- Add compatibility for 1.21
This update brings a new experimental config API that utilises Mojang's Codec for (de)serialization.
```java
public class CodecConfig extends JsonFileCodecConfig/*or*/CodecConfig {
public static final CodecConfig INSTANCE = new CodecConfig();
public final ConfigEntry<Integer> myInt =
register("my_int", 0, Codec.INT);
public final ReadonlyConfigEntry<InnerCodecConfig> myInnerConfig =
register("my_inner_config", InnerCodecConfig.INSTANCE);
public CodecConfig() {
super(path);
}
void test() {
loadFromFile(); // load like this
saveToFile(); // save like this
// or if you just extend CodecConfig instead of JsonFileConfig:
JsonElement element = null;
this.decode(element, JsonOps.INSTANCE); // load
DataResult<JsonElement> encoded = this.encodeStart(JsonOps.INSTANCE); // save
}
}
```
or in Kotlin...
```kotlin
object CodecConfig : JsonFileCodecConfig(path) {
val myInt by register<Int>(0, Codec.INT)
val myInnerConfig by register(InnerCodecConfig)
fun test() {
loadFromFile()
saveToFile()
// blah blah blah
}
}
```
## Rewritten Kotlin DSL
Completely rewrote the Kotlin DSL!
```kotlin
YetAnotherConfigLib("namespace") {
val category by categories.registering {
val option by rootOptions.registering<Int> {
controller = slider(range = 5..10)
binding(::thisProp, default)
val otherOption by categories["category"]["group"].futureRef<Boolean>()
otherOption.onReady { it.setAvailable(false) }
}
// translation key is generated automagically
val label by rootOptions.registeringLabel
val group by groups.registering {
val otherOption = options.register<Boolean>("otherOption") {
controller = tickBox()
}
}
}
}
```
## Changes
- Fix dropdown controllers erroneously showing their dropdown - Crendgrim
- Make cancel/reset and undo buttons public for accessing
- Add compatibility for 1.21
This update brings a new experimental config API that utilises Mojang's Codec for (de)serialization.
```java
public class CodecConfig extends JsonFileCodecConfig/*or*/CodecConfig {
public static final CodecConfig INSTANCE = new CodecConfig();
public final ConfigEntry<Integer> myInt =
register("my_int", 0, Codec.INT);
public final ReadonlyConfigEntry<InnerCodecConfig> myInnerConfig =
register("my_inner_config", InnerCodecConfig.INSTANCE);
public CodecConfig() {
super(path);
}
void test() {
loadFromFile(); // load like this
saveToFile(); // save like this
// or if you just extend CodecConfig instead of JsonFileConfig:
JsonElement element = null;
this.decode(element, JsonOps.INSTANCE); // load
DataResult<JsonElement> encoded = this.encodeStart(JsonOps.INSTANCE); // save
}
}
```
or in Kotlin...
```kotlin
object CodecConfig : JsonFileCodecConfig(path) {
val myInt by register<Int>(0, Codec.INT)
val myInnerConfig by register(InnerCodecConfig)
fun test() {
loadFromFile()
saveToFile()
// blah blah blah
}
}
```
## Rewritten Kotlin DSL
Completely rewrote the Kotlin DSL!
```kotlin
YetAnotherConfigLib("namespace") {
val category by categories.registering {
val option by rootOptions.registering<Int> {
controller = slider(range = 5..10)
binding(::thisProp, default)
val otherOption by categories["category"]["group"].futureRef<Boolean>()
otherOption.onReady { it.setAvailable(false) }
}
// translation key is generated automagically
val label by rootOptions.registeringLabel
val group by groups.registering {
val otherOption = options.register<Boolean>("otherOption") {
controller = tickBox()
}
}
}
}
```
## Changes
- Fix dropdown controllers erroneously showing their dropdown - Crendgrim
- Make cancel/reset and undo buttons public for accessing
- Add compatibility for 1.21
This update brings a new experimental config API that utilises Mojang's Codec for (de)serialization.
```java
public class CodecConfig extends JsonFileCodecConfig/*or*/CodecConfig {
public static final CodecConfig INSTANCE = new CodecConfig();
public final ConfigEntry<Integer> myInt =
register("my_int", 0, Codec.INT);
public final ReadonlyConfigEntry<InnerCodecConfig> myInnerConfig =
register("my_inner_config", InnerCodecConfig.INSTANCE);
public CodecConfig() {
super(path);
}
void test() {
loadFromFile(); // load like this
saveToFile(); // save like this
// or if you just extend CodecConfig instead of JsonFileConfig:
JsonElement element = null;
this.decode(element, JsonOps.INSTANCE); // load
DataResult<JsonElement> encoded = this.encodeStart(JsonOps.INSTANCE); // save
}
}
```
or in Kotlin...
```kotlin
object CodecConfig : JsonFileCodecConfig(path) {
val myInt by register<Int>(0, Codec.INT)
val myInnerConfig by register(InnerCodecConfig)
fun test() {
loadFromFile()
saveToFile()
// blah blah blah
}
}
```
## Rewritten Kotlin DSL
Completely rewrote the Kotlin DSL!
```kotlin
YetAnotherConfigLib("namespace") {
val category by categories.registering {
val option by rootOptions.registering<Int> {
controller = slider(range = 5..10)
binding(::thisProp, default)
val otherOption by categories["category"]["group"].futureRef<Boolean>()
otherOption.onReady { it.setAvailable(false) }
}
// translation key is generated automagically
val label by rootOptions.registeringLabel
val group by groups.registering {
val otherOption = options.register<Boolean>("otherOption") {
controller = tickBox()
}
}
}
}
```
## Changes
- Fix dropdown controllers erroneously showing their dropdown - Crendgrim
- Make cancel/reset and undo buttons public for accessing
- Add compatibility for 1.21
This build supports the following versions:
- Fabric 1.20.1
- Fabric 1.20.4
- Fabric 1.20.6 (also supports 1.20.5)
- NeoForge 1.20.6 (also supports 1.20.5)
- NeoForge 1.20.4
- MinecraftForge 1.20.1
## Bug Fixes
- Fix YACL's metadata not displaying properly in MultiMC and its forks.
- Fix (Neo)Forge throwing an unusual error when a user accidentally puts YACL for fabric on forge.
- Fix access transformer not being present on NeoForge builds, causing crashes.
- Fix right mouse button not propagating to controllers.
([#180](https://github.com/isXander/YetAnotherConfigLib/pull/180), thanks Crendgrim)
This build supports the following versions:
- Fabric 1.20.1
- Fabric 1.20.4
- Fabric 1.20.6 (also supports 1.20.5)
- NeoForge 1.20.6 (also supports 1.20.5)
- NeoForge 1.20.4
- MinecraftForge 1.20.1
## Bug Fixes
- Fix YACL's metadata not displaying properly in MultiMC and its forks.
- Fix (Neo)Forge throwing an unusual error when a user accidentally puts YACL for fabric on forge.
- Fix access transformer not being present on NeoForge builds, causing crashes.
- Fix right mouse button not propagating to controllers.
([#180](https://github.com/isXander/YetAnotherConfigLib/pull/180), thanks Crendgrim)
This build supports the following versions:
- Fabric 1.20.1
- Fabric 1.20.4
- Fabric 1.20.6 (also supports 1.20.5)
- NeoForge 1.20.6 (also supports 1.20.5)
- NeoForge 1.20.4
- MinecraftForge 1.20.1
## Bug Fixes
- Fix YACL's metadata not displaying properly in MultiMC and its forks.
- Fix (Neo)Forge throwing an unusual error when a user accidentally puts YACL for fabric on forge.
- Fix access transformer not being present on NeoForge builds, causing crashes.
- Fix right mouse button not propagating to controllers.
([#180](https://github.com/isXander/YetAnotherConfigLib/pull/180), thanks Crendgrim)
This build supports the following versions:
- Fabric 1.20.1
- Fabric 1.20.4
- Fabric 1.20.6 (also supports 1.20.5)
- NeoForge 1.20.6 (also supports 1.20.5)
- NeoForge 1.20.4
- MinecraftForge 1.20.1
## Bug Fixes
- Fix YACL's metadata not displaying properly in MultiMC and its forks.
- Fix (Neo)Forge throwing an unusual error when a user accidentally puts YACL for fabric on forge.
- Fix access transformer not being present on NeoForge builds, causing crashes.
- Fix right mouse button not propagating to controllers.
([#180](https://github.com/isXander/YetAnotherConfigLib/pull/180), thanks Crendgrim)
This build supports the following versions:
- Fabric 1.20.1
- Fabric 1.20.4
- Fabric 1.20.5
- Forge 1.20.1
- NeoForge 1.20.4
## For developers...
This is the first build which uses a new build toolchain to support multiple minecraft versions in the same codebase.
With this change, the artifact of the mod has changed.
```groovy
modImplementation "dev.isxander:yet-another-config-lib:{modversion}+{mcversion}-{loader}"
// for example...
modImplementation "dev.isxander:yet-another-config-lib:3.4.0+1.20.1-fabric"
```
If you are using YACL in an architectury project (one with a common subproject), you will from now on depend on
the fabric version of YACL. There is no longer any common artifact. I don't believe there to be any issues with doing it
like this.
## Additions
- New colour picker widget by [Superkat32](https://github.com/isXander/YetAnotherConfigLib/pull/140)
- This works with existing colour options.
- Added a custom tab API so categories can provide their own GUI, instead of YACL options.
- Mod developers can make their category class implement `CustomTabProvider`. Javadoc is available.
- Add a new Kotlin DSL for creating your YACL UIs. This is a wrapper on top of the java builder interface providing extra functionality for Kotlin users.
- YACL does not provide any kotlin libraries, nor does it depend on them. If you would like to use this DSL, make sure your own mod depends on your loader's Kotlin mod.
- This is included in the main artifact. You don't need additional dependencies.
- An example usage can be found [in the testmod](https://github.com/isXander/YetAnotherConfigLib/blob/multiversion/dev/src/testmod/kotlin/dev/isxander/yacl3/test/DslTest.kt)
- Improved the backend of dropdown controllers by [Crendgrim](https://github.com/isXander/YetAnotherConfigLib/pull/162)
## Bug Fixes
- Fix GIFs not being preloaded in the resource reloader
This build supports the following versions:
- Fabric 1.20.1
- Fabric 1.20.4
- Fabric 1.20.5
- Forge 1.20.1
- NeoForge 1.20.4
## For developers...
This is the first build which uses a new build toolchain to support multiple minecraft versions in the same codebase.
With this change, the artifact of the mod has changed.
```groovy
modImplementation "dev.isxander:yet-another-config-lib:{modversion}+{mcversion}-{loader}"
// for example...
modImplementation "dev.isxander:yet-another-config-lib:3.4.0+1.20.1-fabric"
```
If you are using YACL in an architectury project (one with a common subproject), you will from now on depend on
the fabric version of YACL. There is no longer any common artifact. I don't believe there to be any issues with doing it
like this.
## Additions
- New colour picker widget by [Superkat32](https://github.com/isXander/YetAnotherConfigLib/pull/140)
- This works with existing colour options.
- Added a custom tab API so categories can provide their own GUI, instead of YACL options.
- Mod developers can make their category class implement `CustomTabProvider`. Javadoc is available.
- Add a new Kotlin DSL for creating your YACL UIs. This is a wrapper on top of the java builder interface providing extra functionality for Kotlin users.
- YACL does not provide any kotlin libraries, nor does it depend on them. If you would like to use this DSL, make sure your own mod depends on your loader's Kotlin mod.
- This is included in the main artifact. You don't need additional dependencies.
- An example usage can be found [in the testmod](https://github.com/isXander/YetAnotherConfigLib/blob/multiversion/dev/src/testmod/kotlin/dev/isxander/yacl3/test/DslTest.kt)
- Improved the backend of dropdown controllers by [Crendgrim](https://github.com/isXander/YetAnotherConfigLib/pull/162)
## Bug Fixes
- Fix GIFs not being preloaded in the resource reloader
This build supports the following versions:
- Fabric 1.20.1
- Fabric 1.20.4
- Fabric 1.20.5
- Forge 1.20.1
- NeoForge 1.20.4
## For developers...
This is the first build which uses a new build toolchain to support multiple minecraft versions in the same codebase.
With this change, the artifact of the mod has changed.
```groovy
modImplementation "dev.isxander:yet-another-config-lib:{modversion}+{mcversion}-{loader}"
// for example...
modImplementation "dev.isxander:yet-another-config-lib:3.4.0+1.20.1-fabric"
```
If you are using YACL in an architectury project (one with a common subproject), you will from now on depend on
the fabric version of YACL. There is no longer any common artifact. I don't believe there to be any issues with doing it
like this.
## Additions
- New colour picker widget by [Superkat32](https://github.com/isXander/YetAnotherConfigLib/pull/140)
- This works with existing colour options.
- Added a custom tab API so categories can provide their own GUI, instead of YACL options.
- Mod developers can make their category class implement `CustomTabProvider`. Javadoc is available.
- Add a new Kotlin DSL for creating your YACL UIs. This is a wrapper on top of the java builder interface providing extra functionality for Kotlin users.
- YACL does not provide any kotlin libraries, nor does it depend on them. If you would like to use this DSL, make sure your own mod depends on your loader's Kotlin mod.
- This is included in the main artifact. You don't need additional dependencies.
- An example usage can be found [in the testmod](https://github.com/isXander/YetAnotherConfigLib/blob/multiversion/dev/src/testmod/kotlin/dev/isxander/yacl3/test/DslTest.kt)
- Improved the backend of dropdown controllers by [Crendgrim](https://github.com/isXander/YetAnotherConfigLib/pull/162)
## Bug Fixes
- Fix GIFs not being preloaded in the resource reloader
This build supports the following versions:
- Fabric 1.20.1
- Fabric 1.20.4
- Fabric 1.20.5
- Forge 1.20.1
- NeoForge 1.20.4
## For developers...
This is the first build which uses a new build toolchain to support multiple minecraft versions in the same codebase.
With this change, the artifact of the mod has changed.
```groovy
modImplementation "dev.isxander:yet-another-config-lib:{modversion}+{mcversion}-{loader}"
// for example...
modImplementation "dev.isxander:yet-another-config-lib:3.4.0+1.20.1-fabric"
```
If you are using YACL in an architectury project (one with a common subproject), you will from now on depend on
the fabric version of YACL. There is no longer any common artifact. I don't believe there to be any issues with doing it
like this.
## Additions
- New colour picker widget by [Superkat32](https://github.com/isXander/YetAnotherConfigLib/pull/140)
- This works with existing colour options.
- Added a custom tab API so categories can provide their own GUI, instead of YACL options.
- Mod developers can make their category class implement `CustomTabProvider`. Javadoc is available.
- Add a new Kotlin DSL for creating your YACL UIs. This is a wrapper on top of the java builder interface providing extra functionality for Kotlin users.
- YACL does not provide any kotlin libraries, nor does it depend on them. If you would like to use this DSL, make sure your own mod depends on your loader's Kotlin mod.
- This is included in the main artifact. You don't need additional dependencies.
- An example usage can be found [in the testmod](https://github.com/isXander/YetAnotherConfigLib/blob/multiversion/dev/src/testmod/kotlin/dev/isxander/yacl3/test/DslTest.kt)
- Improved the backend of dropdown controllers by [Crendgrim](https://github.com/isXander/YetAnotherConfigLib/pull/162)
## Bug Fixes
- Fix GIFs not being preloaded in the resource reloader
This build supports the following versions:
- Fabric 1.20.1
- Fabric 1.20.4
- Fabric 1.20.5
- Forge 1.20.1
- NeoForge 1.20.4
## For developers...
This is the first build which uses a new build toolchain to support multiple minecraft versions in the same codebase.
With this change, the artifact of the mod has changed.
```groovy
modImplementation "dev.isxander:yet-another-config-lib:{modversion}+{mcversion}-{loader}"
// for example...
modImplementation "dev.isxander:yet-another-config-lib:3.4.0+1.20.1-fabric"
```
If you are using YACL in an architectury project (one with a common subproject), you will from now on depend on
the fabric version of YACL. There is no longer any common artifact. I don't believe there to be any issues with doing it
like this.
## Additions
- New colour picker widget by [Superkat32](https://github.com/isXander/YetAnotherConfigLib/pull/140)
- This works with existing colour options.
- Added a custom tab API so categories can provide their own GUI, instead of YACL options.
- Mod developers can make their category class implement `CustomTabProvider`. Javadoc is available.
- Add a new Kotlin DSL for creating your YACL UIs. This is a wrapper on top of the java builder interface providing extra functionality for Kotlin users.
- YACL does not provide any kotlin libraries, nor does it depend on them. If you would like to use this DSL, make sure your own mod depends on your loader's Kotlin mod.
- This is included in the main artifact. You don't need additional dependencies.
- An example usage can be found [in the testmod](https://github.com/isXander/YetAnotherConfigLib/blob/multiversion/dev/src/testmod/kotlin/dev/isxander/yacl3/test/DslTest.kt)
- Improved the backend of dropdown controllers by [Crendgrim](https://github.com/isXander/YetAnotherConfigLib/pull/162)
## Bug Fixes
- Fix GIFs not being preloaded in the resource reloader
- Hook into the resource reloader to preload any webp/gif files that are used.
This should make loading images when opening GUIs appear instantaneous.
- Fix issue where buttons got stuck and appeared as though nothing had saved.
- Fix an issue on NeoForged where the access widener was not transformed to an access transformer.
- Hook into the resource reloader to preload any webp/gif files that are used.
This should make loading images when opening GUIs appear instantaneous.
- Fix issue where buttons got stuck and appeared as though nothing had saved.
- Fix an issue on NeoForged where the access widener was not transformed to an access transformer.
# YetAnotherConfigLib 3.3.0 (Beta 1) for Minecraft 1.20.2
As you can see, a lot of the contributions to this release are from other people! That's incredible, and I'm very
thankful for the community commitment to this project!
This release is a beta release, which just means that I'm not 100% sure that everything works as intended.
I encourage developers to at least try this build out, and if there are no problems, you're safe to release (I hope!).
## New Features
- Added new methods to add options to groups and categories, including conditional adding and option suppliers.
This increases the chances you don't need to break the huge builder chain present of YACL, so you can just keep writing,
even if you need to conditionally add an option, or run some code around the option. Look for `optionIf`!
## Changes
- Support for the `Home` and `End` keys. ([#108](https://github.com/isXander/YetAnotherConfigLib/pull/108))
- Add functionality for `Ctrl + Left/Right` (you can now jump over words, without selecting it). ([#108](https://github.com/isXander/YetAnotherConfigLib/pull/108))
- Make the 'finding the next word' functionality more consistent with other programs. ([#108](https://github.com/isXander/YetAnotherConfigLib/pull/108))
- Caret now pauses flickering when moving it. ([#108](https://github.com/isXander/YetAnotherConfigLib/pull/108))
- Position the caret and the highlight area being the same height as the text. ([#108](https://github.com/isXander/YetAnotherConfigLib/pull/108))
- Render the caret above the selection, instead of below. ([#108](https://github.com/isXander/YetAnotherConfigLib/pull/108))
## Fixes
- Fix `NumberFieldController` increasing their values by a power of 10 when clicking on the screen. Issue @ [#103](https://github.com/isXander/YetAnotherConfigLib/issue/103) PR @ [#108](https://github.com/isXander/YetAnotherConfigLib/pull/108)
- Fix values not updating when unfocusing a string controller. ([#108](https://github.com/isXander/YetAnotherConfigLib/pull/108))
- Fix a bug where the caret is not rendered at the beginning of the text in string/number field controllers. ([#108](https://github.com/isXander/YetAnotherConfigLib/pull/108))
- Fix dropdowns not being sorted correctly with capital letters. ([#114](https://github.com/isXander/YetAnotherConfigLib/pull/114))
## Misc
- Added debug JVM property `-Dyacl3.debug.imageFiltering=true/false` which applies experimental filtering to images
to make them look better. I'd like your feedback on this!
- You now no longer need to add additional repositories to your `build.gradle`.
You can safely remove:
- `https://maven.quiltmc.org/repository/release/`
- `https://oss.sonatype.org/content/repositories/snapshots/`
## Translation Updates
- Add Dutch translation. ([#121](https://github.com/isXander/YetAnotherConfigLib/pull/121))
- Add Italian translation. ([#107](https://github.com/isXander/YetAnotherConfigLib/pull/107))
# YetAnotherConfigLib 3.3.0 (Beta 1) for Minecraft 1.20.2
As you can see, a lot of the contributions to this release are from other people! That's incredible, and I'm very
thankful for the community commitment to this project!
This release is a beta release, which just means that I'm not 100% sure that everything works as intended.
I encourage developers to at least try this build out, and if there are no problems, you're safe to release (I hope!).
## New Features
- Added new methods to add options to groups and categories, including conditional adding and option suppliers.
This increases the chances you don't need to break the huge builder chain present of YACL, so you can just keep writing,
even if you need to conditionally add an option, or run some code around the option. Look for `optionIf`!
## Changes
- Support for the `Home` and `End` keys. ([#108](https://github.com/isXander/YetAnotherConfigLib/pull/108))
- Add functionality for `Ctrl + Left/Right` (you can now jump over words, without selecting it). ([#108](https://github.com/isXander/YetAnotherConfigLib/pull/108))
- Make the 'finding the next word' functionality more consistent with other programs. ([#108](https://github.com/isXander/YetAnotherConfigLib/pull/108))
- Caret now pauses flickering when moving it. ([#108](https://github.com/isXander/YetAnotherConfigLib/pull/108))
- Position the caret and the highlight area being the same height as the text. ([#108](https://github.com/isXander/YetAnotherConfigLib/pull/108))
- Render the caret above the selection, instead of below. ([#108](https://github.com/isXander/YetAnotherConfigLib/pull/108))
## Fixes
- Fix `NumberFieldController` increasing their values by a power of 10 when clicking on the screen. Issue @ [#103](https://github.com/isXander/YetAnotherConfigLib/issue/103) PR @ [#108](https://github.com/isXander/YetAnotherConfigLib/pull/108)
- Fix values not updating when unfocusing a string controller. ([#108](https://github.com/isXander/YetAnotherConfigLib/pull/108))
- Fix a bug where the caret is not rendered at the beginning of the text in string/number field controllers. ([#108](https://github.com/isXander/YetAnotherConfigLib/pull/108))
- Fix dropdowns not being sorted correctly with capital letters. ([#114](https://github.com/isXander/YetAnotherConfigLib/pull/114))
## Misc
- Added debug JVM property `-Dyacl3.debug.imageFiltering=true/false` which applies experimental filtering to images
to make them look better. I'd like your feedback on this!
- You now no longer need to add additional repositories to your `build.gradle`.
You can safely remove:
- `https://maven.quiltmc.org/repository/release/`
- `https://oss.sonatype.org/content/repositories/snapshots/`
## Translation Updates
- Add Dutch translation. ([#121](https://github.com/isXander/YetAnotherConfigLib/pull/121))
- Add Italian translation. ([#107](https://github.com/isXander/YetAnotherConfigLib/pull/107))
- Added `ConfigClassHandler#save` and `ConfigClassHandler#load` and deprecated `ConfigClassHandler#serializer`.
- The serializer should now never be called directly.
- New load method tells serializer to load into a new instance of the config class. Only applied if the load was fully successful.
- Deprecated `ConfigSerializer#load` for `ConfigSerializer#loadSafely`.
- Added new parameter on `SerialEntry`, called `required`.
- If set to true, and the entry is not found in the config, the config will be re-saved with the default value.
- If set to false, and the entry is not found in the config, the default value will be used, but the config will not be re-saved.
- Added new parameter on `SerialEntry`, called `nullable`.
- If set to false, and the entry is found in the config, but the value is null, the default value will be used, and the config will be re-saved.
## Bug Fixes
- Fixed error when using the same image twice.
- Removed debug log from WEBP and GIF image loaders.
- Added `ConfigClassHandler#save` and `ConfigClassHandler#load` and deprecated `ConfigClassHandler#serializer`.
- The serializer should now never be called directly.
- New load method tells serializer to load into a new instance of the config class. Only applied if the load was fully successful.
- Deprecated `ConfigSerializer#load` for `ConfigSerializer#loadSafely`.
- Added new parameter on `SerialEntry`, called `required`.
- If set to true, and the entry is not found in the config, the config will be re-saved with the default value.
- If set to false, and the entry is not found in the config, the default value will be used, but the config will not be re-saved.
- Added new parameter on `SerialEntry`, called `nullable`.
- If set to false, and the entry is found in the config, but the value is null, the default value will be used, and the config will be re-saved.
## Bug Fixes
- Fixed error when using the same image twice.
- Removed debug log from WEBP and GIF image loaders.
- Added `ConfigClassHandler#save` and `ConfigClassHandler#load` and deprecated `ConfigClassHandler#serializer`.
- The serializer should now never be called directly.
- New load method tells serializer to load into a new instance of the config class. Only applied if the load was fully successful.
- Deprecated `ConfigSerializer#load` for `ConfigSerializer#loadSafely`.
- Added new parameter on `SerialEntry`, called `required`.
- If set to true, and the entry is not found in the config, the config will be re-saved with the default value.
- If set to false, and the entry is not found in the config, the default value will be used, but the config will not be re-saved.
- Added new parameter on `SerialEntry`, called `nullable`.
- If set to false, and the entry is found in the config, but the value is null, the default value will be used, and the config will be re-saved.
## Bug Fixes
- Fixed error when using the same image twice.
- Removed debug log from WEBP and GIF image loaders.
- Added `ConfigClassHandler#save` and `ConfigClassHandler#load` and deprecated `ConfigClassHandler#serializer`.
- The serializer should now never be called directly.
- New load method tells serializer to load into a new instance of the config class. Only applied if the load was fully successful.
- Deprecated `ConfigSerializer#load` for `ConfigSerializer#loadSafely`.
- Added new parameter on `SerialEntry`, called `required`.
- If set to true, and the entry is not found in the config, the config will be re-saved with the default value.
- If set to false, and the entry is not found in the config, the default value will be used, but the config will not be re-saved.
- Added new parameter on `SerialEntry`, called `nullable`.
- If set to false, and the entry is found in the config, but the value is null, the default value will be used, and the config will be re-saved.
## Bug Fixes
- Fixed error when using the same image twice.
- Removed debug log from WEBP and GIF image loaders.
The artifact for this release is
`dev.isxander.yacl:yet-another-config-lib-fabric:3.2.0+1.20` (assuming Fabric)
## Config API V2
Starting this update, the previous config api is now deprecated.
The new API is much more modular, and is now fully API-safe.
### What does it look like?
```java
public class MyConfig {
public static final ConfigClassHandler<MyConfig> HANDLER = ConfigClassHandler.createBuilder(MyConfig.class)
.id(new ResourceLocation("my_mod", "my_config")) // unique ID for your config
.serializer(config -> GsonConfigSerializerBuilder.create(config)
.setPath(FabricLoader.getInstance().getConfigDir().resolve("my_config.json"))
.setJson5(true) // json5 support, with GSON!
.build())
.build();
@SerialEntry(comment = "optional comment!")
public boolean myOption = true;
public static void save() {
MyConfig.HANDLER.serializer().save();
}
public static void load() {
MyConfig.HANDLER.serializer().load();
}
}
```
As you can see from the above example, it's syntactically quite similar
to the old API, but with a few key differences:
- The method of serialization has been separated from the class handler itself,
allowing an API safe implementation without needing to override the class handler.
- Supports abstract serialization.
- Names make a lot more sense.
### Auto-gen
The new API can now fully auto-generate your config into a YACL GUI with annotations.
I have been very wary of this feature, since usually it can be very limiting, destroying most
of the core values of the powerful YACL builder interface. However, I believe I've found a great
modular way so that developers can extend the auto-gen feature with their own custom annotations,
adding support for their own custom controllers!
```java
public class MyConfig {
public static final ConfigClassHandler<MyConfig> HANDLER = ConfigClassHandler.createBuilder(MyConfig.class)
.id(new ResourceLocation("my_mod", "my_config")) // unique ID for your config
.serializer(config -> GsonConfigSerializerBuilder.create(config)
.setPath(FabricLoader.getInstance().getConfigDir().resolve("my_config.json"))
.setJson5(true) // json5 support, with GSON!
.build())
.build();
@AutoGen(category = "my_category", group = "my_group")
@Boolean(formatter = Boolean.Formatter.YES_NO, colored = true)
public boolean myOption = true;
Above is an example of auto-generating a `BooleanController`. Notice how
the field does not require `@SerialEntry`. These are completely separate,
and you can use both at the same time.
For the full range of auto-gen annotations, check the source!
Documentation for the new API is still a work in progress. For now, it's best
to look at the following class: [`dev.isxander.yacl3.test.AutogenConfigTest`](https://github.com/isXander/YetAnotherConfigLib/blob/1.20.x/dev/test-common/src/main/java/dev/isxander/yacl3/test/AutogenConfigTest.java) (not available on the artifact).
## Fix Sodium crash
This is bringing the off-branch hotfix 3.1.1 to the main branch.
## Dropdown controllers
[Crendgrim](https://github.com/isXander/Crendgrim) has PRed a dropdown controller! Which is in this release!
This adds two new controller builders, `DropdownStringControllerBuilder` and `ItemControllerBuilder`.
The latter renders the item in the dropdown, and suggests only the items.
The artifact for this release is
`dev.isxander.yacl:yet-another-config-lib-fabric:3.2.0+1.20` (assuming Fabric)
## Config API V2
Starting this update, the previous config api is now deprecated.
The new API is much more modular, and is now fully API-safe.
### What does it look like?
```java
public class MyConfig {
public static final ConfigClassHandler<MyConfig> HANDLER = ConfigClassHandler.createBuilder(MyConfig.class)
.id(new ResourceLocation("my_mod", "my_config")) // unique ID for your config
.serializer(config -> GsonConfigSerializerBuilder.create(config)
.setPath(FabricLoader.getInstance().getConfigDir().resolve("my_config.json"))
.setJson5(true) // json5 support, with GSON!
.build())
.build();
@SerialEntry(comment = "optional comment!")
public boolean myOption = true;
public static void save() {
MyConfig.HANDLER.serializer().save();
}
public static void load() {
MyConfig.HANDLER.serializer().load();
}
}
```
As you can see from the above example, it's syntactically quite similar
to the old API, but with a few key differences:
- The method of serialization has been separated from the class handler itself,
allowing an API safe implementation without needing to override the class handler.
- Supports abstract serialization.
- Names make a lot more sense.
### Auto-gen
The new API can now fully auto-generate your config into a YACL GUI with annotations.
I have been very wary of this feature, since usually it can be very limiting, destroying most
of the core values of the powerful YACL builder interface. However, I believe I've found a great
modular way so that developers can extend the auto-gen feature with their own custom annotations,
adding support for their own custom controllers!
```java
public class MyConfig {
public static final ConfigClassHandler<MyConfig> HANDLER = ConfigClassHandler.createBuilder(MyConfig.class)
.id(new ResourceLocation("my_mod", "my_config")) // unique ID for your config
.serializer(config -> GsonConfigSerializerBuilder.create(config)
.setPath(FabricLoader.getInstance().getConfigDir().resolve("my_config.json"))
.setJson5(true) // json5 support, with GSON!
.build())
.build();
@AutoGen(category = "my_category", group = "my_group")
@Boolean(formatter = Boolean.Formatter.YES_NO, colored = true)
public boolean myOption = true;
Above is an example of auto-generating a `BooleanController`. Notice how
the field does not require `@SerialEntry`. These are completely separate,
and you can use both at the same time.
For the full range of auto-gen annotations, check the source!
Documentation for the new API is still a work in progress. For now, it's best
to look at the following class: [`dev.isxander.yacl3.test.AutogenConfigTest`](https://github.com/isXander/YetAnotherConfigLib/blob/1.20.x/dev/test-common/src/main/java/dev/isxander/yacl3/test/AutogenConfigTest.java) (not available on the artifact).
## Fix Sodium crash
This is bringing the off-branch hotfix 3.1.1 to the main branch.
## Dropdown controllers
[Crendgrim](https://github.com/isXander/Crendgrim) has PRed a dropdown controller! Which is in this release!
This adds two new controller builders, `DropdownStringControllerBuilder` and `ItemControllerBuilder`.
The latter renders the item in the dropdown, and suggests only the items.
The artifact for this release is
`dev.isxander.yacl:yet-another-config-lib-fabric:3.2.0+1.20.2` (assuming Fabric)
## Config API V2
Starting this update, the previous config api is now deprecated.
The new API is much more modular, and is now fully API-safe.
### What does it look like?
```java
public class MyConfig {
public static final ConfigClassHandler<MyConfig> HANDLER = ConfigClassHandler.createBuilder(MyConfig.class)
.id(new ResourceLocation("my_mod", "my_config")) // unique ID for your config
.serializer(config -> GsonConfigSerializerBuilder.create(config)
.setPath(FabricLoader.getInstance().getConfigDir().resolve("my_config.json"))
.setJson5(true) // json5 support, with GSON!
.build())
.build();
@SerialEntry(comment = "optional comment!")
public boolean myOption = true;
public static void save() {
MyConfig.HANDLER.serializer().save();
}
public static void load() {
MyConfig.HANDLER.serializer().load();
}
}
```
As you can see from the above example, it's syntactically quite similar
to the old API, but with a few key differences:
- The method of serialization has been separated from the class handler itself,
allowing an API safe implementation without needing to override the class handler.
- Supports abstract serialization.
- Names make a lot more sense.
### Auto-gen
The new API can now fully auto-generate your config into a YACL GUI with annotations.
I have been very wary of this feature, since usually it can be very limiting, destroying most
of the core values of the powerful YACL builder interface. However, I believe I've found a great
modular way so that developers can extend the auto-gen feature with their own custom annotations,
adding support for their own custom controllers!
```java
public class MyConfig {
public static final ConfigClassHandler<MyConfig> HANDLER = ConfigClassHandler.createBuilder(MyConfig.class)
.id(new ResourceLocation("my_mod", "my_config")) // unique ID for your config
.serializer(config -> GsonConfigSerializerBuilder.create(config)
.setPath(FabricLoader.getInstance().getConfigDir().resolve("my_config.json"))
.setJson5(true) // json5 support, with GSON!
.build())
.build();
@AutoGen(category = "my_category", group = "my_group")
@Boolean(formatter = Boolean.Formatter.YES_NO, colored = true)
public boolean myOption = true;
Above is an example of auto-generating a `BooleanController`. Notice how
the field does not require `@SerialEntry`. These are completely separate,
and you can use both at the same time.
For the full range of auto-gen annotations, check the source!
Documentation for the new API is still a work in progress. For now, it's best
to look at the following class: [`dev.isxander.yacl3.test.AutogenConfigTest`](https://github.com/isXander/YetAnotherConfigLib/blob/1.20.x/dev/test-common/src/main/java/dev/isxander/yacl3/test/AutogenConfigTest.java) (not available on the artifact).
## Fix Sodium crash
This is bringing the off-branch hotfix 3.1.1 to the main branch.
## Dropdown controllers
[Crendgrim](https://github.com/isXander/Crendgrim) has PRed a dropdown controller! Which is in this release!
This adds two new controller builders, `DropdownStringControllerBuilder` and `ItemControllerBuilder`.
The latter renders the item in the dropdown, and suggests only the items.
The artifact for this release is
`dev.isxander.yacl:yet-another-config-lib-fabric:3.2.0+1.20.2` (assuming Fabric)
## Config API V2
Starting this update, the previous config api is now deprecated.
The new API is much more modular, and is now fully API-safe.
### What does it look like?
```java
public class MyConfig {
public static final ConfigClassHandler<MyConfig> HANDLER = ConfigClassHandler.createBuilder(MyConfig.class)
.id(new ResourceLocation("my_mod", "my_config")) // unique ID for your config
.serializer(config -> GsonConfigSerializerBuilder.create(config)
.setPath(FabricLoader.getInstance().getConfigDir().resolve("my_config.json"))
.setJson5(true) // json5 support, with GSON!
.build())
.build();
@SerialEntry(comment = "optional comment!")
public boolean myOption = true;
public static void save() {
MyConfig.HANDLER.serializer().save();
}
public static void load() {
MyConfig.HANDLER.serializer().load();
}
}
```
As you can see from the above example, it's syntactically quite similar
to the old API, but with a few key differences:
- The method of serialization has been separated from the class handler itself,
allowing an API safe implementation without needing to override the class handler.
- Supports abstract serialization.
- Names make a lot more sense.
### Auto-gen
The new API can now fully auto-generate your config into a YACL GUI with annotations.
I have been very wary of this feature, since usually it can be very limiting, destroying most
of the core values of the powerful YACL builder interface. However, I believe I've found a great
modular way so that developers can extend the auto-gen feature with their own custom annotations,
adding support for their own custom controllers!
```java
public class MyConfig {
public static final ConfigClassHandler<MyConfig> HANDLER = ConfigClassHandler.createBuilder(MyConfig.class)
.id(new ResourceLocation("my_mod", "my_config")) // unique ID for your config
.serializer(config -> GsonConfigSerializerBuilder.create(config)
.setPath(FabricLoader.getInstance().getConfigDir().resolve("my_config.json"))
.setJson5(true) // json5 support, with GSON!
.build())
.build();
@AutoGen(category = "my_category", group = "my_group")
@Boolean(formatter = Boolean.Formatter.YES_NO, colored = true)
public boolean myOption = true;
Above is an example of auto-generating a `BooleanController`. Notice how
the field does not require `@SerialEntry`. These are completely separate,
and you can use both at the same time.
For the full range of auto-gen annotations, check the source!
Documentation for the new API is still a work in progress. For now, it's best
to look at the following class: [`dev.isxander.yacl3.test.AutogenConfigTest`](https://github.com/isXander/YetAnotherConfigLib/blob/1.20.x/dev/test-common/src/main/java/dev/isxander/yacl3/test/AutogenConfigTest.java) (not available on the artifact).
## Fix Sodium crash
This is bringing the off-branch hotfix 3.1.1 to the main branch.
## Dropdown controllers
[Crendgrim](https://github.com/isXander/Crendgrim) has PRed a dropdown controller! Which is in this release!
This adds two new controller builders, `DropdownStringControllerBuilder` and `ItemControllerBuilder`.
The latter renders the item in the dropdown, and suggests only the items.
The `ImageRenderer` API has been rewritten internally to use a dual-thread
initialization. Before, GL calls were made on a separate thread, which silently
threw errors. Sodium 0.5 introduced an option called `No Error Context`, which turned
these warnings into complete JVM crashes.
Because of this, this rewrite was unavailable.
In the process of a huge YACL update, this commit was buried under a lot more changes
that are not ready for production yet, so I decided to branch from 3.1.0 and cherrypick
this commit to fix the issue.
## Does it affect me as a developer?
Most likely not, declaring images through `OptionDescription.Builder` is unaffected as that
is part of the safe API. However, if you use the `ImageRenderer` directly to create your own
custom renderers, you will have to update your code to use the new API.
## Does it affect me as a user?
Most likely, yes. Zoomify and a few other popular mods use the `ImageRenderer` API directly,
these mods will need updating, and will fail to load the images or even crash if they are not updated.
The `ImageRenderer` API has been rewritten internally to use a dual-thread
initialization. Before, GL calls were made on a separate thread, which silently
threw errors. Sodium 0.5 introduced an option called `No Error Context`, which turned
these warnings into complete JVM crashes.
Because of this, this rewrite was unavailable.
In the process of a huge YACL update, this commit was buried under a lot more changes
that are not ready for production yet, so I decided to branch from 3.1.0 and cherrypick
this commit to fix the issue.
## Does it affect me as a developer?
Most likely not, declaring images through `OptionDescription.Builder` is unaffected as that
is part of the safe API. However, if you use the `ImageRenderer` directly to create your own
custom renderers, you will have to update your code to use the new API.
## Does it affect me as a user?
Most likely, yes. Zoomify and a few other popular mods use the `ImageRenderer` API directly,
these mods will need updating, and will fail to load the images or even crash if they are not updated.
The `ImageRenderer` API has been rewritten internally to use a dual-thread
initialization. Before, GL calls were made on a separate thread, which silently
threw errors. Sodium 0.5 introduced an option called `No Error Context`, which turned
these warnings into complete JVM crashes.
Because of this, this rewrite was unavailable.
In the process of a huge YACL update, this commit was buried under a lot more changes
that are not ready for production yet, so I decided to branch from 3.1.0 and cherrypick
this commit to fix the issue.
## Does it affect me as a developer?
Most likely not, declaring images through `OptionDescription.Builder` is unaffected as that
is part of the safe API. However, if you use the `ImageRenderer` directly to create your own
custom renderers, you will have to update your code to use the new API.
## Does it affect me as a user?
Most likely, yes. Zoomify and a few other popular mods use the `ImageRenderer` API directly,
these mods will need updating, and will fail to load the images or even crash if they are not updated.
The `ImageRenderer` API has been rewritten internally to use a dual-thread
initialization. Before, GL calls were made on a separate thread, which silently
threw errors. Sodium 0.5 introduced an option called `No Error Context`, which turned
these warnings into complete JVM crashes.
Because of this, this rewrite was unavailable.
In the process of a huge YACL update, this commit was buried under a lot more changes
that are not ready for production yet, so I decided to branch from 3.1.0 and cherrypick
this commit to fix the issue.
## Does it affect me as a developer?
Most likely not, declaring images through `OptionDescription.Builder` is unaffected as that
is part of the safe API. However, if you use the `ImageRenderer` directly to create your own
custom renderers, you will have to update your code to use the new API.
## Does it affect me as a user?
Most likely, yes. Zoomify and a few other popular mods use the `ImageRenderer` API directly,
these mods will need updating, and will fail to load the images or even crash if they are not updated.
A PR by [Crendgrim](https://github.com/isXander/YetAnotherConfigLib/pull/89) - thanks a lot!
- Allow to specify size limits for option lists.
- This allows to set a minimum and maximum length for the option list with the `minimumNumberOfEntries`
and `maximumNumberOfEntries` builder methods.
- Allow "reversed" lists that add new options at their end.
- List options until now always grew at the top. This patch allows you to manipulate this behaviour with the
`insertEntriesAtEnd` builder method.
### `ImageRenderer` changes
Added a `tick()` method to image renderers that allows to update the image in a regular interval.
## Bug Fixes
- Fixed a bug where image renderers were rendered twice per frame.
- Updated the ImageIO dependency to fix sometimes buggy animated WebP rendering.
- Fixed the name of the list being rendered on every entry of said list.
A PR by [Crendgrim](https://github.com/isXander/YetAnotherConfigLib/pull/89) - thanks a lot!
- Allow to specify size limits for option lists.
- This allows to set a minimum and maximum length for the option list with the `minimumNumberOfEntries`
and `maximumNumberOfEntries` builder methods.
- Allow "reversed" lists that add new options at their end.
- List options until now always grew at the top. This patch allows you to manipulate this behaviour with the
`insertEntriesAtEnd` builder method.
### `ImageRenderer` changes
Added a `tick()` method to image renderers that allows to update the image in a regular interval.
## Bug Fixes
- Fixed a bug where image renderers were rendered twice per frame.
- Updated the ImageIO dependency to fix sometimes buggy animated WebP rendering.
- Fixed the name of the list being rendered on every entry of said list.
A PR by [Crendgrim](https://github.com/isXander/YetAnotherConfigLib/pull/89) - thanks a lot!
- Allow to specify size limits for option lists.
- This allows to set a minimum and maximum length for the option list with the `minimumNumberOfEntries`
and `maximumNumberOfEntries` builder methods.
- Allow "reversed" lists that add new options at their end.
- List options until now always grew at the top. This patch allows you to manipulate this behaviour with the
`insertEntriesAtEnd` builder method.
### `ImageRenderer` changes
Added a `tick()` method to image renderers that allows to update the image in a regular interval.
## Bug Fixes
- Fixed a bug where image renderers were rendered twice per frame.
- Updated the ImageIO dependency to fix sometimes buggy animated WebP rendering.
- Fixed the name of the list being rendered on every entry of said list.
A PR by [Crendgrim](https://github.com/isXander/YetAnotherConfigLib/pull/89) - thanks a lot!
- Allow to specify size limits for option lists.
- This allows to set a minimum and maximum length for the option list with the `minimumNumberOfEntries`
and `maximumNumberOfEntries` builder methods.
- Allow "reversed" lists that add new options at their end.
- List options until now always grew at the top. This patch allows you to manipulate this behaviour with the
`insertEntriesAtEnd` builder method.
### `ImageRenderer` changes
Added a `tick()` method to image renderers that allows to update the image in a regular interval.
## Bug Fixes
- Fixed a bug where image renderers were rendered twice per frame.
- Updated the ImageIO dependency to fix sometimes buggy animated WebP rendering.
- Fixed the name of the list being rendered on every entry of said list.
- Fix `IntegerFieldController` and `LongFieldController` not allowing negative values.
- Reimplement `ButtonOption` changing the 'EXECUTE' text with `ButtonOption.Builder#text()`
- Fix `IntegerFieldController` and `LongFieldController` not allowing negative values.
- Reimplement `ButtonOption` changing the 'EXECUTE' text with `ButtonOption.Builder#text()`
- Fix IntegerFieldController and LongFieldController not allowing negative values.
- Reimplement ButtonOption changing the 'EXECUTE' text with `ButtonOption.Builder#text()`
- Fix a crash on some loads when viewing list widgets.
- Fix IntegerFieldController and LongFieldController not allowing negative values.
- Reimplement ButtonOption changing the 'EXECUTE' text with `ButtonOption.Builder#text()`
- Fix a crash on some loads when viewing list widgets.
3.0 of YACL introduces a new UI layout, taking advantage of 1.19.4's new tab system!
## Description Panel
The description panel takes the place of the old category buttons, you can now interact with the text by clicking or hovering and the description can contain an animated WebP file or a static image. This can help you as a developer to portray what your option does with an actual example.
Like the old tooltip system, these descriptions can dynamically change based on the value of the option, including the image.
After a few seconds of hovering, the description will start to auto-scroll if necessary so inputs such as controller can still use the UI.
```java
.description(OptionDescription.createBuilder()
.text(Text.literal("Line 1"))
.text(Text.literal("Line 2"))
.webpImage(new Identifier("mymod", "config/screenshots/config_example.webp"))
.build())
```
*the above is applicable to both groups and options*
## Tab System
YACL now uses a slightly modified version of 1.19.4's new create world screen, this adds tab overflow, so you can scroll through the tabs in case there are too many to fit on the screen.
## Controller Builders
Controllers now use a builder system, rather than using constructors. This allows for more flexibility in the future.
You can still use your own controller implementations without creating a builder, using `.customController()`.
## For mod developers...
This update is for both 1.19.4 and 1.20, there is complete API parity. 1.20 is now the active branch,
and 1.19.4 is now considered LTS and may receive features from 1.20 at a later date.
## For users/modpack developers...
YACL 3.0 includes the old 2.x inside the new JAR. So you can safely upgrade to 3.0 without breaking
mods that have not yet updated. However, the old UI will still be present for this outdated mods.
3.0 of YACL introduces a new UI layout, taking advantage of 1.19.4's new tab system!
## Description Panel
The description panel takes the place of the old category buttons, you can now interact with the text by clicking or hovering and the description can contain an animated WebP file or a static image. This can help you as a developer to portray what your option does with an actual example.
Like the old tooltip system, these descriptions can dynamically change based on the value of the option, including the image.
After a few seconds of hovering, the description will start to auto-scroll if necessary so inputs such as controller can still use the UI.
```java
.description(OptionDescription.createBuilder()
.text(Text.literal("Line 1"))
.text(Text.literal("Line 2"))
.webpImage(new Identifier("mymod", "config/screenshots/config_example.webp"))
.build())
```
*the above is applicable to both groups and options*
## Tab System
YACL now uses a slightly modified version of 1.19.4's new create world screen, this adds tab overflow, so you can scroll through the tabs in case there are too many to fit on the screen.
## Controller Builders
Controllers now use a builder system, rather than using constructors. This allows for more flexibility in the future.
You can still use your own controller implementations without creating a builder, using `.customController()`.
## For mod developers...
This update is for both 1.19.4 and 1.20, there is complete API parity. 1.20 is now the active branch,
and 1.19.4 is now considered LTS and may receive features from 1.20 at a later date.
## For users/modpack developers...
YACL 3.0 includes the old 2.x inside the new JAR. So you can safely upgrade to 3.0 without breaking
mods that have not yet updated. However, the old UI will still be present for this outdated mods.
3.0 of YACL introduces a new UI layout, taking advantage of 1.19.4's new tab system!
## Description Panel
The description panel takes the place of the old category buttons, you can now interact with the text by clicking or hovering and the description can contain an animated WebP file or a static image. This can help you as a developer to portray what your option does with an actual example.
Like the old tooltip system, these descriptions can dynamically change based on the value of the option, including the image.
After a few seconds of hovering, the description will start to auto-scroll if necessary so inputs such as controller can still use the UI.
```java
.description(OptionDescription.createBuilder()
.text(Text.literal("Line 1"))
.text(Text.literal("Line 2"))
.webpImage(new Identifier("mymod", "config/screenshots/config_example.webp"))
.build())
```
*the above is applicable to both groups and options*
## Tab System
YACL now uses a slightly modified version of 1.19.4's new create world screen, this adds tab overflow, so you can scroll through the tabs in case there are too many to fit on the screen.
## Controller Builders
Controllers now use a builder system, rather than using constructors. This allows for more flexibility in the future.
You can still use your own controller implementations without creating a builder, using `.customController()`.
## For mod developers...
This update is for both 1.19.4 and 1.20, there is complete API parity. 1.20 is now the active branch,
and 1.19.4 is now considered LTS and may receive features from 1.20 at a later date.
## For users/modpack developers...
YACL 3.0 includes the old 2.x inside the new JAR. So you can safely upgrade to 3.0 without breaking
mods that have not yet updated. However, the old UI will still be present for this outdated mods.
This version adds no features, nor bug fixes, instead it implements a breaking change:
**The YACL package has changed** to `dev.isxander.yacl3` and **the YACL mod-id has changed** to `yet_another_config_lib_v3`.
This is to prevent conflicts with 2.0, so you can load both versions at the same time so older mods don't break.
This version adds no features, nor bug fixes, instead it implements a breaking change:
**The YACL package has changed** to `dev.isxander.yacl3` and **the YACL mod-id has changed** to `yet_another_config_lib_v3`.
This is to prevent conflicts with 2.0, so you can load both versions at the same time so older mods don't break.
This version adds no features, nor bug fixes, instead it implements a breaking change:
**The YACL package has changed** to `dev.isxander.yacl3` and **the YACL mod-id has changed** to `yet_another_config_lib_v3`.
This is to prevent conflicts with 2.0, so you can load both versions at the same time so older mods don't break.
This release is parity with 3.0.0-beta.6 for 1.20.
Unfortunately, 3.0 will only be available for 1.19.4 and up, not 1.19.2. This is because YACL
now highly depends on .4's new tab system (found in the create new world screen).
If there is a high enough demand for a backport to 1.19.2, I will consider it, but no promises!
This release is parity with 3.0.0-beta.6 for 1.20.
Unfortunately, 3.0 will only be available for 1.19.4 and up, not 1.19.2. This is because YACL
now highly depends on .4's new tab system (found in the create new world screen).
If there is a high enough demand for a backport to 1.19.2, I will consider it, but no promises!
- `OptionDescription.Builder#description` has been renamed to `text`, to make it more clear as it used to look like:
```java
.description(OptionDescription.createBuilder()
.description(Component.literal("This is some text"))
.build())
```
- `ListOption.createBuilder` now no longer takes a class parameter, to match with `Option`. This means you can no longer
do `ListOption.createBuilder(String.class)`, instead you should do `ListOption.<String>createBuilder()`.
## Bug Fixes
- Fixed option list entries sometimes appearing on top of the navbar.
- Added `OptionDescription.Builder.customImage()` to add your own renderer for the option description.
## API Changes
This release brings a few API breakages, getting them out the way, as it is a major update.
- All controllers now have an API builder for creating them. This is to make it easier to add
more options to them in the future. This also creates a new API layer to remove simple implementations of YACL
from using the GUI package. The old constructors are still available and you can pass your own controller
with `.customController()`. An example would be `.controller(TickBoxControllerBuilder::create)` or:
```java
.controller(opt -> IntegerSliderControllerBuilder.create(opt)
.range(0, 10)
.step(1))
```
- Completely removed `.tooltip()` from groups and options. You should use `.description()` instead.
To make this a little easier, `OptionDescription.of(Component...)` has been added so you don't need to
create a builder.
- Removed `OptionDescription.Builder.name(Component)` as it now just uses the option name.
## Bug Fixes
- Fixed option descriptions being stuck on the last clicked option when not hovering.
- Fixed category tooltips not being displayed with the new tabs.
- `OptionGroup.Builder` and `ConfigCategory.Builder` now extend `OptionAddable` so you can abstractly
add options to either of them.
## API Changes
- Deprecated the varargs tooltip builder method in `Option.Builder` due to unsafe varargs. There is now
an equivalent that is not varargs but a single function.
- New builder API for `GsonConfigInstance`, deprecated the constructors.
## Bug Fixes
- Fixed `StringController`s not focusing properly since 2.3.1 ([#58](https://github.com/isXander/YetAnotherConfigLib/issues/58)).
- Fixed resetting a `StringController` sometimes crashing the game ([#57](https://github.com/isXander/YetAnotherConfigLib/issues/57)).
- Fix `ListOption.Builder` not exposing `listener()` like in `Option.Builder` ([#55](https://github.com/isXander/YetAnotherConfigLib/issues/55)).
Due to breaking JAR compatibility in an earlier version of YACL, mods that support YACL for
1.19.3 can no longer support 1.19.2. This is a backport of YACL 2.2.0 to 1.19.2 to allow mods to
support it.
### My stance on backporting
Personally, I hate to backport my mods. When breaking changes are made in Minecraft between versions,
the code of the mod has to be changed to support the new version, making the older version of MC incompatible.
If you want to support multiple versions of Minecraft, you have to maintain multiple branches of the mod, which
is a lot of work for just one person, and I don't have the time to do that.
This is a one-off backport, and I will not be backporting any future versions of YACL to 1.19.2. If you want to
support and use new features of YACL in your mod, you will have to drop support for 1.19.2.
- New `List is empty` text when lists are empty
- Fix category buttons sometimes not being clickable when you can scroll
- Fix the list add button not disabling when lists are disabled
- Fix the option list background not quite reaching the edge of the screen.
## Developer Changes
- New `LabelOption` for shorthand to making labels!
- Log when option bindings don't match up after using their save function
- Internally move YACLScreen button actions into separate methods for future features :o
- Fully publish sources jar & javadoc jar now that the loom plugin is fixed.
- Remove padding between list items
- No longer hide add and reset buttons when lists are collapsed, but automatically expand them when clicked
- Fix removing items from lists didn't update up and down buttons
- Fix lists not updating properly when removing the final item from a list
- Refactor some gui list code to abstract all list functionality from main gui classes
- Fix option entries sometimes overlapping due to the reset button
- Fix string elements cropping 1px off the top of the text
- Abstracted builders to restrict API usage
Implements mutable list options where you can create, remove and shift entries in a list.
### API
Lists hack option groups with their own implementation for this, so each individual list takes form as a whole option group.
```java
ListOption.createBuilder(String.class)
.name(Text.of("List Option"))
.binding(/* gets and sets a List, requires list field to be not final, does not manipulate the list */)
.controller(StringController::new) // usual controllers, passed to every entry
.initial("") // when adding a new entry to the list, this is the initial value it has
.build()
```
### Implementation details
When implementing this, it was vital to me that _all_ controllers work with lists, not ones specifically designed
for list entries. This was achieved quite easily by having each entry being its own option with an empty name and tooltip with its own controller, that pairs with its list "parent" to actually modify the option.
Option groups were taken advantage of and hacked into its own option, only minor changes had to be made to get this
to work with value application.
Applicable controllers have been modified to expand their inputs to near full width when no name is present.
- Allow `StringControllerElement` to have unlimited text length
- When pressing `Delete` in a text field whilst text is highlighted,
it will act like `Backspace` like it should.
- Update to 1.19.3
- Colour field controllers
- Better carot positioning when clicking in text fields
- Better text selection for text fields
- Smooth scrolling for category list
- Fix category list scrollbar appearing under option list background in-game
- Fix tick box name text length limiting
- Smooth category scrolling
- Individual reset buttons for every option
- Fix bug where option lists that *just* went over into scrolling scrolled extremely slow.
## Developer API changes
- Actual Config API to save and load fields in a class automatically [(documentation)](https://github.com/isXander/YetAnotherConfigLib/wiki/config-api)
- Separate `Dimension` into `Dimension` and `MutableDimension`
- Make `dim` private in `AbstractWidget` so mods can't change the dimension without `setDimension`
- New Option API method `isPendingValueDefault` to check if pending value is equal to default value of binding
- Fix `Option#requestSetDefault` and `Option#forgetPendingValue` implementations weren't notifying listeners
- Make controller names go italic when there are pending changes
- Allow `availableValues` to be passed to `EnumController`
- More validation for slider controllers
- Improve tooltips a lot:
- They now never get cut off by the edge of the screen
- They never overlap the hovered option/group/category
- They don't take half a second to appear
- They don't disappear when you move your mouse
- `ButtonOption` now consumes itself, so you can access it when building.
- Make `Option#available` mutable with `Option#setAvailable`
- Option tooltips now have access to the pending value to dynamically change
- `PlaceholderCategory`: A category that when selected, just opens a screen
- `instant` property for option builders: makes the option apply instantly instead of when pressing "Apply"
- Categories can now be scrolled when overflowing
- Available property for options, so you can disable certain options in some conditions
- Fix all first tooltip line having a larger line height
- Improved search - Now searches every category rather than the currently selected one
- Option Flags - Add flags to options that when changed, the flag is executed once per the whole config.
- Deprecated "Require Restart" in favour of option flags.
- Fix search field overlapping undo and cancel at some GUI scales
- Fix scrollbar appearing in the wrong place at some GUI scales
- Fix option entries not extending to fill the list's width at some GUI scales
- Fix tooltips rendering below the scrollbar