User Tools

Site Tools


tutorial:mixin_injects

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_injects [2022/03/08 18:56] – Added interface inection section. salvopeluxtutorial:mixin_injects [2022/08/05 19:19] (current) – Added signed to integer types clomclem
Line 5: Line 5:
  
 <code java> <code java>
-@Inject(method = "", at = @At("INJECTION POINT REFERENCE"))+@Inject(method = "METHOD NAME OR SIGNATURE", at = @At("INJECTION POINT REFERENCE"))
 private void injectMethod(METHOD ARGS, CallbackInfo info) { private void injectMethod(METHOD ARGS, CallbackInfo info) {
  
Line 28: Line 28:
 | D | double | double-precision floating-point value | | D | double | double-precision floating-point value |
 | F | float | single-precision floating-point value | | F | float | single-precision floating-point value |
-| I | int | integer | +| I | int | signed integer | 
-| J | long | long integer |+| J | long | signed long integer |
 | L//ClassName//; | reference | an instance of //ClassName// | | L//ClassName//; | reference | an instance of //ClassName// |
 | S | short | signed short | | S | short | signed short |
Line 35: Line 35:
 | [ | reference | one array dimension | | [ | reference | one array dimension |
  
-A method descriptor is comprised of the method name, followed by a set of parentheses containing the input types, followed by the output type. A method defined in Java as ''Object m(int i, double[] d, Thread t)'' would have the method descriptor ''m(I[DLjava/lang/Thread;)Ljava/lang/Object;''+A method descriptor is comprised of the method name, followed by a set of parentheses containing the parameter types, followed by the return type. A method defined in Java as ''Object m(int i, double[] d, Thread t)'' would have the method descriptor ''m(I[DLjava/lang/Thread;)Ljava/lang/Object;''.
  
-Generics' types are left out, as Generics don't exist on runtime. So ''Pair<Integer, ? extends Task<? super VillagerEntity>‍>'' would become ''Lcom/mojang/datafixers/util/Pair''.+In the case that the return type is voidyou need to use V (Void Descriptor Type) as the type (for example, ''void foo(String bar)'' would become ''foo(Ljava/lang/String;)V'').
  
-//@Inject// methods always have a void return type. The method name does not matter; using something that describes what the inject does is best. The target method's arguments are placed first in the method's header, followed by a ''CallbackInfo'' object. If the target method has a return type (T), ''CallbackInfoReturnable<T>'' is used instead of ''CallbackInfo''.+Generics' types are left out, as generics don't exist on runtime. So ''Pair<Integer, ? extends Task<? super VillagerEntity>‍>'' would become ''Lcom/mojang/datafixers/util/Pair''
 + 
 +''@Inject'' methods always have a void return type. The method name does not matter and neither does the access modifier; using something that describes what the inject does is best. The target method's arguments are placed first in the method's header, followed by a ''CallbackInfo'' object. If the target method has a return type (T), ''CallbackInfoReturnable<T>'' is used instead of ''CallbackInfo''.
  
 === Returning & Cancelling from Inject === === Returning & Cancelling from Inject ===
Line 67: Line 69:
  
 For more information on this particular example, view its usage in the [[https://github.com/FabricMC/fabric-example-mod/blob/master/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java|Fabric Example Mod repo]]. For more information on this particular example, view its usage in the [[https://github.com/FabricMC/fabric-example-mod/blob/master/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java|Fabric Example Mod repo]].
- 
-====== Inject an interface ====== 
- 
-This is a new tecnique introduced by Loom 0.11 to add methods into a specific existing class. 
-More specifically, you can create an Interface, and then inject this interface into the class. 
-As result the target class will acquire all the methods of the interface, as if it always had them. 
-Interface injection is a compile time only feature, this means that a Mixin should also be used to implement the interface into the target class. 
- 
-This is particulatly useful for libraries, with this you can add new methods to existing classes and use them without the need of casting or reimplementing the interface every time. 
- 
-Let's explain better with an example: 
- 
-The scope of this example is to add the following method into FlowableFluid to get the sound of the bucket when emptied. 
-This, normally, is not possible because FlowableFluid does not has a similar method. 
- 
-<code java [enable_line_numbers="false"]> 
-Optional<SoundEvent> getBucketEmptySound() 
-</code> 
- 
-To add the method into the class, first of all you need to create an interface with it: 
- 
-<code java [enable_line_numbers="false"]> 
-package net.fabricmc.example; 
- 
-public interface BucketEmptySoundGetter { 
- Optional<SoundEvent> getBucketEmptySound(); 
-} 
-</code> 
- 
-Now you need to implement this interface into FlowableFluid with a mixin implementing the interface: 
- 
-<code java [enable_line_numbers="false"]> 
-@Mixin(FlowableFluid.class) 
-public class MixinFlowableFluid implements BucketEmptySoundGetter { 
- @Override 
- public Optional<SoundEvent> getBucketEmptySound() { 
- 
- return Optional.of(((FlowableFluid) (Object) this).isIn(FluidTags.LAVA) ? SoundEvents.ITEM_BUCKET_EMPTY_LAVA : SoundEvents.ITEM_BUCKET_EMPTY); 
- } 
-} 
-</code> 
- 
-Lastly you need to inject the interface into FabricFluid. 
-The following snippet can be added to your fabric.mod.json file to add one or more interfaces to the net/minecraft/fluid/FlowableFluid class. 
- 
-<code json [enable_line_numbers="false"]> 
-{ 
- "custom": { 
- "loom:injected_interfaces": { 
- "net/minecraft/class_3609": ["net/fabricmc/example/BucketEmptySoundGetter"] 
- } 
- } 
-} 
-</code> 
- 
-Now you can use the new method: 
- 
-<code java [enable_line_numbers="false"]> 
-Optional<SoundEvent> sound = mytestfluid.getBucketEmptySound(); 
-</code> 
- 
-You could also override this method in classes extending FlowableFluid to implement custom behaviours. 
tutorial/mixin_injects.1646765768.txt.gz · Last modified: 2022/03/08 18:56 by salvopelux