-
Notifications
You must be signed in to change notification settings - Fork 1
YACL UI
Configurable comes with a YACL UI generator built-in. This generator is entirely optional both at compile time and runtime.
If YACL is not present at compile time, the YACL UI generator will not be generated and the ModMenu / NeoForge Config UI hooks will not be initialised.
- If it is present at compile time and a ModMenu implementation is already present, Configurable will not overwrite it.
If YACL is not present at runtime, the config UI will open a prompt for the user to install YACL to view and edit the config in-game.
All YACL elements will default to having translatable names with keys along the lines of
configurable.modid.yacl.<section>.<value>
YACL option groups and options are determined by the structure of your @Configurable elements
@Configurable("your_class")
public class YourClass {
@Configurable("your_field")
public static boolean yourField;
}will create the option group your_class that contains the option your_field.
Since YACL doesn't support nested option groups, parents are dissolved and their children are placed at the top-level.
@Configurable("your_class")
public class YourClass {
@Configurable("your_field")
public static boolean yourField;
@Configurable("your_other_class")
public class YourOtherClass {
@Configurable("your_other_field")
public static int yourOtherField;
}
}will create the option your_field and the option group your_other_class that contains the option your_other_field
The category of an option / option-group is determined by its package:
package com.your.project;
@Configurable("your_class")
public class YourClass {
@Configurable("your_field")
public static boolean yourField;
}will be placed in the project category.
This can be overwritten by specifying the category:
package com.your.project;
@Configurable(value = "your_class", yacl = @Yacl(category = "your_category"))
public class YourClass {
@Configurable("your_field")
public static boolean yourField;
}category is transitive
By setting @Yacl#exclude to true, the annotated element will not be included in the generated UI.
exclude is transitive
By setting @Yacl#collapsed to true on an option group, it will be collapsed by default.
The option controller by default is determined by the field type. It can be set to any type, however, mismatching types will cause compilation errors.
Booleans default to using the tick box controller, however, this can be set to the boolean controller that simply
toggles between "true" and "false":
public class YourClass {
@Configurable(value = "your_field", controller = ControllerType.BOOL)
public static boolean yourField;
}@Yacl#type allows you to specify multiple OptionTypes for how the game should behave when the option is changed.
Valid types are:
OptionType.GAME_RESTART; OptionType.RELOAD_CHUNKS; OptionType.WORLD_RENDER_UPDATE; OptionType.ASSET_RELOAD;
type is transitive
@Yacl#descriptioner expects the name of a method that will be used to determine the text description of an option
or option group.
For example to have the description be dependent on the current value:
public class YourClass {
@Configurable(value = "your_field", yacl = @Yacl(descriptioner = "yourDescription"))
public static boolean yourField;
public static Text yourDescription(boolean value) {
return Text.translatable("some.key.%s".formatted(value));
}
}When supplied to an option group, the expected method will have no parameters:
@Configurable(value = "your_class", yacl = @Yacl(descriptioner = "yourDescription"))
public class YourClass {
@Configurable("your_field")
public static boolean yourField;
public static Text yourDescription() {
return Text.translatable("some.key");
}
}@Yacl#formatter expects the name of a method that will be used to determine the displayed value of the controller
for an option.
For example to make the above controller use a "ON"/"OFF" formatter:
public class YourClass {
@Configurable(value = "your_field", controller = ControllerType.BOOL, formatter = "onOffFormatter")
public static boolean yourField;
public static Text onOffFormatter(boolean value) {
return value ? ScreenTexts.ON : ScreenTexts.OFF;
}
}Some controllers do not accept a value formatter, such as the tick box controller, the formatter argument will be ignored in these cases.
@Yacl#listeners expects the names of one or more method to listen to changes to the value of the annotated option
within the config UI.
For example to print the current value to the console:
public class YourClass {
@Configurable(value = "your_field", yacl = @Yacl(listener = "yourListener"))
public static boolean yourField;
public static void yourListener(boolean value) {
LOGGER.info("your_field set to {}", value);
}
}@Yacl#image allows you to specify the image that should be rendered in the option or option group description.
The @Image annotation controls where the image should come from and how it should appear.
A basic example would be a 16x16 texture:
public class YourClass {
@Configurable(value = "your_field", yacl = @Yacl(image = @Image("minecraft:textures/item/gold_ingot.png")))
public static boolean yourField;
}This also allows you to use webp images:
public class YourClass {
@Configurable(value = "your_field", yacl = @Yacl(image = @Image(type = ImageType.WEBP, value = "modid:textures/your_image.webp")))
public static boolean yourField;
}Or use a custom image renderer.
See Method Based Options
public class YourClass {
@Configurable(value = "your_field", yacl = @Yacl(image = @Image(type = ImageType.WEBP, custom = "yourImageRenderer")))
public static boolean yourField;
public static ImageRenderer yourImageRenderer() {
return new ImageRenderer() {
@Override
public int render(DrawContext context, int x, int y, int renderWidth, float delta) {
float ratio = renderWidth / 16f;
int targetHeight = (int) (16f * ratio);
context.getMatrices().push();
context.getMatrices().translate(x, y, 0);
context.getMatrices().scale(ratio, ratio, 1);
context.drawItem(Items.ENCHANTED_GOLDEN_APPLE.getDefaultStack(), 0, 0);
context.getMatrices().pop();
return targetHeight;
}
@Override
public void close() {
}
};
}
}image is transitive. To remove an inherited image you can do the following:
@Configurable(value = "your_class", yacl = @Yacl(image = @Image("minecraft:textures/item/gold_ingot.png")))
public class YourClass {
@Configurable(value = "your_field", yacl = @Yacl(image = @Image))
public static boolean yourField;
}