public abstract class MixinWorldProviderExample extends Object
Inject
annotation. A full explanation of the various At
options
is beyond the scope of this example but a number of common examples are provided below.Constructor and Description |
---|
MixinWorldProviderExample() |
Modifier and Type | Method and Description |
---|---|
void |
onCanCoordinateBeSpawn(int x,
int z,
org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable<Boolean> cir)
This method demonstrates the use of the cancellable argument for an injection.
|
void |
onGetFogColor(float celestialAngle,
float partialTicks,
org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable<net.minecraft.util.Vec3> cir)
This method demonstrates injecting into a method with a return value.
|
void |
onRegisterWorld(net.minecraft.world.World worldIn,
org.spongepowered.asm.mixin.injection.callback.CallbackInfo ci)
What's this? A parameterised
At ? Surely not! |
public void onGetFogColor(float celestialAngle, float partialTicks, org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable<net.minecraft.util.Vec3> cir)
This method demonstrates injecting into a method with a return value. Notice that we take the original method, change the return type to
void and add a CallbackInfoReturnable
with the original return type (Vec3
) as the type parameter.
This method also demonstrates a more precise syntax for identifying the target method. This is useful if there are several methods in the
target class with the same name. We simply append the bytecode descriptor of the target method to the method name. For more details on this
syntax see the javadoc in org.spongepowered.asm.mixin.injection.struct.MemberInfo
.
The At
specified HEAD will inject the callback at the top of the method (before all other code).
celestialAngle
- The celestial anglepartialTicks
- The partial tickscir
- The callbackpublic void onCanCoordinateBeSpawn(int x, int z, org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable<Boolean> cir)
This method demonstrates the use of the cancellable argument for an injection. Specifying that an injection is cancellable allows us to supply our own return values and short-circuit the target method's normal logic.
Choosing the appropriate At
is very important when dealing with cancellable callbacks. For example you may with to be able to
"short-circuit" a method by injecting at the HEAD and cancelling it if you don't want the method to be executed. However if you want the method
to execute but be able to change the result, then injecting at RETURN makes more sense. Injecting at RETURN also allows you to see the value
the method was going to return and optionally change it. The CallbackInfoReturnable.getReturnValue()
method can be used to get the return
value from the stack, but only when using the RETURN injection point.
It should be noted that it's perfectly possible to specify cancellable when injecting into a method which returns void, but with the key difference being that it's not possible to fetch the return value (because there isn't one) or set a return value (because there isn't one!) but it is still perfectly possible to short-circuit a method in this way.
x
- The x coordinatez
- The z coordinatecir
- The callbackpublic void onRegisterWorld(net.minecraft.world.World worldIn, org.spongepowered.asm.mixin.injection.callback.CallbackInfo ci)
What's this? A parameterised At
? Surely not!
HEAD
and
RETURN
are only two of the available values for At
types and are the
most straightforward to understand. HEAD only ever makes a single injection (at the head of the method) and RETURN injects before every
RETURN opcode in a method. Other injection types are available however:
INVOKE
FIELD
NEW
INVOKE_STRING
JUMP
InjectionPoint
to implement any custom
logic you wishThe specific arguments accepted by each type of invokation are described in each class's javadoc. This example shows a simple use of the INVOKE type.
This is what the code in the target method looks like:
this.worldObj = worldIn; this.terrainType = worldIn.getWorldInfo().getTerrainType(); this.generatorSettings = worldIn.getWorldInfo().getGeneratorOptions(); // we want to inject a callback to our method here, immediately prior to calling registerWorldChunkManager this.registerWorldChunkManager(); this.generateLightBrightnessTable();
Having identified the target method, we simply supply the method name as the target argument to the At
annotation. Note
that
unlike the method parameter (which must refer to a method in the target class) the target parameter for the At
must be a fully-qualified member reference (include both the owner and signature) because the obfuscation processor requires
this information in order to look up the target member in the obfuscation tables.
worldIn
- The world to registerci
- The callback on register