Mixin Library
The following functions are provided to scripts via the mixin global.
DANGER
Mixins are a very complicated topic that's very hard to grasp without a decent understanding of the JVM. If you would like to learn more about them, check out:
DOUBLE DANGER
Due to a limitation in how mixins are applied, if another mod chooses to apply mixins during the preLaunch phase, all Allium script mixins will NOT apply. If a script mixin appears to not be applying properly, this might be why.
WARNING
This page is under construction
Functions
mixin.to(targetClass, interfaces, targetEnvironment, duck)
Mix into a specified class.
Parameters
targetClass-string: The target class name, like what would be passed torequire().interfaces-table<string>?: Optional interfaces to apply to the target class, using therequire()format.targetEnvironment-string?: The target environment, one of"client"or"server". Leavenilto apply to common code.duck-boolean?: Whether to make this mixin a duck interface.
WARNING
Unlike standard class building, class names are passed as strings. This is because:
- mixins must not load the class they're mixing into, otherwise the application of the mixin will fail.
- mixins are registered before the game properly launches (
mixinAllium entrypoint,preLaunchFabric entrypoint). In this pre-launch environment it is best practice to not load any game classes.
Returns
userdata [instance]- A mixin class builder.
Usage
See Class Building - Mixin Class Builder
mixin.get(hookId)
Get a reference to a mixin injection with the given hookId. This function can (and should) be used in static and dynamic script entrypoints.
Parameters
hookId-string: The hook ID of the injector created in themixinentrypoint.
Returns
userdata [instance]: The injector's method hook. See Method Hook
Usage
Assuming there exists an injection with the ID "increase_cactus_height":
local methodHook = mixin.get("increase_cactus_height")mixin.quack(mixinId)
Provides the duck interface associated to a given ID. Used to access the accessors and invokers on objects belonging to the duck interface's target class.
Parameters
mixinId-string: The ID of a duck interface mixin.
Returns
userdata [class]: The mixin interface.
Usage
Provided the class:
package com.example;
import java.lang.String;
public class Dummy {
private final String foobar;
public Dummy(String foobar) {
this.foobar = foobar + (int)(Math.random()*100);
}
private void bat(boolean baz) {
// ...
}
}and the following mixin to access the private field foobar:
local builder = mixin.to("com.example.Dummy")
builder:getAccessor({ "foobar" })
builder:invoker({ "bat(Z)V" })
builder:build("foobar_interface")we use mixin.quack() to access the duck interface:
local Dummy = require("com.example.Dummy")
local AccessExample = mixin.quack("foobar_interface")
local dummy = Dummy("asd")
local accessibleDummy = java.cast(dummy, AccessExample)
local foobar = accessibleDummy:getFoobar()
accessibleDummy:invokeBat(false)Annotation Tables
Annotation tables are used heavily in both annotation functions and sugar functions. Annotation tables are tables that gets recursively parsed and applied to the annotation interface that the function represents. The method names become keys, and the return values become the value. Arrays are a standard table with number indices.
There is a special exception to the method name value, where if it's the only key-value pair being provided, the key name can be omitted. A common example of this is the mixin @At annotation. Both:
{ value = "HEAD" }and:
{ "HEAD" }are valid ways to define an @At annotation.
Annotations
The following functions are provided on the annotation index of the mixin global.
Most of these functions represent injector annotations. Only one injector annotation can be provided per-method. The exceptions to this are expression() and definition(), which can be provided more than once per method.
mixin.annotation.inject(annotation)
Creates an @Inject annotation.
For more information see:
- Mixin Wiki - Advanced Mixin Usage - Callback Injectors
- Mixin Cheatsheet -
@Inject - Mixin Cheatsheet -
@Inject, cancellable
Parameters
annotation-table: An annotation table that matches the@Injectannotation.
Returns
userdata [instance]: A reference to the annotation for use in mixin method building.
mixin.annotation.modifyArg(annotation, targetType)
Creates a @ModifyArg annotation.
For more information see Mixin Cheatsheet - @ModifyArg.
Parameters
annotation-table: An annotation table that matches the@ModifyArgannotation.targetType-string: A type descriptor string of the argument being modified.
Returns
userdata [instance]: A reference to the annotation for use in mixin method building.
mixin.annotation.modifyArgs(annotation)
Creates a @ModifyArgs annotation.
For more information see Mixin Cheatsheet - @ModifyArgs.
Parameters
annotation-table: An annotation table that matches the@ModifyArgsannotation.
Returns
userdata [instance]: A reference to the annotation for use in mixin method building.
mixin.annotation.modifyExpressionValue(annotation, targetType)
Creates a @ModifyExpressionValue annotation.
For more information see MixinExtras - ModifyExpressionValue
Parameters
annotation-table: An annotation table that matches the@ModifyExpressionValueannotation.targetType-string: A type descriptor string of the argument being modified.
Returns
userdata [instance]: A reference to the annotation for use in mixin method building.
mixin.annotation.modifyReturnValue(annotation)
Creates a @ModifyReturnValue annotation.
For more information see MixinExtras - ModifyReturnValue
Parameters
annotation-table: An annotation table that matches the@ModifyReturnValueannotation.
Returns
userdata [instance]: A reference to the annotation for use in mixin method building.
mixin.annotation.wrapMethod(annotation)
Creates a @WrapMethod annotation.
For more information see MixinExtras - WrapMethod
Parameters
annotation-table: An annotation table that matches the@WrapMethodannotation.
Returns
userdata [instance]: A reference to the annotation for use in mixin method building.
mixin.annotation.custom(annotation, annotationType, methodDescriptor, parameterTypes, returnType)
Creates a custom injector annotation.
Parameters
annotation-table: An annotation table that matches the givenannotationType.annotationType-userdata [class]: The annotation class to be used.methodDescriptor-string: The target method's descriptor string.parameterTypes-table<string>: The parameters of the injector method. These may differ from the target method's descriptor.returnType-string: The return type of the injector method. This may differ from the target method's dscriptor.
Returns
userdata [instance]: A reference to the annotation for use in mixin method building.
mixin.annotation.expression(annotation)
Creates an @Expression annotation. This method does not produce an injector annotation and may be used multiple times within an inject method.
For more information see MixinExtras - Expressions
Parameters
annotation-table: An annotation table that matches the@Expressionannotation.
Returns
userdata [instance]: A reference to the annotation for use in mixin method building.
mixin.annotation.definition(annotation)
Creates a @Definition annotation. This method does not produce an injector annotation and may be used multiple times within an inject method.
For more information see MixinExtras - Expressions
Parameters
annotation-table: An annotation table that matches the@Definitionannotation.
Returns
userdata [instance]: A reference to the annotation for use in mixin method building.
Sugars
The following functions are provided on the sugar index of the mixin global.
Sugars are annotations that are applied to additional parameters that are applied to the end of the injector method's parameter list.
mixin.sugar.localref(type, annotation, mutable)
Creates a parameter with a @Local annotation.
See MixinExtras Wiki - Local for more information.
Parameters
type-string: A type descriptor string of the parameter.annotation-table?: An optional annotation table that matches the@Localannotation.mutable-boolean?: Whether this parameter should be mutable.
WARNING
Setting mutable to true changes the parameter's type from the one passed in type to one from the LocalRef family.
Returns
userdata [instance]: A reference to the parameter and annotation for use in mixin method building.
mixin.sugar.share(type, annotation)
Creates a parameter with a @Share annotation.
See MixinExtras Wiki - Share for more information.
Parameters
type-string: A type descriptor string of the parameter.annotation-table?: An optional annotation table that matches the@Shareannotation.
Returns
userdata [instance]: A reference to the parameter and annotation for use in mixin method building.
mixin.sugar.cancellable()
Creates a parameter with a @Cancellable annotation.
See MixinExtras Wiki - Cancellable for more information.
Returns
userdata [instance]: A reference to the parameter and annotation for use in mixin method building.
Method Hook
Because of the restrictions of the mixin entrypoint, the Lua function that is to be put into the injector has to be hooked in from the static or dynamic entrypoints. The method hook is how this is done. It has a single function:
methodHook:hook(func)
Hooks the given function into the given mixin injection.
Parameters
func-function: The function to be run when the injector gets invoked. Parameters passed into this function depend on the injector. If the injection does not target a static method, the first parameter passed to the function isthis, followed by the remaining parameters specified by the injection annotation.
TIP
It can be hard to visualize where a mixin should be made and what parameters it will provide. Scaffolding out the mixin in java first, where linting and auto-fill can help guide to the correct results, is a good idea.
HELP WANTED
It would be nice to be able to auto-fill in the parameters using the mixin annotation information right in the Lua file itself. If you have extension development experience in any IDE, and have an interest in contributing to an IDE extension for Allium, join the Discord linked in the top right!
Usage
TODO: A better example
methodHook:hook(function(this, ...)
-- your code
end)