MinecraftFabric Mod Development Complete Process 4 – Customized Item Blocks, Food, and Fuel

Table of Contents

    • Custom Items and Blocks
      • Auto Detect Ore Deposit Tool
        • tool function
        • accomplish
        • Results of the
      • custom music box
      • custom food
      • custom fuel

Custom items and blocks

Automatically detect mineral deposits tool

Detector texture download address: https://url.kaupenjoe.net/mbkj57/assets

As we all know, serious people never like conventional mining methods. It would be great if there was a custom tool for detecting mineral deposits underfoot~
Next, we will implement the tool step by step

Tool function

Durability 64, right-click on the block to use it. Each use will destroy a point of durability regardless of whether the mineral deposit is found or not.

The right-clicked block will explore 128 blocks downwards. If there is iron or diamond ore, it will be reported to the player in the chat box.
Otherwise, if it cannot be found, a failure message will be output.

Achieving

First create a separate custom folder to store our customized items

Create a new class MetalDetectorItem.java. The specific location can be seen in the picture below.

The main code is as follows, I believe you can understand it!

Tips: Use the alt + insert shortcut key to quickly add a constructor.

package com.example.item.custom;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
import net.minecraft.util.math.BlockPos;

import java.util.Objects;

//extends inherits the parent class Item
public class MetalDetectorItem extends Item {<!-- -->

    // Don't forget the constructor
    public MetalDetectorItem(Settings settings){<!-- -->
        super(settings);
    }

    // When an item is used on a block (i.e. right click on the block)
    @Override
    public ActionResult useOnBlock(ItemUsageContext context) {<!-- -->
        // if client
        if(!context.getWorld().isClient()){<!-- -->
            // Get the block position and player position, and initialize the foundBlock variable to determine whether the block is found
            BlockPos posClicked = context.getBlockPos();
            PlayerEntity player = context.getPlayer();
            boolean foundBlock = false;

            //According to the block coordinates, survey 128 blocks downward based on the Y axis
            // posClicked.down(i) means that the current coordinates are i cells downward
            for(int i=0;i<=posClicked.getY() + 128;i + + ){<!-- -->
                // Get the corresponding block states one by one
                BlockState state = context.getWorld().getBlockState(posClicked.down(i));
                // Determine the status of the block and output success information if it meets the conditions.
                if(isTargetBlock(state)){<!-- -->
                    assert player != null;
                    outputTargetBlockCoordinates(
                            posClicked.down(i),
                            player,
                            state.getBlock()
                    );
                    foundBlock=true;
                    break;
                }
            }

            // If nothing is found, output a failure message
            if(!foundBlock){<!-- -->
                assert player != null;
                player.sendMessage(
                        Text.literal("No Target Ore Found!!!")
                );
            }

            // Finally, don’t forget to add 1 loss to the item held by the player (that is, my detector)
            context.getStack().damage(1, Objects.requireNonNull(context.getPlayer()), player1 -> {<!-- -->
                player1.sendToolBreakStatus(player1.getActiveHand());
            });
        }
        return ActionResult. SUCCESS;
    }

    // Function to detect whether the specified block is iron ore or diamond ore
    private boolean isTargetBlock(BlockState state){<!-- -->
        return state.isOf(Blocks.IRON_ORE) || state.isOf(Blocks.DIAMOND_ORE);
    }

    // Function to output mine coordinates
    private void outputTargetBlockCoordinates(BlockPos blockPos, PlayerEntity player, Block block){<!-- -->
        player.sendMessage(
                Text.literal("Target Ore:" + block.asItem().getName().getString() + " at (" + blockPos.getX() + "," + blockPos.getY() + "," + blockPos .getZ() + ")"),
                false
        );
    }
}

Execution results

Custom music box

Like custom items, we create a new custom folder to store custom blocks

Create a custom music box block SoundBlock.java according to the position shown in the figure below

The code of the music box is very simple, that is, right click once to make a sound

Code Listing SoundBlock.java

package com.example.block.custom;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;

public class SoundBlock extends Block {<!-- -->
    public SoundBlock(Settings settings) {<!-- -->
        super(settings);
    }

