User Tools

Site Tools


zh_cn:tutorial:mixin_examples

Differences

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

Link to this comparison view

Next revision
Previous revision
zh_cn:tutorial:mixin_examples [2021/08/29 11:09] – 暂定填充页面 hendrix-shenzh_cn:tutorial:mixin_examples [2023/12/18 02:19] (current) – [捕获局部变量] solidblock
Line 1: Line 1:
 ====== Mixin 示例 ====== ====== Mixin 示例 ======
-收录了较为常见的 Mixin 示例.+收录了较为常见的 Mixin 示例。此页面旨在帮助开发者快速学习 Mixin 的使用,建议在开始之前先查看 [[zh_cn:tutorial:mixin_introduction|Mixin介绍]]。
  
-===== Injecting into the head of a method =====+===== 注入到内部私有类的一个方法 ===== 
 +使用 targets 参数并添加 ''$'' 符号来指向内部类。 
 +<code java> 
 +@Mixin(targets = "net.minecraft.client.render.block.BlockModelRenderer$AmbientOcclusionCalculator"
 +public class AmbientOcclusionCalculatorMixin { 
 +    // 为所欲为 ^ v ^ 
 +
 +</code> 
 + 
 +===== 在 Mixin 类中获取目标类实例对象 ===== 
 +注意:应该避免像这样两次强转 ''this''。如果你是要使用来自目标来的方法或字段,使用 ''@Shadow''。如果方法或字段是来自目标类的父类,可以直接将你的这个 mixin 继承那个父类。 
 +Mixin: 
 +<code java> 
 +@Mixin(TargetClass.class) 
 +public class MyMixin extends EveryThingThatTargetClassExtends implements EverythingThatTargetClassImplements { 
 +  @Inject(method = "foo()V", at = @At("HEAD")) 
 +  private void injected(CallbackInfo ci) { 
 +    TargetClass thisObject = (TargetClass)(Object)this; 
 +  } 
 +
 +</code> 
 +===== 注入到静态初始化代码块的开头 ===== 
 +Mixin: 
 +<code java> 
 +@Inject(method = "<clinit>", at = @At("HEAD")) 
 +private void injected(CallbackInfo ci) { 
 +    doSomething3(); 
 +
 +</code> 
 + 
 +结果: 
 +<code diff> 
 +static { 
 ++   injected(new CallbackInfo(“<clinit>”, false)); 
 +    doSomething1(); 
 +    doSomething2(); 
 +
 +</code> 
 + 
 +===== 注入在一个方法的开头 =====
 Mixin: Mixin:
 <code java> <code java>
Line 11: Line 50:
 </code> </code>
  
-Result:+结果:
 <code diff> <code diff>
   public void foo() {   public void foo() {
Line 21: Line 60:
 </code> </code>
  
-===== Injecting into the tail of a method =====+===== 注入到一个方法的结尾 =====
 Mixin: Mixin:
 <code java> <code java>
Line 30: Line 69:
 </code> </code>
  
-Result:+结果:
 <code diff> <code diff>
   public void foo() {   public void foo() {
Line 42: Line 81:
 </code> </code>
  
-===== Injecting into the returns of a method =====+===== 注入到一个方法的返回之前 =====
 Mixin: Mixin:
 <code java> <code java>
Line 51: Line 90:
 </code> </code>
  
-Result:+结果:
 <code diff> <code diff>
   public void foo() {   public void foo() {
Line 64: Line 103:
 </code> </code>
  
-===== Injecting into the point before a method call =====+===== 注入到一个方法调用之前 =====
 Mixin: Mixin:
 <code java> <code java>
Line 73: Line 112:
 </code> </code>
  
-Result:+结果:
 <code diff> <code diff>
   public void foo() {   public void foo() {
Line 84: Line 123:
 </code> </code>
  
-===== Injecting into the point after a method call =====+===== 注入到一个方法调用之后 =====
 Mixin: Mixin:
 <code java> <code java>
Line 93: Line 132:
 </code> </code>
  
-Result:+结果:
 <code diff> <code diff>
   public void foo() {   public void foo() {
Line 104: Line 143:
 </code> </code>
  
-===== Injecting with a slice =====+===== 使用偏移量注入 ===== 
 +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> 
 + 
 +结果: 
 +<code diff> 
 +  public void foo() { 
 +    doSomething1(); 
 +    Something something = new Something(); 
 +    something.doSomething(); 
 +    doSomething2(); 
 ++   injected(new CallbackInfo("foo", false)); 
 +  } 
 +</code> 
 + 
 +===== 使用 Slice 控制注入范围 =====
 Mixin: Mixin:
 <code java> <code java>
Line 123: Line 182:
 </code> </code>
  
-Result:+结果:
 <code diff> <code diff>
   public class Something {   public class Something {
     public void foo() {     public void foo() {
       this.doSomething1();       this.doSomething1();
-+     // It will not inject into here because this is outside of the slice section++     // 不会注入到此位置,因为它位于Slice范围之外
       this.doSomething();       this.doSomething();
       this.doSomething2();       this.doSomething2();
Line 134: Line 193:
       this.doSomething();       this.doSomething();
       this.doSomething3();       this.doSomething3();
-+     // It will not inject into here because this is outside of the slice section++     // 不会注入到此位置,因为它位于Slice范围之外
       this.doSomething();       this.doSomething();
       this.doSomething4();       this.doSomething4();
Line 141: Line 200:
 </code> </code>
  
-===== Injecting and cancelling =====+===== 注入并直接使当前方法返回 =====
 Mixin: Mixin:
 <code java> <code java>
Line 150: Line 209:
 </code> </code>
  
-Result:+结果:
 <code diff> <code diff>
   public void foo() {   public void foo() {
Line 162: Line 221:
 </code> </code>
  
-===== Injecting and cancelling with a return value =====+===== 注入并使当前方法返回指定返回值 =====
 Mixin: Mixin:
 <code java> <code java>
Line 171: Line 230:
 </code> </code>
  
-Result:+结果:
 <code diff> <code diff>
   public int foo() {   public int foo() {
Line 184: Line 243:
 </code> </code>
  
-===== Modifying a return value =====+===== 捕获局部变量 ===== 
 +==== 不用 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: 如果计算局部变量与预期不符则抛出一个异常。 
 +  arg1.doSomething4(); 
 +
 +</code> 
 + 
 +结果: 
 +<code diff> 
 +  public void foo() { 
 +    TypeArg1 arg1 = getArg1(); 
 +    arg1.doSomething1(); 
 +    arg1.doSomething2(); 
 +    TypeArg2 arg2 = getArg2(); 
 +    arg2.doSomething3(); 
 ++   injected(new CallbackInfo("foo", false), arg1); 
 +  } 
 +</code> 
 + 
 + 
 +==== 使用 MixinExtras 捕获局部变量 ==== 
 +:!: MixinExtras 需要 Fabric Loader 0.15 或者以上版本,否则你需要在 ''build.gradle'' 中手动指定。 
 + 
 +:!: 如果有多个同一类型的局部变量,你需要指定 ''ordinal'' 否则会抛出错误。 
 + 
 +Mixin: 
 +<code java> 
 +@Inject(method = "foo()V", at = @At(value = "TAIL")) 
 +private void injected(CallbackInfo ci, @Local TypeArg2 arg2) { 
 +  arg1.doSomething4(); 
 +
 +</code> 
 + 
 +结果: 
 +<code diff> 
 +  public void foo() { 
 +    TypeArg1 arg1 = getArg1(); 
 +    arg1.doSomething1(); 
 +    arg1.doSomething2(); 
 +    TypeArg2 arg2 = getArg2(); 
 +    arg2.doSomething3(); 
 ++   injected(new CallbackInfo("foo", false), arg2); 
 +  } 
 +</code> 
 + 
 +==== 捕获多个同一类型的局部变量中的一个 ==== 
 +Mixin: 
 +<code java> 
 +@Inject(method = "foo()V", at = @At(value = "TAIL")) 
 +private void injected(CallbackInfo ci, @Local(ordinal = 2) TypeArg arg) { 
 +  arg1.doSomething4(); 
 +
 +</code> 
 + 
 +结果: 
 +<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> 
 +===== 修改返回值 =====
 Mixin: Mixin:
 <code java> <code java>
Line 193: Line 322:
 </code> </code>
  
-Result:+结果:
 <code diff> <code diff>
   public int foo() {   public int foo() {
Line 207: Line 336:
 </code> </code>
  
-===== Redirecting a method call =====+===== 重定向一个方法调用 =====
 Mixin: Mixin:
 <code java> <code java>
Line 216: Line 345:
 </code> </code>
  
-Result:+结果:
 <code diff> <code diff>
   public void foo() {   public void foo() {
Line 227: Line 356:
 </code> </code>
  
-===== Redirecting a get field =====+===== 重定向获取到的字段值 =====
 Mixin: Mixin:
 <code java> <code java>
Line 236: Line 365:
 </code> </code>
  
-Result:+结果:
 <code diff> <code diff>
   public class Something {   public class Something {
Line 251: Line 380:
 </code> </code>
  
-===== Redirecting a put field =====+===== 重定向一个字段的赋值 =====
 Mixin: Mixin:
 <code java> <code java>
Line 260: Line 389:
 </code> </code>
  
-Result:+结果:
  
 <code diff> <code diff>
Line 274: Line 403:
 </code> </code>
  
-===== Modifying an argument =====+===== 修改调用方法的一个参数 =====
 Mixin: Mixin:
 <code java> <code java>
Line 283: Line 412:
 </code> </code>
  
-Result:+结果:
 <code diff> <code diff>
   public void foo() {   public void foo() {
Line 294: Line 423:
 </code> </code>
  
-===== Modifying multiple arguments =====+===== 修改调用方法的多个参数 =====
 Mixin: Mixin:
 <code java> <code java>
Line 308: Line 437:
 </code> </code>
  
-Result:+结果:
 <code diff> <code diff>
   public void foo() {   public void foo() {
Line 314: Line 443:
     Something something = new Something();     Something something = new Something();
 -   something.doSomething(3, 2.5D, true); -   something.doSomething(3, 2.5D, true);
-+   // Actually, synthetic subclass of Args is generated at runtime, ++   // 事实上,自动生成的 Args 子类是在运行时被创建的, 
-+   // but we omit the details to make it easier to understand the concept.++   // 但是我们抹去了一些细节以便于理解。
 +   Args args = new Args(new Object[] { 3, 2.5D, true }); +   Args args = new Args(new Object[] { 3, 2.5D, true });
 +   injected(args); +   injected(args);
Line 323: Line 452:
 </code> </code>
  
-===== Modifying a parameter =====+===== 修改一个接收参数 =====
 Mixin: Mixin:
 <code java> <code java>
Line 332: Line 461:
 </code> </code>
  
-Result:+结果:
 <code diff> <code diff>
   public void foo(boolean b, int x, int y, int z) {   public void foo(boolean b, int x, int y, int z) {
Line 342: Line 471:
 </code> </code>
  
-===== Modifying a local variable on an assignment =====+===== 在赋值时修改一个局部变量 =====
 Mixin: Mixin:
 <code java> <code java>
Line 351: Line 480:
 </code> </code>
  
-Result:+结果:
 <code diff> <code diff>
   public void foo() {   public void foo() {
Line 362: Line 491:
 </code> </code>
  
-===== Modifying a constant =====+===== 修改一个常量 =====
 Mixin: Mixin:
 <code java> <code java>
Line 371: Line 500:
 </code> </code>
  
-Result:+结果:
 <code diff> <code diff>
   public void foo() {   public void foo() {
zh_cn/tutorial/mixin_examples.1630235384.txt.gz · Last modified: 2021/08/29 11:09 by hendrix-shen