我的世界1.20.1模组开发---2.添加物品

  由于我也是一边学习一边研究的,这方面的资料还真不是太多,只能靠自己摸索了。由于模组开发内容过多,每一个部分都会单独的写一篇文章来介绍。大致的内容就是我会每次先介绍需要用到的几个类,详细介绍一下具体用法和作用,然后再介绍如何用这些类实现我们的目标。

FMLJavaModLoadingContext类

  这个类可以帮助我们获取Mod事件总线,官方并没有提供这种事件系统,这是Forge团队所提出的一种方案。Forge的事件总线为 IEventBus 接口的实现类,一般我们所用到的事件总线有两种:

  1. Forge总线:负责除了生命周期事件外的所有事件,在游戏运行过程中我们可以触发的事件。可通过 MinecraftForge.EVENT_BUS 获得
  2. Mod总线:主要负责游戏的生命周期事件,也就是初始化过程的事件,游戏未开始时需要进行的一写加载和操作等。可通过 FMLJavaModLoadingContext.get().getModEventBus() 获得。

因为我们是想添加物品,就必须在Mod总线中注册一下这个物品,告诉Minecraft运行游戏前要加载这个物品到游戏中。

        //获取Mod事件总线
        IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();

DeferredRegister类

  这个类可以让我们获得一个类似于注册表的对象,因为我们的Mod会添加很多的方块和物品,所以要通过一个专门的注册表来管理我们所添加的物品,将所有的物品都添加到这个注册表里。最后再将注册表添加到Mod事件总线中就可以把我们添加的物品都告诉游戏。我们可以通过类里面的creat方法创建一个对应物品的注册表。

  //方法原型
  public static <B> DeferredRegister<B> create(IForgeRegistry<B> reg, String modid)
  {
  return new DeferredRegister<>(reg, modid);
  }

  //获取物品的注册表 public static final DeferredRegister<Item> ITEMS= DeferredRegister.create(ForgeRegistries.ITEMS, Test1Mod.MOD_ID);//第一个参数是注册的物品的类型,第二个是MODID

  该方法需要传递两个参数,第一个参数是我们要注册的物品的类型,第二个参数就是我们的MOD_ID。

   IForgeRegistry类里面存放了各种我们所需要的注册类型,因为我们注册的是物品类,从里面获取Item类型即可。方法返回一个泛型为ItemDeferredRegister对象ITEMS,这个对象就是我们的注册表了,所有想添加的物品只需要放到这里面即可。

  我们获取到的注册表对象身上有一个register方法,可以向注册表中注册我们添加的物品

  //方法原型
  public <I extends T> RegistryObject<I> register(final String name, final Supplier<? extends I> sup) { ...... }

  //具体用法
  
//第一个参数数物品的name,对应于语言文件中的name值,贴图的名字要和这个name值一致,且贴图要放在指定位置
  public static final RegistryObject<Item>YUANSHI=ITEMS.register("yuanshi",()->new Item(new Item.Properties()));

  方法需要两个参数,第一个参数需要我们传入一个字符串,表示添加的物品的name值(尽量用小写字母表示,不要有特殊字符,后面还会用到),第二个参数需要我们传入一个Lambda表达式来返回对应类型的对象,因为我们是添加物品,需要返回一个Item对象,创建ITEM对象时我们就设置默认属性,例如上面代码写的那样。 

CreativeModeTab类

  顾名思义,这个类就是为我们模组添加的物品添加一个创造模式物品栏。原版中,每一种方块或者物品都有自己专属的分类栏,我们的每一个mod也有自己的物品栏,里面放着我们的所有物品,即我们添加的所有方块或物品都要放到这里面去。

   和添加物品一样,我们同样要获取一个对应的创造模式物品栏的注册表,将物品或方块注册到注册表里。

    //获取注册表
    public static final DeferredRegister<CreativeModeTab>CREATIVE_MODE_TABS=DeferredRegister.create(Registries.CREATIVE_MODE_TAB, Test1Mod.MOD_ID);
  这次获取的泛型理应也就变成了CreativeModeTab类型,获取注册表之后再调用他的register方法将物品注册进去即可。

正式开始

  添加物品需要的一些类我们都已经介绍完毕,下面就具体说明怎么在项目中写代码。

   首先和其他Java项目一样,我们先创建对应的包,一般都是com.yourName.modName的结构,接着在该包下新建item包用来存放我们的ModItems类,这个类用来添加我们的item;再创建一个ModCreativeModeTab类,用来把新增的物品放到创造模式物品栏里(这个类可以单独放到一个包里,这里我就直接放在item包下了)。

ModItems类代码

  这个类里面创建一个ITEM类的注册表,负责把各种物品注册到注册表里,再写一个对外的接口让Test1Mod主类里的Mod事件总线把注册表添加进去。下面上代码

package com.hmy.test1mod.item;

import com.hmy.test1mod.Test1Mod;
import com.hmy.test1mod.item.custom.EightBallItem;
import net.minecraft.world.item.Item;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;

//该类用于添加物品用
public class ModItems {

