我的世界1.20.1模组开发---5.设置方块掉落物

发布时间 2023-11-01 16:49:47作者: 小明同学404

介绍

  正如这这节的标题一样,这次我们来设置方块的破坏掉落物。比如草方块被破坏后可以掉落泥土、石头被挖掉后会掉落原石、红石框被挖掉后会掉落红石和经验等等。我们可以在我们的mod中为我们的方块或矿物设置破坏后掉落物。

VanillaBlockLoot类

  我们想要设置方块的掉落物表,需要在对应的json文件中设置,这里我们仍然采用自动生成的方式获取我们的json文件。我们创建的类需要继承VanillaBlockLoot类这个类也是继承了更上一层的父类,我们只需要继承这个类就行。这个类里面写了原版方块的掉落物设置,所以我们大部分代码只需要在原版代码的基础上进行修改即可。

  我们只需要重写父类的generate()方法和getKnownBlocks()方法即可,我们只需要在generate()方法体中调用父类提供的add()方法和dropSelf()方法,就能实现方块掉落物的添加。

   //1
    protected void add(Block pBlock, Function<Block, LootTable.Builder> pFactory) {
      this.add(pBlock, pFactory.apply(pBlock));
   }
    //2
   protected void add(Block pBlock, LootTable.Builder pBuilder) {
      this.map.put(pBlock.getLootTable(), pBuilder);
   }

  我们先到源码中看一下add()方法,我们调用的是第一个方法,第一个参数是我们的方块;第二个参数是一个函数,这个函数的参数是Block类型返回值是一个LootTable.Builder类型,我们直接写Lambda表达式即可。add()方法的意思就是给我们的方块设置一个掉落物,掉落物由第二个参数的返回值设置,至于第二个参数怎么写,我们将参考原版的写法,后面再介绍。

   protected void dropOther(Block pBlock, ItemLike pItem) {
      this.add(pBlock, this.createSingleItemTable(pItem));
   }


   protected void dropSelf(Block pBlock) {
      this.dropOther(pBlock, pBlock);
   }

dropSelf()方法是设置方块被挖掉后掉落自己的,例如圆石挖掉后掉落的还是圆石这样的方块。进入源码后可以看到dropSelf()方法调用了dropOther()方法,但是dropOther()里面还是调用了add()方法。我们给被挖掉后掉落自己的方块使用dropSelf()方法就行了。

代码

  我们首先在我们mod的datagen包下创建一个ModLootTableGen类,这个类要继承VanillaBlockLoot类,并重写generate()方法和getKnownBlocks()方法,通过调用dropSelf()方法和add()方法为我们的方块设置对应的掉落物。

  下面上代码

public class ModLootTableGen extends VanillaBlockLoot {

    @Override
    protected void generate() {
        //这个方块破坏后掉落自己
        dropSelf(ModBlocks.BLUE_BLOCK.get());
        //这个方块破坏后掉落对应的矿石
        add(ModBlocks.BLUE_ORE.get(),(pBlock)->{
            return createBlueOreDrops(pBlock);
        });
    }

    //add方法的第二个参数的返回值,大部分照原版的写就行,只需要修改注释地方的参数即可
    protected LootTable.Builder createBlueOreDrops(Block pBlock) {
        return createSilkTouchDispatchTable(pBlock, 
                this.applyExplosionDecay(pBlock, 
                        LootItem.lootTableItem(ModItems.YUANSHI.get())//设置我们要破坏方块后掉落的物品
                                .apply(SetItemCountFunction.setCount(UniformGenerator.between(4.0F, 5.0F)))//设置物品的掉落数量范围
                                .apply(ApplyBonusCount.addUniformBonusCount(Enchantments.BLOCK_FORTUNE))));//受时运效果影响
    }

    //照这样写就行
    @Override
    protected Iterable<Block> getKnownBlocks() {
        return ForgeRegistries.BLOCKS.getEntries().stream()
                .filter(e->e.getKey().location().getNamespace().equals(Test1Mod.MOD_ID))
                .map(Map.Entry::getValue)
                .collect(Collectors.toList());
    }
}

  我们设置的第二个方块是一个矿石方块,破坏后会掉落经验(创建方块时已经设置过了)和对应的矿物,第二个参数我们传入一个Lambda表达式返回值通过调用createBlueOreDrops()方法获得,这个方法我们可以直接模仿原版红石矿的写法,只需要修改掉落的物品和物品数量以及是否受时运影响等配置即可。

  这个类写完后,我们还需要在数据生成的主类DataGenerators类里面添加我们的设置方块掉落物的类,具体写法就是这样子的,暂时写不论为什么这样写,记住就行了x.x。

        generator.addProvider(event.includeServer(), new LootTableProvider(output, Collections.emptySet(),
                List.of(new LootTableProvider.SubProviderEntry(ModLootTableGen::new, LootContextParamSets.BLOCK))));

  最后后我们执行RunData命令,系统会在src/generated/resources/data/modid/loot_tables_blocks目录下自动生成相应的json文件,之后就可以进入游戏测试了。

  下面就是在游戏中我们添加掉落物的方块,左边是矿物,右边是对应的矿物合成的方块。按我们的设置,左边的方块破坏后会掉落对应的矿物,右边的则掉落自己,下面我们就用稿子测试一下。

  哇塞,真的掉落了对应的矿物和方块了,是不是很神奇呢。