概述

一个流体,有着对应的桶是一件很正常的事情,这部分教程作者将带领读者一步一步地完成一个水银桶的制作、和注册。

流体桶的制作

还好,Minecraft提供了一个名为ItemBucket的类,我们只需要继承这个类就好了。在包com.github.ustc_zzzz.fmltutor.item下新建文件ItemBucketMercury.java

src/main/java/com/github/ustc_zzzz/fmltutor/item/ItemBucketMercury.java:

package com.github.ustc_zzzz.fmltutor.item;

import com.github.ustc_zzzz.fmltutor.block.BlockLoader;
import com.github.ustc_zzzz.fmltutor.creativetab.CreativeTabsLoader;

import net.minecraft.init.Items;
import net.minecraft.item.ItemBucket;

public class ItemBucketMercury extends ItemBucket
{
    public ItemBucketMercury()
    {
        super(BlockLoader.fluidMercury);
        this.setContainerItem(Items.bucket);
        this.setUnlocalizedName("bucketMercury");
        this.setCreativeTab(CreativeTabsLoader.tabFMLTutor);
    }
}

ItemBucket类的构造方法需要一个方块作为参数,这个方块当然就是对应的流体方块。

setContainerItem方法的作用是设置包含的物品,这样在合成等地方使用后,Minecraft可以识别出这个物品包含一个桶,并把桶留下。

模型和语言文件:

src/main/resources/assets/fmltutor/models/item/bucket_mercury.json:

{
    "parent": "builtin/generated",
    "textures": {
        "layer0": "fmltutor:items/bucket_mercury"
    },
    "display": {
        "thirdperson": {
            "rotation": [ -90, 0, 0 ],
            "translation": [ 0, 1, -3 ],
            "scale": [ 0.55, 0.55, 0.55 ]
        },
        "firstperson": {
            "rotation": [ 0, -135, 25 ],
            "translation": [ 0, 4, 2 ],
            "scale": [ 1.7, 1.7, 1.7 ]
        }
    }
}

src/main/resources/assets/fmltutor/lang/en_US.lang(部分):

item.bucketMercury.name=Mercury Bucket

src/main/resources/assets/fmltutor/lang/zh_CN.lang(部分):

item.bucketMercury.name=水银桶

因为教程编写者没有美工带来的不忍直视的材质:

src/main/resources/assets/fmltutor/textures/items/bucket_mercury.png:

bucket_mercury

一些例行公事:

src/main/java/com/github/ustc_zzzz/fmltutor/item/ItemLoader.java(部分):

    public static Item bucketMercury = new ItemBucketMercury();

src/main/java/com/github/ustc_zzzz/fmltutor/item/ItemLoader.java(部分):

    public ItemLoader(FMLPreInitializationEvent event)
    {
        register(goldenEgg, "golden_egg");
        register(redstonePickaxe, "redstone_pickaxe");
        register(redstoneApple, "redstone_apple");

        register(redstoneHelmet, "redstone_helmet");
        register(redstoneChestplate, "redstone_chestplate");
        register(redstoneLeggings, "redstone_leggings");
        register(redstoneBoots, "redstone_boots");

        register(bucketMercury, "bucket_mercury");
    }

    @SideOnly(Side.CLIENT)
    public static void registerRenders()
    {
        registerRender(goldenEgg);
        registerRender(redstonePickaxe);
        registerRender(redstoneApple);

        registerRender(redstoneHelmet);
        registerRender(redstoneChestplate);
        registerRender(redstoneLeggings);
        registerRender(redstoneBoots);

        registerRender(bucketMercury);
    }

现在游戏中应该出现了一个桶,并且可以倒出流体了。

注册这个流体桶

然而,现在一个负责处理流体桶的Mod,对于这个物品,还是有三点是未知的:

  • 这是一个用于盛放流体的桶
  • 这个桶盛放的流体是水银这个流体
  • 这个桶的容量正好是一个桶,也就是1000mB

Forge提供的FluidContainerRegistry类就是统一这种事情的,FluidContainerRegistry类提供了四个常用的注册流体容器的方法:

  • public static boolean registerFluidContainer(Fluid fluid, ItemStack filledContainer)
  • public static boolean registerFluidContainer(Fluid fluid, ItemStack filledContainer, ItemStack emptyContainer)
  • public static boolean registerFluidContainer(FluidStack stack, ItemStack filledContainer)
  • public static boolean registerFluidContainer(FluidStack stack, ItemStack filledContainer, ItemStack emptyContainer)

如果提供的第一个参数是Fluid类的实例对象,那么默认注册的流体容器大小为一个桶(也就是1000mB),如果是FluidStack,则按照FluidStack提供的来。 如果提供了emptyContainer参数,则表示这个流体容器有着空容器,否则没有(比如盛装了流体的IndustrailCraft2 Experimental的空流体单元)。

我们现在完成一下这个注册步骤:

src/main/java/com/github/ustc_zzzz/fmltutor/item/ItemBucketMercury.java:

package com.github.ustc_zzzz.fmltutor.item;

import com.github.ustc_zzzz.fmltutor.block.BlockLoader;
import com.github.ustc_zzzz.fmltutor.creativetab.CreativeTabsLoader;
import com.github.ustc_zzzz.fmltutor.fluid.FluidLoader;

import net.minecraft.init.Items;
import net.minecraft.item.ItemBucket;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidContainerRegistry;

public class ItemBucketMercury extends ItemBucket
{
    public ItemBucketMercury()
    {
        super(BlockLoader.fluidMercury);
        this.setContainerItem(Items.bucket);
        this.setUnlocalizedName("bucketMercury");
        this.setCreativeTab(CreativeTabsLoader.tabFMLTutor);
        FluidContainerRegistry.registerFluidContainer(FluidLoader.fluidMercury, new ItemStack(this),
                FluidContainerRegistry.EMPTY_BUCKET);
    }
}

现在看起来似乎没什么问题了。

解决游戏和流体桶交互的问题

其实,细心的读者可能已经发现了,现在游戏有着一个不易发现但是很致命的问题,就是如果在生存模式下使用一个空桶去盛装水银这个流体,会得到一个水桶,这显然不是我们想要的。

这是因为Minecraft中只认水和岩浆两种流体,这导致新添加的流体不会与对应的流体桶交互。我们这里监听一下桶被盛装的事件:

src/main/java/com/github/ustc_zzzz/fmltutor/common/EventLoader.java(部分):

    @SubscribeEvent
    public void onFillBucket(FillBucketEvent event)
    {
        BlockPos blockpos = event.target.getBlockPos();
        IBlockState blockState = event.world.getBlockState(blockpos);
        Fluid fluid = FluidRegistry.lookupFluidForBlock(blockState.getBlock());
        if (fluid != null && new Integer(0).equals(blockState.getValue(BlockFluidBase.LEVEL)))
        {
            FluidStack fluidStack = new FluidStack(fluid, FluidContainerRegistry.BUCKET_VOLUME);
            event.world.setBlockToAir(blockpos);
            event.result = FluidContainerRegistry.fillFluidContainer(fluidStack, event.current);
            event.setResult(Result.ALLOW);
        }
    }

现在看起来真的没什么问题了。

results matching ""

    No results matching ""