tutorial:mixin_tips
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
tutorial:mixin_tips [2022/08/05 02:29] – clomclem | tutorial:mixin_tips [2023/12/18 02:06] (current) – solidblock | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Mixin Tips ====== | + | FIXME //This page is currently being written, and may change at any time.// |
+ | ====== Mixin Tips (WIP) ====== | ||
- | ==== Why make a class abstract? ==== | + | This is a collection of different tips some might find useful. It's recommended to read the previous articles to understand the tips. |
- | **1. Prevent instantiation** | + | ===== Make abstract classes ===== |
It's fair to say that you should never instantiate a mixin class, mainly because the class doesn' | It's fair to say that you should never instantiate a mixin class, mainly because the class doesn' | ||
- | Declaring a mixin class abstract doesn' | + | Declaring a mixin class abstract doesn' |
<code java> | <code java> | ||
Line 14: | Line 15: | ||
</ | </ | ||
- | + | ===== Make abstract | |
- | **2. Make more elegant | + | |
If you want to access a unaccessible method or field from your target class into your mixin class, you need to use '' | If you want to access a unaccessible method or field from your target class into your mixin class, you need to use '' | ||
Line 23: | Line 23: | ||
<code java> | <code java> | ||
@Shadow | @Shadow | ||
- | private | + | protected |
</ | </ | ||
But it's much more // | But it's much more // | ||
<code java> | <code java> | ||
- | private | + | @Shadow |
+ | protected | ||
</ | </ | ||
+ | Note: this doesn' | ||
- | **3. Access the "this" | + | ===== Access the '' |
- | In mixin, if you want to access the " | + | In mixin, if you want to access the "'' |
<code java> | <code java> | ||
Line 40: | Line 42: | ||
</ | </ | ||
- | But that only works if your mixin class extends/ | + | But that only works if your mixin class extends/ |
- | Luckily, this can all be avoided by using an abstract class, in which case you don't have to implement | + | Luckily, this can all be avoided by using an abstract class, in which case you don't have to implement methods and all problems are avoided. |
- | ** UNDER CONSTRUCTION ** | + | ===== How to mixin inner classes ===== |
+ | ==== 1. Normal inaccessible inner classes ==== | ||
+ | |||
+ | Since this you can't directly access (and hence mention) these classes from outside, you need to use the " | ||
+ | |||
+ | You do this by using the complete name of the outer class, then a '' | ||
+ | |||
+ | Class: | ||
+ | |||
+ | <code java> | ||
+ | package some.random.package; | ||
+ | |||
+ | public class Outer { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Mixin with injection: | ||
+ | |||
+ | <code java> | ||
+ | @Mixin(targets = " | ||
+ | public class MyMixin { | ||
+ | @Inject(method = " | ||
+ | private void injected(CallbackInfo ci) { | ||
+ | // your code here | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The only caveat is that if you want to mixin into the inner class constructor, | ||
+ | |||
+ | <code java> | ||
+ | @Inject(method = "< | ||
+ | private void injected(CallbackInfo ci) { | ||
+ | // your code here | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== 2. Static inaccessible inner classes ==== | ||
+ | |||
+ | These are the same as above, the only difference is that the constructor doesn' | ||
+ | |||
+ | |||
+ | ==== 3. Anonymous inner classes ==== | ||
+ | |||
+ | These are the same as the static inaccessible inner classes, the only difference is that since they don't have a name, they are declared by appearance order, for example: the anonymous inner class if declared in our previous example class first would be named Outer$1, a second one would be named Outer$2, a third one Outer$3 and so on (the declaration order is on source level). | ||
+ | |||
+ | ===== How to mixin to lambdas ===== | ||
+ | |||
+ | Sometimes you want to mixin to lambdas. However, lambda do not have visible names. In this case, remember that **mixin is applied to bytecode instead of source**. Therefore, you can view the bytecode to view lambdas. | ||
+ | |||
+ | For example, we want to inject the lambda in '' | ||
+ | <code java> | ||
+ | public class EntitySelectorOptions { | ||
+ | public static void register() { | ||
+ | if (...) { | ||
+ | putOption(" | ||
+ | // Assume that you want to mixin to here | ||
+ | int i = reader.getReader().getCursor(); | ||
+ | // ... | ||
+ | } | ||
+ | // ... | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | If you directly injects to '' | ||
+ | <code java> | ||
+ | private static synthetic method_9982(Lnet/ | ||
+ | L0 | ||
+ | // ... | ||
+ | </ | ||
+ | |||
+ | Therefore, the method name of the lambda you want to mixin should be '' | ||
+ | |||
+ | ===== Mixin to those not remapped ===== | ||
+ | |||
+ | If you want to mixin to classes, methods or fields that are not remapped in yarn, such as '' | ||
+ | <code java> | ||
+ | @Mixin(value = StringReader.class, | ||
+ | public abstract class StringReaderMixin { ... } | ||
+ | </ | ||
+ | |||
+ | Another example is: | ||
+ | |||
+ | <code java> | ||
+ | @Mixin(EntitySelectorReader.class) | ||
+ | public abstract class EntitySelectorReaderMixin { | ||
+ | @Inject(method = " | ||
+ | // your injection method ... | ||
+ | } | ||
+ | </ |
tutorial/mixin_tips.1659666546.txt.gz · Last modified: 2022/08/05 02:29 by clomclem