tutorial:mixin_accessors
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| tutorial:mixin_accessors [2020/08/29 15:18] – Add how to add ores to the end biomes siglong | tutorial:mixin_accessors [2025/11/30 20:08] (current) – gauntrecluse | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== | + | ====== |
| - | A lot of mods add their own ores, and you'll need a way to place them in existing biomes for players to find. In this tutorial, we'll look at adding ores to existing biomes. There are 2 steps that are required to add ores to biomes. | + | |
| - | * Make a ConfiguredFeatures. This defines how your ore block is spawned. | + | |
| - | * Register your feature by using [[tutorial: | + | |
| - | We'll assume you've already created your own ore block at this point. Quartz Ore will serve as our replacement throughout this tutorial. Replace references to Quartz Ore with your ore when appropriate. | + | **Accessor Mixins** are special mixins defined as interfaces which must **only** contain |
| - | ==== Adding | + | The '' |
| - | In this section, our goal will be spawning the ore in the overworld. | + | |
| - | === Making a ConfiguredFeatures === | + | Unlike typical injectors, accessors do not prefix the merged methods with the modid of the mod that contains them. Additionally as the **Accessor Mixins** are used in user code, the names of the handlers are not mangled, these differences are important |
| - | First we need to create a ConfiguredFeatures. Make sure to register your ConfiguredFeature at '' | + | |
| - | <code java [enable_line_numbers=" | + | '' |
| - | public class ExampleMod implements ModInitializer { | + | Prefixing accessor or invoker handlers is not necessary if they are static, as those may not conflict, and the stacktrace provides the Mixin class whose handlers are involved in errors, thus making it sufficient without needing to prefix with the modid. |
| - | public | + | |
| - | .configure(new OreFeatureConfig( | + | |
| - | OreFeatureConfig.Rules.BASE_STONE_OVERWORLD, | + | |
| - | Blocks.NETHER_QUARTZ_ORE.getDefaultState(), | + | |
| - | 9)) // vein size | + | |
| - | | + | |
| - | 0, // bottom offset | + | |
| - | 0, // min y level | + | |
| - | 64))) // max y level | + | |
| - | | + | |
| - | .repeat(20); | + | |
| - | | + | ===== Accessor ===== |
| - | public | + | '' |
| - | | + | |
| + | ==== Getting a value from the field ==== | ||
| + | < | ||
| + | @Mixin(class_310.class) | ||
| + | public | ||
| + | @Accessor(" | ||
| + | int modid$getItemUseCooldown(); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Usage: | ||
| + | |||
| + | < | ||
| + | int field_1752 = ((class_310Accessor) class_310.method_1551()).modid$getItemUseCooldown(); | ||
| + | </ | ||
| + | |||
| + | ==== Setting a value to the field ==== | ||
| + | < | ||
| + | @Mixin(class_310.class) | ||
| + | public interface class_310Accessor | ||
| + | | ||
| + | void modid$setItemUseCooldown(int field_1752); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Usage: | ||
| + | |||
| + | < | ||
| + | ((class_310Accessor) class_310.method_1551()).modid$setItemUseCooldown(100); | ||
| + | </ | ||
| + | |||
| + | When the field is final and you need to set it, use '' | ||
| + | |||
| + | ===== Accessor for static fields ===== | ||
| + | FIXME // | ||
| + | Suppose we want to access the '' | ||
| + | |||
| + | ==== Getting a value from the field ==== | ||
| + | <code java> | ||
| + | @Mixin(VanillaLayeredBiomeSource.class) | ||
| + | public interface VanillaLayeredBiomeSourceAccessor { | ||
| + | @Accessor("BIOMES") | ||
| + | static List< | ||
| + | throw new AssertionError(); | ||
| } | } | ||
| } | } | ||
| </ | </ | ||
| - | === Registering the feature === | + | Usage: |
| - | Vanilla ore features that spawn in the overworld biomes are listed in '' | + | |
| - | <code java [enable_line_numbers=" | + | <code java> |
| - | @Mixin(DefaultBiomeFeatures.class) | + | List< |
| - | public | + | </ |
| - | @Inject(method = "addDefaultOres(Lnet/ | + | |
| - | | + | ==== Setting a value to the field ==== |
| - | | + | <code java> |
| + | @Mixin(VanillaLayeredBiomeSource.class) | ||
| + | public | ||
| + | @Accessor("BIOMES") | ||
| + | static void setBiomes(List< | ||
| + | | ||
| } | } | ||
| } | } | ||
| </ | </ | ||
| - | === Result === | + | Usage: |
| - | You should see quartz ore spawning in the overworld. You can use fill command to remove stone blocks surrounding you like this: ''/ | + | |
| - | {{tutorial: | + | <code java> |
| + | VanillaLayeredBiomeSourceAccessor.setBiomes(biomes); | ||
| + | </ | ||
| - | ==== Adding | + | When the field is final and you need to set it, use '' |
| - | In this section, based on the code in the previous section, we will add the ore to the end biomes. | + | |
| - | === Making a ConfiguredFeatures | + | ===== Invoker ===== |
| - | We replace | + | '' |
| - | <code java [enable_line_numbers=" | + | <yarncode |
| - | public | + | @Mixin(class_1560.class) |
| - | public | + | public |
| - | | + | |
| - | new BlockMatchRuleTest(Blocks.END_STONE), /* We use endstone! */ | + | |
| - | | + | } |
| - | 9)) | + | </yarncode> |
| - | | + | |
| - | 0, | + | Usage: |
| - | | + | |
| - | 64))) | + | < |
| - | | + | class_1560 enderman = ...; |
| - | .repeat(20); | + | ((class_1560Invoker) enderman).modid$invokeTeleportTo(0.0D, 70.0D, 0.0D); |
| + | </ | ||
| + | |||
| + | ===== Invoker for static methods ===== | ||
| + | FIXME //This example is not fully accurate to latest versions, '' | ||
| + | Suppose we want to invoke '' | ||
| - | | + | <code java> |
| - | public void onInitialize() { | + | @Mixin(BrewingRecipeRegistry.class) |
| - | | + | public |
| + | @Invoker(" | ||
| + | static | ||
| + | | ||
| } | } | ||
| } | } | ||
| </ | </ | ||
| - | === Registering the feature === | + | Usage: |
| - | Considering that no ore is generated in the end biomes on vanilla minecraft, '' | + | |
| - | <code java [enable_line_numbers="true"]> | + | <code java> |
| - | @Mixin(DefaultBiomeCreator.class) | + | BrewingRecipeRegistryAccessor.invokeRegisterPotionType(item); |
| - | public | + | </ |
| - | @Inject(method = "method_31065(Lnet/ | + | |
| - | | + | ==== Invoker for constructors ==== |
| - | | + | |
| - | } | + | Invokers for constructors must be static, pass '' |
| + | |||
| + | For example, we will use the '' | ||
| + | <code java> | ||
| + | @Mixin(Identifier.class) | ||
| + | public | ||
| + | @Invoker("< | ||
| + | static | ||
| + | throw new AssertionError(); | ||
| + | } | ||
| } | } | ||
| </ | </ | ||
| + | Usage: | ||
| + | <code java> | ||
| + | Identifier exampleVariable = IdentifierAccessor.newIdentifier(" | ||
| + | </ | ||
tutorial/mixin_accessors.1598714307.txt.gz · Last modified: 2020/08/29 15:18 by siglong