Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

[1.16.1] The Book of Minecraft Modding - complete guide for beginners


Recommended Posts

10 hours ago, diesieben07 said:

Unfortunately most modding tutorials are written by amateurs, who don't even come here to ask for feedback before posting it as just "the way to do it" on Youtube, etc.

As prior amateur, I can attest to this. Currently, I am trying to improve my skills and knowledge by being active on these forms and verifying all of what I want to say. I believe the only tutorials currently recommended are those by McJty. If you need help on a problem that you cannot deconstruct by yourself, you should always turn to the forms or the forge discord.

Link to comment
Share on other sites

  • 3 weeks later...
5 hours ago, Marconium2 said:

when you create your RegistryHandler class, it would have been helpful if you showed what you put in the import ...;   section. It took me quite a while to figure out what to import.

Do you not have an IDE that does this for you? You should never have to manually worry about imports except in very special corner cases.

  • Like 1
Link to comment
Share on other sites

You just give me the inspiration to do the same (of course as soon as I know more about forge and complex stuff😅).


package com.example.examplemod;

import ...;

public class RegistryHandler {
    // create DeferredRegister object
    public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, ExampleMod.MODID);

    public static void init() {
        // attach DeferredRegister to the event bus

    // register item
    public static final RegistryObject<Item> COPPER = ITEMS.register("copper", () ->
            new Item(
                    new Item.Properties().group(ItemGroup.MATERIALS)


    public static void init() {
        // attach DeferredRegister to the event bus


Personally I register this here in the constructor of my main class, just confirm. And to keep everything organized, I create a class for every DeferredRegister (e.g. the Item DeferredRegister is in a class called "ModItems" and there are all my items), I do this for every DeferredRegister I use, but this is just a small detail and everybody has the freedom to do what he wants. (I register the bus in my mainclass constructor and separate the items from the blocks, the blocks from the potions etc.)

I also wanted to ask (I know that 99.99% doesn't respect this anyway, but you should always do it) that you tell the readers on the start page that they should know Java first. As I said before, 99.99% of people don't read it and start right away, they get an error and ask you directly:


- some guy: "Some kind of generic error", hey you! Can you please solve it for me directly? I don't understand anything about generics…

- You: Have you at least learned Java?

(The answer is already: NO)

So you could also just the recommend readers java tutorials in the same way as cadiboo it did (bad english, srry):

Last question:

How did you create such a website? And do you pay to host it?

I am interested in it myself (as I said before) and don't know if I should program my own website or rather use a website generator like: Github Beautiful Jekyll.  Just asking (and I think it's one of the few website tutorials, though not the only one that supports DarkTheme. Sorry, but this is something to celebrate).


Hope these tips will help you (sorry if it's a bit long)

I would use a DataGenerator instead of doing this manually. If you want a tutorial about the DataGenerator:

Edited by FrostDracony
  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...
5 hours ago, chuckster. said:

works fine up until RegistryHandler.init();. Comes up with init as red error, and RegistryHandler as depreciated with a cross through it. please help, cant find any solutions about it online.

You should make your own thread in the Modder Support forum and show your code.

Link to comment
Share on other sites

Hey Could somebody here tell me how to make hostile mobs and make custom models for them and stuff I am a really big noob to this and know pretty much nothing I didnt really try and make one myself since i will most likely mess a lotta stuff up so i would really appreciate some help.

Edit: Also im Using 1.16

Edited by JabberWocky234
Unclarified Point
Link to comment
Share on other sites

  • 7 months later...

Thanks for this tutorial. I built a mod years ago and am trying to get back into it.

Correct me if I'm wrong, but it looks like in 1.16.5, Item.Properties().group is now .tab(), and vanilla ItemGroup categories are now given in the form TAB_MATERIALS, TAB_MISC etc.

Link to comment
Share on other sites

3 hours ago, Yawny420 said:

Correct me if I'm wrong, but it looks like in 1.16.5, Item.Properties().group is now .tab(), and vanilla ItemGroup categories are now given in the form TAB_MATERIALS, TAB_MISC etc.

For the official mappings yes. This tutorial uses MCP mappings so it is also correct. You will need to translate them into your mapping set used.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing

    No registered users viewing this page.

  • Posts

    • Thanks for the help everybody! I tried this and although the block did register, the fluid just appears as a flat plane you can only see if you break the block under it. I tried debugging it as much as I could but alas I couldn't solve it Here is the code for my "fixed" liquidblock as suggested by Luis_ST: package com.hotmail.majdroaydi.minitech.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.sounds.SoundEvent; import net.minecraft.tags.FluidTags; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.LiquidBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.FlowingFluid; import net.minecraft.world.level.pathfinder.PathComputationType; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; import java.util.Optional; import java.util.function.Supplier; public class ForgeLiquidBlock extends LiquidBlock { public ForgeLiquidBlock(Supplier<? extends FlowingFluid> supplier, Properties properties) { super(supplier, properties); } @Override public VoxelShape getCollisionShape(BlockState p_54760_, BlockGetter p_54761_, BlockPos p_54762_, CollisionContext p_54763_) { return p_54763_.isAbove(STABLE_SHAPE, p_54762_, true) && p_54760_.getValue(LEVEL) == 0 && p_54763_.canStandOnFluid(p_54761_.getFluidState(p_54762_.above()), getFluid()) ? STABLE_SHAPE : Shapes.empty(); } @Override public boolean isPathfindable(BlockState p_54704_, BlockGetter p_54705_, BlockPos p_54706_, PathComputationType p_54707_) { return !getFluid().is(FluidTags.LAVA); } @Override public boolean skipRendering(BlockState p_54716_, BlockState p_54717_, Direction p_54718_) { return p_54717_.getFluidState().getType().isSame(getFluid()); } @Override public void onPlace(BlockState p_54754_, Level p_54755_, BlockPos p_54756_, BlockState p_54757_, boolean p_54758_) { if (this.shouldSpreadLiquid(p_54755_, p_54756_, p_54754_)) { p_54755_.getLiquidTicks().scheduleTick(p_54756_, p_54754_.getFluidState().getType(), getFluid().getTickDelay(p_54755_)); } } @Override public BlockState updateShape(BlockState p_54723_, Direction p_54724_, BlockState p_54725_, LevelAccessor p_54726_, BlockPos p_54727_, BlockPos p_54728_) { if (p_54723_.getFluidState().isSource() || p_54725_.getFluidState().isSource()) { p_54726_.getLiquidTicks().scheduleTick(p_54727_, p_54723_.getFluidState().getType(), getFluid().getTickDelay(p_54726_)); } //return super.updateShape(p_54723_, p_54724_, p_54725_, p_54726_, p_54727_, p_54728_); return p_54723_; // Calling super.updateShape will just call LiquidBlock's updateShape, not what we are looking for! Thankfully, Block.updateShape, simply enough, just returns the first parameter. } @Override public void neighborChanged(BlockState p_54709_, Level p_54710_, BlockPos p_54711_, Block p_54712_, BlockPos p_54713_, boolean p_54714_) { if (this.shouldSpreadLiquid(p_54710_, p_54711_, p_54709_)) { p_54710_.getLiquidTicks().scheduleTick(p_54711_, p_54709_.getFluidState().getType(), getFluid().getTickDelay(p_54710_)); } } private boolean shouldSpreadLiquid(Level p_54697_, BlockPos p_54698_, BlockState p_54699_) { if (getFluid().is(FluidTags.LAVA)) { boolean flag = p_54697_.getBlockState(p_54698_.below()).is(Blocks.SOUL_SOIL); for(Direction direction : POSSIBLE_FLOW_DIRECTIONS) { BlockPos blockpos = p_54698_.relative(direction.getOpposite()); if (p_54697_.getFluidState(blockpos).is(FluidTags.WATER)) { Block block = p_54697_.getFluidState(p_54698_).isSource() ? Blocks.OBSIDIAN : Blocks.COBBLESTONE; p_54697_.setBlockAndUpdate(p_54698_, net.minecraftforge.event.ForgeEventFactory.fireFluidPlaceBlockEvent(p_54697_, p_54698_, p_54698_, block.defaultBlockState())); this.fizz(p_54697_, p_54698_); return false; } if (flag && p_54697_.getBlockState(blockpos).is(Blocks.BLUE_ICE)) { p_54697_.setBlockAndUpdate(p_54698_, net.minecraftforge.event.ForgeEventFactory.fireFluidPlaceBlockEvent(p_54697_, p_54698_, p_54698_, Blocks.BASALT.defaultBlockState())); this.fizz(p_54697_, p_54698_); return false; } } } return true; } private void fizz(LevelAccessor p_54701_, BlockPos p_54702_) { p_54701_.levelEvent(1501, p_54702_, 0); } @Override public ItemStack pickupBlock(LevelAccessor p_153772_, BlockPos p_153773_, BlockState p_153774_) { if (p_153774_.getValue(LEVEL) == 0) { p_153772_.setBlock(p_153773_, Blocks.AIR.defaultBlockState(), 11); return new ItemStack(getFluid().getBucket()); } else { return ItemStack.EMPTY; } } @Override public Optional<SoundEvent> getPickupSound() { return getFluid().getPickupSound(); } } The code for my OilFluid can be found above.
    • Whoops! Sorry, my fault. But yes, a block entity (tile entity in 1.16-) *is* needed for storing data (i.e. furnace). But I think what OP is doing is making an item combiner, which doesn't need one
    • Looking to work with reliable Fabric & Forge developers to produce original mods for use on my YouTube channel! We'll be regularly working together and you'll be given a detailed brief for each commission that outlines exactly what I want. From there, you can give me a price that fits the scope of the project and we can get to work :thumbsup: Because these commissions are only for YouTube videos, you're essentially making vertical-slices / proof-of-concepts. They can have bugs, you can take shortcuts & we can use video editing to hide bugs & achieve some effects. With that in mind, turnaround speed depends on project complexity but for an average commission I'd expect delivery two days - five days Send me a email at either lmaololtbhhonest@gmail.com OR Business@tbhhonest.com if you're interested! preview of channel: https://imgur.com/a/bOVkiUo LINK:  https://www.youtube.com/channel/UCnwo3X3eCrUp7N1DZPc-MGQ  
    • If you want a tiny fraction of offset, use float.epsilon. 0.01 will actually be noticeable. It's about 1/6th of a texture pixel.
  • Topics

  • Who's Online (See full list)

  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.