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! ! !