    //获取物品的注册表
    public static final DeferredRegister<Item> ITEMS= DeferredRegister.create(ForgeRegistries.ITEMS, Test1Mod.MOD_ID);//第一个参数是注册的物品的类型,第二个是MODID

    //开始注册物品(向注册表中注册物品)
    //第一个参数数物品的name,对应于语言文件中的name值,贴图的名字要和这个name值一致,且贴图要放在指定位置
    public static final RegistryObject<Item>YUANSHI=ITEMS.register("yuanshi",
            ()->new Item(new Item.Properties()));
    //添加第二个物品
    public static final RegistryObject<Item> JIUCHANZHIYUAN =ITEMS.register("jiuchanzhiyuan",
            ()->new Item(new Item.Properties()));
    //添加第三个物品
    public static final RegistryObject<Item> REDSWORD =ITEMS.register("redsword",
            ()->new Item(new Item.Properties()));
   //......
//后面再添加物品和上面的写法一样
//对外暴露的接口,在主类中将注册表添加到事件总线上 public static void register(IEventBus eventBus){ ITEMS.register(eventBus); } }

ModCreativeModeTab类代码

  这个类里面负责把ModItems类里新增的物品添加到创造模式物品栏注册表里,同样获取一个注册表把新增物品注册到里面,再写一个对外的接口让Test1Mod主类里的Mod事件总线把注册表添加进去。

package com.hmy.test1mod.item;

import com.hmy.test1mod.Test1Mod;
import com.hmy.test1mod.block.ModBlocks;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.RegistryObject;

//这个类用来将物品放到创造模式物品栏里
public class ModCreativeModeTab {
    public static final String TEST1_TAB_STRING="creativetab.test1_tab";

    //获取注册表
    public static final DeferredRegister<CreativeModeTab>CREATIVE_MODE_TABS=
            DeferredRegister.create(Registries.CREATIVE_MODE_TAB, Test1Mod.MOD_ID);
   
    public static final RegistryObject<CreativeModeTab>TEST1_TAB=CREATIVE_MODE_TABS.register("test1_tab",
            ()-> CreativeModeTab.builder()
                    .icon(()->new ItemStack(ModItems.YUANSHI.get()))//设置mod物品栏的图标
                    .title(Component.translatable(TEST1_TAB_STRING))//设置mod物品栏的标题
                    //开始向物品栏里添加我们新增的物品
                    .displayItems((pParameters, pOutput) -> {
                        pOutput.accept(ModItems.YUANSHI.get()); //用get方法获取对应的参数传进去
                        pOutput.accept(ModItems.JIUCHANZHIYUAN.get());
                        pOutput.accept(ModItems.REDSWORD.get());
                    })
                    .build());//构建完成
  

   //对外接口方法,让主类注册用 public static final void register(IEventBus eventBus){ CREATIVE_MODE_TABS.register(eventBus); } }

  这里面的register方法的第二个参数也是用Lambda表达式返回CreativeModeTab的对象,并设置一些对应的属性。具体就先照着上面的代码写就可以。

主类代码

  主类里要获取总线,并将其他注册表放到总线里。

package com.hmy.test1mod;

import com.hmy.test1mod.block.ModBlocks;
import com.hmy.test1mod.item.ModCreativeModeTab;
import com.hmy.test1mod.item.ModItems;
import com.mojang.logging.LogUtils;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.BuildCreativeModeTabContentsEvent;
import net.minecraftforge.event.server.ServerStartingEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import org.slf4j.Logger;


@Mod(Test1Mod.MOD_ID)
public class Test1Mod
{
    public static final String MOD_ID = "test1mod";//mod_id
    private static final Logger LOGGER = LogUtils.getLogger();//暂时不用管
    public Test1Mod()
    {
        //获取事件总线
        IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();

        //将获取到的mod总线通过这个方法将ModItems里的注册表加到总线里
        ModItems.register(modEventBus);
     //创造模式物品栏注册表放到总线了 ModCreativeModeTab.register(modEventBus);
     //这个是添加方块用的,后面会介绍 ModBlocks.register(modEventBus); modEventBus.addListener(
this::commonSetup); MinecraftForge.EVENT_BUS.register(this); }
  //下面的方法暂时用不到,不用管
private void commonSetup(final FMLCommonSetupEvent event) {} private void addCreative(BuildCreativeModeTabContentsEvent event) {} @SubscribeEvent public void onServerStarting(ServerStartingEvent event) {} @Mod.EventBusSubscriber(modid = MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) public static class ClientModEvents { @SubscribeEvent public static void onClientSetup(FMLClientSetupEvent event) {} } }

   这几步完成后我们就可以在创造模式下看到我们自己添加的物品栏和对应的物品了。但是不是像我这样有贴图的,这是我设置好贴图和材质后的样子。完成上面这些操作后未设置贴图后的物品只是一堆马赛克,后面一篇文章我们就会将如何设置物品的贴图。

posted @ 2023-10-18 12:00  小明同学404  阅读(1690)  评论(0)    收藏  举报