概述
一个流体,有着对应的桶是一件很正常的事情,这部分教程作者将带领读者一步一步地完成一个水银桶的制作、和注册。
流体桶的制作
还好,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:
一些例行公事:
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);
}
}
现在看起来真的没什么问题了。