drafts:mixin_access_added_members
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revision | |||
| drafts:mixin_access_added_members [2026/01/03 14:50] – removed - external edit (Unknown date) 127.0.0.1 | drafts:mixin_access_added_members [2026/01/03 14:50] (current) – ↷ Page name changed from drafts:mixin_duck_interface to drafts:mixin_access_added_members gauntrecluse | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Accessing Added Members ====== | ||
| + | ===== Introduction ===== | ||
| + | |||
| + | Mixin allows developers to add new fields and methods to a target class, this can be useful for operations internal to the Mixin class, but you may want to expose your added members to the rest of your project. In order to do this, we can leverage interfaces. By implementing an interface into the Mixin class, and using the implemented methods to expose our added members, we're able to call the interface methods outside of the Mixin class by casting instances of the target class to the interface. | ||
| + | |||
| + | This process is often called using a " | ||
| + | |||
| + | ===== Tutorial ===== | ||
| + | |||
| + | ==== Hypothetical Scenario ==== | ||
| + | |||
| + | For our example situation, we'll use 1.21.10 with Mojang Mappings. We will add and expose fields to the Zombie class for a hypothetical combo mechanic we'd want to be able to interact with outside of the Mixin. | ||
| + | |||
| + | ==== Adding the Field ==== | ||
| + | |||
| + | <code java> | ||
| + | @Mixin(Zombie.class) | ||
| + | abstract class ZombieExampleMixin { | ||
| + | |||
| + | @Unique | ||
| + | private int modid$comboCount; | ||
| + | | ||
| + | @Inject(method = "< | ||
| + | private void populateField() { | ||
| + | modid$comboCount = 0; | ||
| + | } | ||
| + | |||
| + | @Inject(method = " | ||
| + | private void doSomethingWithCombos(CallbackInfo ci) { | ||
| + | /* ... */ | ||
| + | } | ||
| + | |||
| + | } | ||
| + | </ | ||
| + | |||
| + | This field is normally entirely inaccessible, | ||
| + | |||
| + | :?: We use '' | ||
| + | |||
| + | ==== Creating the Interface ==== | ||
| + | |||
| + | A somewhat common naming convention for interfaces with this purpose is '' | ||
| + | |||
| + | <code java> | ||
| + | public interface ZombieAccess { | ||
| + | |||
| + | int modid$getComboHits(); | ||
| + | |||
| + | void modid$setComboHits(int newCount); | ||
| + | |||
| + | } | ||
| + | </ | ||
| + | |||
| + | This effectively acts as an exposed getter and setter for our example' | ||
| + | |||
| + | ==== Implementing the Interface ==== | ||
| + | |||
| + | <code java> | ||
| + | @Mixin(Zombie.class) | ||
| + | abstract class ZombieExampleMixin implements ZombieAccess { | ||
| + | |||
| + | @Unique | ||
| + | private int modid$comboCount; | ||
| + | |||
| + | @Override | ||
| + | public int modid$getComboHits() { | ||
| + | return modid$comboCount; | ||
| + | } | ||
| + | |||
| + | @Override | ||
| + | public void modid$setComboHits(int newCount) { | ||
| + | modid$comboCount = newCount; | ||
| + | } | ||
| + | |||
| + | @Inject(method = "< | ||
| + | private void populateField() { | ||
| + | modid$comboCount = 0; | ||
| + | } | ||
| + | |||
| + | |||
| + | @Inject(method = " | ||
| + | private void doSomethingWithCombos(CallbackInfo ci) { | ||
| + | /* ... */ | ||
| + | } | ||
| + | |||
| + | } | ||
| + | </ | ||
| + | |||
| + | ==== Using the Interface ==== | ||
| + | |||
| + | The compiler will allow us to cast instances of the '' | ||
| + | |||
| + | <code java> | ||
| + | public class ExampleClass { | ||
| + | |||
| + | public static void holder(Zombie zombie) { | ||
| + | int currentCombo = ((ZombieAccess) zombie).modid$getComboHits(); | ||
| + | ((ZombieAccess) zombie).modid$setComboHits(currentCombo + 1); | ||
| + | } | ||
| + | |||
| + | } | ||
| + | </ | ||