Skip to content
API State: Draft

Unfinished

This part of the API is brand-new. It will be changed if there are any bugs, missing features or usability improvements. This part of the API might receive breaking changes within a minor version.

It is not recommended relying on this part of the API, it will most likely change.

Draft

Our own usage and testing has shown that this part of the API is complete and seems bug free. However, other plugins may have other use cases which are not covered by our testing. Therefore, please go ahead and use this API part. Let us know if there are missing features or bugs. This API part will be changed if there are more bugs, missing features or usability improvements. We will try to keep it compatible with previous versions if changes are needed. This part of the API won't receive breaking changes within a minor version.

Please use this part of the API and give us feedback!

Stable

Both our own and third party testing showed that this part of the API is complete. Only bugs and major conceptual problems would lead to more changes. This part of the API will only change over at least one major version and will likely carry deprecation as long as possible.

This part of the API should be safe to use. We try to keep it compatible with previous versions if changes are needed.

Function API Classes
  • org.betonquest.betonquest.api.service.function.Functions
  • org.betonquest.betonquest.api.function.FunctionProvider
  • org.betonquest.betonquest.api.identifier.FunctionIdentifier
  • org.betonquest.betonquest.api.function.MathFunction
  • org.betonquest.betonquest.api.function.FunctionDefinition
  • org.betonquest.betonquest.api.function.FunctionExpression
  • org.betonquest.betonquest.api.function.FunctionAssignment
  • org.betonquest.betonquest.lib.function.FunctionParser
  • org.betonquest.betonquest.lib.function.token.FunctionTokenizer

Functions Overview🔗

This page covers the functions API and the underlying concepts.

Function Basics

See Functions for more information about how functions work in the script.

Introduction🔗

Functions solve a problem that is not common in BetonQuest's scripting language, but not having them is a huge pain in specific situations. They combine logic with math and are a powerful tool for creating complex behaviors that otherwise would be very verbose with just actions and conditions or completely impossible in the first place.

Accessing Functions🔗

Functions are accessed through the Functions interface. It allows you to find and evaluate functions.

public void myFunction(final Functions functions, final FunctionIdentifier identifier) throws QuestException {
    final MathFunction mathFunction = functions.getFunction(identifier); //(1)!
    final FunctionProvider functionProvider = functions.getFunctionProvider(identifier.getPackage()); //(2)!
    final FunctionAssignment result = mathFunction.evaluate(functionProvider, List.of(new NumberSourceAssignment(10)); //(3)!
    final Number value = result.asNumber(); //(4)!
}

  1. getFunction returns a MathFunction object that can be used to evaluate the function. This may throw a QuestException if the function is not found.
  2. getFunctionProvider returns a FunctionProvider object that can be used to resolve relative function identifiers to MathFunction objects.
  3. evaluate takes a list of FunctionAssignment objects that are used to evaluate the function. Functions can be evaluated with any number of arguments, but the required number of arguments is defined by the function definition. Missing arguments might result in an error, too many arguments might be just ignored and have no effect.
  4. Functions produce their result as FunctionAssignments that can be passed to other functions or resolved to java values. asNumber (as an example) returns the result of the function as a Number object.

You can also skip the getFunction step and use the evaluate method directly.

public void myFunction(final Functions functions, final FunctionIdentifier identifier) throws QuestException {
    final FunctionAssignment result = functions
        .evaluate(identifier, List.of(new NumberSourceAssignment(10))); //(1)!
    final Number value = result.asNumber();
}
  1. evaluate is essentially a shortcut for getFunction(identifier).evaluate(functions, arguments) if you don't need to access the MathFunction object itself.

Registering Subroutines🔗

Subroutines are functions that can be called within other functions. They are registered with the Functions interface before functions can use them.

Availablity

Subroutines are only available once registered. If you define functions in the script that use subroutines, they will cause an error when evaluated without the subroutine being registered beforehand. Since subroutines are not checked at parse-time, they may be registered after the script has been loaded.

public void myFunction(final Functions functions, final MathFunction subroutine) {
    functions.registerSubroutine("foo", subroutine);
}

Parsing Functions🔗

Functions are parsed from String by the FunctionTokenizer and FunctionParser classes. They are currently not exposed to the API and only available in the library.

public MathFunction parseFunction(final String functionAsString) throws QuestException {
    final FunctionTokenizer tokenizer = new FunctionTokenizer(); //(1)!
    final FunctionParser parser = new FunctionParser(); //(2)!
    final List<FunctionToken> tokens = tokenizer.tokenize(functionAsString); //(3)!
    return parser.parse(tokens); //(4)!
}
  1. FunctionTokenizer is used to tokenize the function string into a list of FunctionTokens.
  2. FunctionParser is used to parse the list of FunctionTokens into a MathFunction.
  3. Invalid strings will cause a QuestException to be thrown.
  4. Invalid tokens will cause a QuestException to be thrown.