mixson

Annotation Registration

Mixson provides an annotation processor to allow users to create clean, easy to maintain events. Classes that utilize the APT are not strictly required to contain only Mixson methods. This means classes, such as an entrypoint for Fabric/Quilt, could be processed.

Adding Classes to the Processor

The exact details of implementation vary depending on the mod loader.

{
...
"custom": {
"mixson": [
"path.to.the.Class"
]
}
...
}

Registering an Event

To register an event, annotation a method that takes in a single EventContext parameter with no return with @MixsonEvent.

The definition of @MixsonEvent is as follows:

public @interface MixsonEvent {
String[] value();
String eventId() default "";
int priority() default Mixson.DEFAULT_PRIORITY;
boolean failSilently() default false;
int ordinal() default -1;
...
}

the value is equivalent to resourceId. The annotation can take in several resources to be applied to the same event. These values support wildcard modifiers.

the eventId is not by default required. If an eventId is not provided, the processor will use the method name as the identifier. The identifier is mapped as follows: $ -> : X -> _x _ -> /.

For example, the method named modid$model_item_ironBlock will generate the identifier modid:model/item/iron_block.

Event Example

The following event will change the texture of the iron block to that of the coal block:

@MixsonEvent("models/block/iron_block")
private static void modid$changeIronBlockModel(EventContext context) {
JsonElement elem = context.getFile();
JsonObject object = elem.getAsJsonObject();
object.getAsJsonObject("textures").addProperty("all", "minecraft:block/coal_block");
}

Using References

To add references, parameters proceeding the EventContext should be of type BuiltResourceReference and annotated with @Reference.

The definition of @Reference is as follows:

public @interface Reference {
String value();
int priority() default Mixson.DEFAULT_PRIORITY;
String referenceId() default "";
}

The value is equivalent to resourceId.

The referenceId can be left blank and be autogenerated just as eventId can.

Referencing Example

@MixsonEvent("models/block/iron_block")
private static void modid$changeIronBlockModel(EventContext context, @Reference("models/block/coal_block") BuiltResourceReference modid$coalBlockReference) {
JsonElement elem = context.getFile();
Optional<JsonElement> maybeCoalBlock = modid$coalBlockReference.retrieve();
if(maybeCoalBlock.isEmpty()) return;
String textureFile = maybeCoalBlock.get().getAsJsonObject().getAsJsonObject("textures").get("all");
JsonObject object = elem.getAsJsonObject();
object.getAsJsonObject("textures").addProperty("all", textureFile);
}

The Generator

Sometimes, the resources that are going to be modified may not be known until runtime. To allow resourceIds and eventIds to be generated at runtime, events leverage the generative system. In this system, events call methods marked with the @Generator annotation to load what resources they are to be assigned to.

The @Generator method is to be applied to a method that takes a single parameter of type GeneratorContext and return type void.

GeneratorContext has a single method for the user to use:

public void addFile(String resourceId, String eventName);

The GeneratorContext#addFile method is used to add files to the context to be added to the generative event.

The @Generator annotation is declared as follows:

public @interface Generator {
String value();
}

the value acts as an identifier for the generator to be referenced with by events.

Generator Example

This generator will add two resources to be modified:

@Generator("modid:generator_id")
private static void generatorOne(GeneratorContext context) {
context.addFile("models/item/wooden_pickaxe", "change wooden pickaxe");
context.addFile("models/item/golden_pickaxe", "change golden pickaxe");
}

Registering a Generative Event

There is a single annotation for generative events: @GenerativeMixsonEvent. Instead of taking in resourceId and eventId, generative events take in a generatorId (as value).

Below is the definition of the @GenerativeMixsonEvent:

public @interface GenerativeMixsonEvent {
String value();
int priority() default Mixson.DEFAULT_PRIORITY;
boolean failSilently() default false;
int ordinal() default -1;
boolean external() default false;
...
}

the external field specifies if the generator may be found outside the class that the method was declared in.

Generative Modification Example

The following event runs the generator modid:generator_one to put the netherite pickaxe texture on different sources:

@GenerativeMixsonEvent("modid:generator_one")
private static void modid$changeWoodenAndGoldenPickaxeTexture(EventContext context, @Reference("models/item/netherite_pickaxe") BuiltResourceReference modid$netheritePickaxeModel) {
JsonElement elem = context.getFile();
JsonObject object = elem.getAsJsonObject();
Optional<JsonElement> maybePickaxe = modid$coalBlockReference.retrieve();
if(maybePickaxe.isEmpty()) return;
String textureFile = maybePickaxe.get().getAsJsonObject().getAsJsonObject("textures").get("layer0");
object.getAsJsonObject("textures").addProperty("layer0", textureFile);
}
@Generator("modid:generator_one")
private static void generatorOne(GeneratorContext context) {
context.addFile("models/item/wooden_pickaxe", "change wooden pickaxe");
context.addFile("models/item/golden_pickaxe", "change golden pickaxe");
}