Background
Minecraft vanilla flowers are actually implemented in a somewhat tricky way. Basically there are two flower types called "yellow" and "red" even though there are many more flowers than that. Yellow flowers are basically just dandelions and all other are considered "red" flowers. Yellow and red have separate registry entries and then red uses a type property to called EnumFlowerType to further distinguish.
Tip: While it is tempting to follow the same structure for your custom flower(s), I suggest taking a "flat" approach where you don't use a property but rather create a separate class for each flower type. This makes the coding easier and also is in line with the upcoming Flattening effort in 1.13. I take this approach and therefore I recommend to extend BlockBush rather than BlockFlower.
I have created an example mod on GitHub that contains many of my tutorial techniques. You can reference code examples from that repository. You are free to copy my code according to the license, but please make sure you understand the code -- don't just copy!
Once you've created the flower itself, you'll want to make a world generator to associate with your biome.
Steps To Create A Custom Flower
Here are some recommended steps:
- Create flower class: Create a custom flower class that extends BlockBush.
- Create an "init" class for blocks: This is recommended to collect all your registration code and @ObjectHolder injection. In this class you can do all of the following:
- Register the flower block: Create a method to handle the RegistryEvent.Register
method with @ObjectHolder annotation. - Register the associated flower ItemBlock: Create a method to handle the RegistryEvent.Register
- method with @ObjectHolder annotation.
- Register the block model. Use the ModelRegistryEvent to register your block model.
- Register the item model. Use the ModelRegistryEvent to register your item model.
- Create your asset files:
- Create your blockstate JSON asset file, named to match your registry name and located in proper location in your resources directory.
- Create your block model JSON asset file, named to match your blockstate reference name and located in proper location in your resources directory.
- Create your item model JSON asset file, named to match your blockstate reference name and located in proper location in your resources directory.
- Create your flower texture PNG asset file, named to match your model reference name and located in proper location in your resources directory.
- Create your flower recipe JSON asset file(s), named to match your registry name and located in proper location in your resources directory.
- Create localization: Add an entry in your .lang files for localization.
- Optionally register in Ore Dictionary.
- Create a generator class: Make a new class that extends WorldGenerator and @Overrides the generate() method to place your custom flower.
- Associate generator with biome decorator.
Create A Custom Flower Block Class
Simply extend BlockBush with a simple class.
See example code.
Create An Init Class To Collect Registration Code
I recommend making a class called something like ModBlocks to collect all the registration and instantiation related to blocks. (You should do similar for your items, and other custom things that require registration.)
Create methods that are @SubscribeEvent annotated to handle the RegistryEvent.Register and RegistryEvent.Register events along with @ObjectHolder annotation to register your block.
Warning: Make sure your block's registry name exactly matches the blockstate JSON filename as well as the @ObjectHolder injection name.
Create methods that handle the ModelRegistryEvent to register the block and item models.
See example code.
Create Your Related Asset Files
You need to have a properly organized asset directory with exact names matching the registry name and/or references between files. You will need a:
- Blockstate JSON. Make sure the file name exactly matches the registry name. Note that you need to handle both grow STAGE variants. See example code.
- Block model JSON. Make sure the file name exactly matches the model path in your blockstate file. See example code.
- Item model JSON. Make sure the file name exactly matches the model path in your blockstate file. See example code.
- Recipe JSONs. See example code.
- Texture PNG. Make sure the file name exactly matches the resource path in your model file. See example file.
Create Localization Entry In Your .lang File
To support multiple languages, your blocks and items have an "unlocalized name" which then uses a .lang file to get translated into supported language. See Jabelar's localization tutorial for more information on this.
So you should add entries to your localization files for the names of your flowers. See example code.
Optionally Add Ore Dictionary Registration
The Ore Dictionary is a Forge hook to try to allow mods to interwork with equivalent recipe ingredients. However, as the recipe system has been changing along with feature changes like recipe book and the upcoming 1.13 tag system, the Ore Dictionary is currently not really fully working.
You can find out more about the Ore Dictionary in Jabelar's Ore Dictionary tutorial.
Warning: Ore Dictionary is in flux due to evolving recipe, the Flattening effort, and upcoming tagging systems. I can't entirely recommend it at this time.
If you do want to go ahead with Ore Dictionary, you can register after the @ObjectHolder injection. Therefore I recommend doing your registration in the init handling method of your mod.
Assuming you want your flower to generate naturally, you'll want to create a custom world generator. This is simply done by extending WorldGenerator and implementing the generate() method. I'd copy most of the code from the code from the vanilla flower generator but of course place your block instead.
See example code.
If you want to add your flowers to vanilla biomes, you should handle the DecorateBiomeEvent and test for EventType.FLOWERS and call your generate() method accordingly.
If you have a fully custom biome then you should call the generate() function of your generator class from a method such as genFlowers() in your custom BiomeDecorator class. See example code.
You should test that your flower works by doing the following:
Create A Class That Extends WorldGenerator
Assuming you want your flower to generate naturally, you'll want to create a custom world generator. This is simply done by extending WorldGenerator and implementing the generate() method. I'd copy most of the code from the code from the vanilla flower generator but of course place your block instead.
See example code.
Associate Your Generator With Your BiomeDecorator
If you want to add your flowers to vanilla biomes, you should handle the DecorateBiomeEvent and test for EventType.FLOWERS and call your generate() method accordingly.
If you have a fully custom biome then you should call the generate() function of your generator class from a method such as genFlowers() in your custom BiomeDecorator class. See example code.
Testing
You should test that your flower works by doing the following:
- Review your console log to ensure there are not any errors related to missing assets.
- In a creative mode world, check that your flower displays properly in the creative tab.
- Plant the flower in a suitable location.
- Test that bone meal will make it grow faster.
- Test that you can get any recipe results in a crafting table.
Conclusion
As always, please leave comments if you find any issues with the tutorial. Happy modding!
Does this work with other biomes in the over-world? For example in the Jungle I want my "Bromeliad" to spawn, and to spawn specifically there how would you go about doing that?
ReplyDelete