User Tools

Site Tools


tutorial:mixin_examples

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
tutorial:mixin_examples [2022/08/05 16:10] clomclemtutorial:mixin_examples [2025/10/12 09:21] (current) – Mark page as having a planned rewrite gauntrecluse
Line 1: Line 1:
 +FIXME //The Fabric Wiki's Mixin segments is under heavy reviews, pages on the topic are subject to major edits or rewrites. This page in particular is noted as being unreliable to learn Mixin as a tool from. Learning by example should be used sparingly, as it may lead to a lack of understanding. Prioritize, if you are unable to learn through documentation, presenting your intention in detail in a Mixin support channel on the Fabric or SpongePowered Discord servers and discussing with experienced devs there.//
 +
 +
 +:!: //A rewrite of this page is planned and will be drafted in the foreseeable future, whilst some quicker changes and improvements may be applied to this page in the process, more fundamental structural changes will happen as part of a broader rewrite and replacement by a new version of the page//
 +
 ====== Mixin Examples ====== ====== Mixin Examples ======
 This is a collection of frequently used mixins. This is a collection of frequently used mixins.
Line 8: Line 13:
 <code java> <code java>
 @Mixin(targets = "net.minecraft.client.render.block.BlockModelRenderer$AmbientOcclusionCalculator") @Mixin(targets = "net.minecraft.client.render.block.BlockModelRenderer$AmbientOcclusionCalculator")
-public class Calculator {+public class AmbientOcclusionCalculatorMixin {
     // do your stuff here     // do your stuff here
 } }
 </code> </code>
  
-===== Access `thisinstance of the class your mixin is targeting =====+===== Access the this instance of the class your mixin is targeting ===== 
 +Note: Double casting ''this'' should be avoided when possible. If you intend to use a method or field from the target class, use ''@Shadow''. If the method or field is from a parent of the target class, have your mixin extend the direct parent of the target class. 
 Mixin: Mixin:
 <code java> <code java>
Line 20: Line 27:
   @Inject(method = "foo()V", at = @At("HEAD"))   @Inject(method = "foo()V", at = @At("HEAD"))
   private void injected(CallbackInfo ci) {   private void injected(CallbackInfo ci) {
-    ((TargetClass)(Object)this).methodOfTheTargetClass();+    TargetClass thisObject = (TargetClass)(Object)this;
   }   }
 +}
 +</code>
 +
 +===== Injecting into the head of a static block =====
 +Mixin:
 +<code java>
 +@Inject(method = "<clinit>", at = @At("HEAD"))
 +private void injected(CallbackInfo ci) {
 +    doSomething3();
 +}
 +</code>
 +
 +Result:
 +<code diff>
 +static {
 ++   injected(new CallbackInfo(“<clinit>”, false));
 +    doSomething1();
 +    doSomething2();
 } }
 </code> </code>
Line 124: Line 149:
 +   injected(new CallbackInfo("foo", false)); +   injected(new CallbackInfo("foo", false));
     doSomething2();     doSomething2();
 +  }
 +</code>
 +
 +===== Injecting into the point with shift amount =====
 +Mixin:
 +<code java>
 +@Inject(method = "foo()V", at = @At(value = "INVOKE", target = "La/b/c/Something;doSomething()V", shift = At.Shift.BY, by = 2))
 +private void injected(CallbackInfo ci) {
 +  doSomething3();
 +}
 +</code>
 +
 +Result:
 +<code diff>
 +  public void foo() {
 +    doSomething1();
 +    Something something = new Something();
 +    something.doSomething();
 +    doSomething2();
 ++   injected(new CallbackInfo("foo", false));
   }   }
 </code> </code>
Line 207: Line 252:
 </code> </code>
  
 +===== Capturing local values =====
 +==== Capture locals without MixinExtras ====
 +
 +Mixin:
 +<code java>
 +@Inject(method = "foo()V", at = @At(value = "TAIL"), locals = LocalCapture.CAPTURE_FAILHARD)
 +private void injected(CallbackInfo ci, TypeArg1 arg1) {
 +  //CAPTURE_FAILHARD: If the calculated locals are different from the expected values, throws an error.
 +  arg1.doSomething4();
 +}
 +</code>
 +
 +Result:
 +<code diff>
 +  public void foo() {
 +    TypeArg1 arg1 = getArg1();
 +    arg1.doSomething1();
 +    arg1.doSomething2();
 +    TypeArg2 arg2 = getArg2();
 +    arg2.doSomething3();
 ++   injected(new CallbackInfo("foo", false), arg1);
 +  }
 +</code>
 +
 +==== Capture locals with MixinExtras ====
 +:!: See the oficial MixinExtra's [[https://github.com/LlamaLad7/MixinExtras/wiki/Local|Wiki]].
 +
 +:!: MixinExtras required Fabric Loader 0.15 or above, or you have to manually specify it in ''build.gradle''.
 +
 +:!: If there are multiple locals with that type, you have to specify ''ordinal'' or it will throw an error.
 +
 +:!: the use of ''@Local'' is recommended over ''LocalCapture''
 +
 +Mixin:
 +<code java>
 +@Inject(method = "foo()V", at = @At(value = "TAIL"))
 +private void injected(CallbackInfo ci, @Local TypeArg2 arg2) {
 +  arg2.doSomething4();
 +}
 +</code>
 +
 +Result:
 +<code diff>
 +  public void foo() {
 +    TypeArg1 arg1 = getArg1();
 +    arg1.doSomething1();
 +    arg1.doSomething2();
 +    TypeArg2 arg2 = getArg2();
 +    arg2.doSomething3();
 ++   injected(new CallbackInfo("foo", false), arg2);
 +  }
 +</code>
 +
 +==== Capturing one of multiple locals of a type ====
 +Mixin:
 +<code java>
 +@Inject(method = "foo()V", at = @At(value = "TAIL"))
 +private void injected(CallbackInfo ci, @Local(ordinal = 2) TypeArg arg) {
 +  arg.doSomething4();
 +}
 +</code>
 +
 +Result:
 +<code diff>
 +  public void foo() {
 +    TypeArg arg1 = getArg1();
 +    TypeArg arg2 = getArg2();
 +    TypeArg arg3 = getArg3();
 +    TypeArg arg4 = getArg4();
 +    doSomething();
 ++   injected(new CallbackInfo("foo", false), arg3);
 +  }
 +</code>
 +
 +===== Modifying locals =====
 +This requires MixinExtras.
 +
 +Mixin:
 +<code java>
 +  @Inject(method = "foo()V", at = @At(value = "INVOKE", target = "doSomething()V", shift = At.Shift.AFTER))
 +  private static void injected(CallbackInfo ci, @Local LocalRef<String> localRef) {
 +    localRef.set(localRef.get() + " - modified")
 +  }
 +</code>
 +
 +Result:
 +<code diff>
 +  public void foo() {
 +    String s = "example string";
 +    doSomething();
 ++   s = s + " - modified";
 +    doSomething2(s);
 +  }
 +</code>
 ===== Modifying a return value ===== ===== Modifying a return value =====
 Mixin: Mixin:
tutorial/mixin_examples.1659715834.txt.gz · Last modified: 2022/08/05 16:10 by clomclem