-
Notifications
You must be signed in to change notification settings - Fork 5
Validation
One of Fzzy Configs most powerful features is the validation system that is applied to every setting either implicitly or explicitly by the creator.
Every setting is tightly controlled and fail-soft; no need to worry about catastrophic failure of a mod system if the config changes and the old file isn't valid. No need to worry if a user modifies one of the .toml directly.
Every read, write, and update is checked for errors and problems are either automatically corrected or shunted to the default value.
Below is a (potentially non-exhaustive) list of types that Fzzy Config has validation tools for.
- Integer
- Long
- Short
- Byte
- Double
- Float
- Boolean
- Lists
- Sets
- Maps
- Enums
- Mathematical Expression
- Color
- Identifier
- TagKey
- Ingredient
- Arbitrary Objects
"Validation" is a bit of a misnomer, as the toolset does much more than that. It's a label of convenience stemming from the base class ValidatedField
. Validation tools provide a set of tools to handle settings in various ways. To borrow from the KDoc for Entry
, validation tools do the following:
- serialize contents
- deserialize input
- validate updates
- correct errors
- provide widgets
- apply inputs
- supply outputs
- create instances
Every setting that appears in a Config GUI is backed in some way by validation. Even when you don't explicitly provide it, Fzzy Config will wrap supported types with basic validation in the background.
- If you try to add a setting of an unsupported type, you will need to create custom validation for it, or it will not appear in config GUIs
For more specific control of your settings, in the vein of Minecraft GameOption
, define the validation for your setting. This grants you the ability to:
- Provide input restrictions
- Suggest inputs to users
- In some places define the widget used in-game
All primitive number types have validation tools. Validation:
- Controls the number type: bytes stay bytes etc.
- Define a minimum allowable value
- Define a maximum value
Number validation can be defined by using one of the six subclasses of ValidatedNumber
. By default the allowable min and max will be the entire range of the type (Integer.MIN_VALUE to Integer.MAX_VALUE, for example)
//kotlin
var myValidatedFloat = ValidatedFloat(0.5f,1f,0f) // default value, max value, min value
//java
public ValidatedFloat myValidatedFloat = new ValidatedFloat(0.5f,1f,0f); // default value, max value, min value
Validated Numbers each have their own partnered Annotation you can use to annotate an otherwise plain field with.
// kotlin
@ValidatedFloat.Restrict(0f,1f)
var myValidatedFloat = 0.5f
// java
@ValidatedFloat.Restrict(min = 0f, max = 1f)
public float myValidatedFloat = 0.5f
Fzzy Config has shorthand contructors for validated numbers. These are generally used to provide Validators for other validation constructors, like Lists or Maps, where you need a ValidatedNumber but may not have any actual need for restrictions.
// kotlin
var myValidatedFloat = ValidatedFloat()
//java
public ValidatedFloat myValidatedFloat = new ValidatedFloat();
Booleans are very simple things. In general, you never need to define validation for booleans except when needed for use in other validation.
// kotlin
var myValidatedBoolean = ValidatedBoolean()
//java
public ValidatedBoolean myValidatedBoolean = new ValidatedBoolean();
Fzzy Config has validation tools for lists, maps, and sets. Each of these constructs has builders and other intricacies that are best digested thoroughly by visiting the documentation:
NOTE: Validated collections implement their respective collection type (list, set, map), so can be used directly as such instead of having to .get()
the wrapped map value.
Any ValidatedField
can be converted into a list implementation with it as backing validation using the toList()
method
//kotlin
//wraps the vararg valued provided with a blank validated field (identifiers in this case). validation with actual bounds and logic can of course be used too
val listFromField = ValidatedIdentifier().toList(Identifier("stick"), Identifier("blaze_rod"))
//java
//wraps the vararg valued provided with a blank validated field (identifiers in this case). validation with actual bounds and logic can of course be used too
public ValidatedList<Identifier> listFromField = new ValidatedIdentifier().toList(new Identifier("stick"), new Identifier("blaze_rod"));
ValidatedList and Set have a series of static methods that can be used to initialize a variety of collections of given common types, much in the same vein as the java List.of()
or kotlin listOf()
.
// kotlin
var validatedIntList = ValidatedList.ofInt(1,2,5,10)
var validatedIntSet = ValidatedSet.ofInt(1,2,5,10)
// java
public ValidatedList<Integer> validatedIntList = ValidatedList.ofInt(1,2,5,10);
public ValidatedSet<Integer> validatedIntSet = ValidatedSet.ofInt(1,2,5,10);
Any enum included in a Config is automatically validated, but much like booleans making ValidatedEnums may be useful for constructing other valdiation types.
// kotlin
enum class MyEnum{
A,
B,
C
}
var validatedEnum = ValidatedEnum(MyEnum.A)
var validatedEnumExtension = MyEnum.A.validated() // kotlin extension function for validating an enum automatically
// java
public enum MyEnum{
A,
B,
C
}
public ValidatedEnum<MyEnum> validatedEnum = new ValidatedEnum(MyEnum.A);
Enums can implement a special interface EnumTranslatable
. See Translation for details.
Fzzy Config has a built-in math engine called Expression
. See the Expressions article for more details.
Fzzy Config has a built-in Color system with full validation support and conversion to and from RGB, RGB integers, hex strings, and more. See the Colors article for more details.
ValidatedIdentifier
is one of the more powerful validation tools at the Fzzy Config modders disposal. ValidatedIdentifier
can provide:
- Suggestions for allowable identifiers
- Restrictions based on tags, registries, or pre-defined lists
- ValidatedIdentifier implements most methods that Identifier itself does.
For more details, check out the related documentation:
FzzyConfig can automatically validate TagKeys from any registry. Validated Tags also provide suggestions to the user.
// kotlin
// Validated tags accept a predicate that can be used to filter a tag further.
var validatedTag = ValidatedTagKey(ItemTags.AXES, {id -> id.namespace == "minecraft})
var shortHandTag = ItemTags.AXES.validated() // kotlin extension function for quick validation
// java
// Validated tags accept a predicate that can be used to filter a tag further.
public ValidatedTagKey<Item> validatedTag = ValidatedTagKey(ItemTags.AXES, {id -> id != Identifier("netherite_axe")})
Minecraft ingredients can be validated, with restrictions placed on the three ways you can construct Ingredients (single item, item list, item tag)
ValidatedIngredients are constructed from one of three constructors based on the type of ingredient desired as default
// kotlin
// A validated Ingredient for a single item
val validatedIngredientItem = ValidatedIngredient(Identifier("oak_log"))
// A validated ingredient accepting a set of items
val validatedIngredientList = ValidatedIngredient(setOf(Identifier("oak_log"),Identifier("dark_oak_log")))
// A validated ingredient utilizing a tag
val validatedIngredientTag = ValidatedIngredient(ItemTags.LOGS_THAT_BURN)
//get the ingredient from the holder for use in Materials etc
val validatedIngredientIngredient: Ingredient = validatedIngredientItem.toIngredient()
//java
// A validated Ingredient for a single item
public ValidatedIngredient validatedIngredientItem = new ValidatedIngredient(new Identifier("oak_log"));
// A validated ingredient accepting a set of items
public ValidatedIngredient validatedIngredientList = new ValidatedIngredient(Set.of(new Identifier("oak_log"),new Identifier("dark_oak_log")));
// A validated ingredient utilizing a tag
public ValidatedIngredient validatedIngredientTag = new ValidatedIngredient(ItemTags.LOGS_THAT_BURN);
//get the ingredient from the holder for use in Materials etc
public Ingredient validatedIngredientIngredient = validatedIngredientItem.toIngredient()
ValidatedIngredient
is not an ingredient itself, and does not hold ingredients. It lazily creates ingredients only when needed. This prevents an ingredient from being created before the source for the ingredient is ready (before a tag is populated, for example). As seen in the code examples above, call toIngredient()
to have the validation supply an ingredient.
Arbitrary POJO/POKO can be validated. Fzzy Config will automatically wrap any object that implements Walkable
, or you can construct validation manually with ValidatedAny
. The validation constructs a "mini-config" around the object; any validation or validatable fields included within the object will be validated just like a proper config.
See examples of ValidatedAny at Laying out Configs