    // onUse is right click
    @Override
    public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {<!-- -->
        // Play a sound at the player's location
        world.playSound(player, pos, SoundEvents.BLOCK_NOTE_BLOCK_BASS.value(), SoundCategory.BLOCKS,1f,1f);
        return ActionResult.SUCCESS;
    }
}

Note, when we register this block in ModBlocks, don’t manually specify the sounds, otherwise it will cause the sound playback to fail!

This is how to write the registration box

public static final Block SOUND_BLOCK = regBlock("sound_block",
            new SoundBlock(FabricBlockSettings. copyOf(Blocks. WHITE_WOOL)));

Customized food

Tomato texture download: https://url.kaupenjoe.net/mbkj61/assets

We’re going to make a tomato that has a certain effect when eaten

Create a new class AwfulTomatoFood.java to represent our food

code listing

package com.example.item.food;

import net.minecraft.command.argument.NbtCompoundArgumentType;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.item.FoodComponent;
import net.minecraft.item.FoodComponents;
import net.minecraft.nbt.NbtCompound;

public class AwfulTomatoFood {<!-- -->
    //Define a food, use FoodComponent.Builder
    public static final FoodComponent AWFUL_TOMATO = new FoodComponent.Builder()
            // Supplementary hunger value
            .hunger(2)
            //Set the saturation (that is, consume the saturation before the hunger value starts to decrease)
            .saturationModifier(0.25f)

            // Add the potion effect after eating
            // Parameter 1: potion effect, parameter 2: probability of obtaining the effect
            .statusEffect(new StatusEffectInstance(StatusEffects.POISON,200),0.5f)
            .statusEffect(new StatusEffectInstance(StatusEffects.INSTANT_DAMAGE,1),0.25f)

            // You can also eat when the hunger bar is full
            .alwaysEdible()
            //Can be fed to dogs
            .meat()
            //Specify that the food is a snack, and you will eat it very quickly (about half the time it takes to eat ordinary food)
            .snack()
            .build();
}

When registering, do not use this class directly like you did before to register custom items! Please follow the code below to register

Code Listing ModItems.java

// To explicitly tell the compiler that you need to register a food, use FabricItemSettings().food()
public static final Item AWFUL_TOMATO_FOOD = regItem("awful_tomato",
        new Item(new FabricItemSettings().food(AwfulTomatoFood.AWFUL_TOMATO)));

Custom fuel

Defining fuel is very simple, just define it just like defining ordinary items.

Code Listing ModItems.java

package com.example.item;

import com.example.TutorialMod;
import com.example.item.custom.MetalDetectorItem;
import com.example.item.food.AwfulTomatoFood;
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroupEntries;
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
import net.fabricmc.fabric.api.registry.FuelRegistry;
import net.minecraft.item.Item;
import net. minecraft. registry. Registries;
import net.minecraft.registry.Registry;
import net.minecraft.util.Identifier;


public class ModItems {<!-- -->

    ...

    //Define fuel items
    public static final Item COAL_BRIQUETTE = regItem("coal_briquette",
            new Item(new FabricItemSettings()));

    private static Item regItem(String name,Item item){<!-- -->
        return Registry.register(Registries.ITEM,new Identifier(TutorialMod.MOD_ID,name),item);
    }

    public static void registerModItems(){<!-- -->
        TutorialMod.LOGGER.debug("TutorialMod is registering Items, MOD_ID: " + TutorialMod.MOD_ID);

        // Use FuelRegistry to register fuel here
        // Parameter 1: The name of the fuel to be registered
        // Parameter 2: Fuel calorific value (200 is the time to smelt an item in a common furnace, and this time is proportional to the blast furnace)
        FuelRegistry.INSTANCE.add(ModItems.COAL_BRIQUETTE,200);
    }
}

There is a key concept to understand here

The second parameter received by FuelRegistry.INSTANCE.add should be understood as the calorific value of the fuel, that is, 200 is a standard value, which can smelt an item;
Similarly, in a blast furnace, since the calorific value is fixed, it is still only enough to smelt one item;
It should not be understood as the burning time, otherwise moving into the blast furnace will be twice the smelting time, which is obviously wrong! ! !