工具、武器、护甲与食物

我们在先前的章节中创建了一个没用的物品,那这一节就来创建一些有用的物品。


工具与武器

Minecraft有铁剑、金剑、钻石剑,但是却偏偏没有绿宝石剑。因此,我在这里将会以绿宝石剑为例,教读者打造工具与武器。

与先前一样,创建一个常量。

public static final RegistryObject<Item> EMERALD_SWORD = ITEMS.register("emerald_sword", () -> {
    return new SwordItem(...);
});

可以发现,我们这次不再是new Item()了,而是new SwordItem()了。要求填入的参数也不止Properties了,而是(IItemTier tier, int attackDamageIn, float attackSpeedIn, Item.Properties builder),后三个参数你应该知道是什么意思,如果不知道填什么的可以参阅源代码 (提示:按住Ctrl,试试点击相关的类),那我们就着重讲解第一个——ItemTier

通过参阅源代码,我们可以发现,原版的工具都是填入ItemTier.<material>。而ItemTier是个枚举类。因此,我们如果想添加自己的ItemTier,只能模仿ItemTier,自己继承IItemTier接口,写一个与ItemTier一样的枚举类。

因此,我参照了原版的ItemTier,自己写了一个枚举类,代码如下。

src/main/java/xyz/bzstudio/modderguide/item/MGItemTier.java

public enum MGItemTier implements IItemTier {
    EMERALD(3, 2333, 7.0F, 2.0F, 9, () -> Ingredient.fromItems(Items.EMERALD));

    private final int harvestLevel;
    private final int maxUses;
    private final float efficiency;
    private final float attackDamage;
    private final int enchantability;
    private final LazyValue<Ingredient> repairMaterial;

    MGItemTier(int harvestLevelIn, int maxUsesIn, float efficiencyIn, float attackDamageIn, int enchantabilityIn, Supplier<Ingredient> repairMaterialIn) {
        this.harvestLevel = harvestLevelIn;
        this.maxUses = maxUsesIn;
        this.efficiency = efficiencyIn;
        this.attackDamage = attackDamageIn;
        this.enchantability = enchantabilityIn;
        this.repairMaterial = new LazyValue<>(repairMaterialIn);
    }

    @Override
    public int getMaxUses() {
        return this.maxUses;
    }

    @Override
    public float getEfficiency() {
        return this.efficiency;
    }

    @Override
    public float getAttackDamage() {
        return this.attackDamage;
    }

    @Override
    public int getHarvestLevel() {
        return this.harvestLevel;
    }

    @Override
    public int getEnchantability() {
        return this.enchantability;
    }

    @Override
    public Ingredient getRepairMaterial() {
        return this.repairMaterial.getValue();
    }
}

然后,自行将代码补充完毕,再加入模型与材质,我们的绿宝石剑就做好了,打开游戏试试吧!
绿宝石剑


护甲

护甲的创建与工具、武器类似,但在材质方面还是比较特殊

例如,我们已经按创建工具、武器的方法创建好了一个绿宝石头盔。但如果读者尝试把它戴在头上时,会发现戴着的只是一个紫黑块
护甲材质无法显示

那这样怎么解决呢?读者可以浏览一下assets/minecraft/textures/models/armor下的图片,就会明白为什么玩家只会戴着紫黑块了。

我们可以看到,在该目录下的图片都是以<material_name>_layer_<1/2>.png的方式命名的,其中<material_name>就是读者创建ArmorMaterial的时候填入的参数name。其余的部分读者应该自己可以搞懂。

但当我们打开游戏,会发现我们的材质还是没有正常显示。让我们翻阅日志,就会发现这样一句话:

[22:00:13] [Render thread/WARN] [minecraft/TextureManager]: Failed to load texture: minecraft:textures/models/armor/emerald_layer_1.png

想必读者应该明白了:Minecraft并没有到我们自己的资源包目录下加载贴图。换言之,就是我们没有指定材质的命名空间。因此,我们只需要将<material_name>改为<modid>:<material_name>即可解决问题

或许,读者还可以将其写进枚举类的getName()方法,以后就不用手动添加modid了。

src/main/java/xyz/bzstudio/modderguide/item/MGArmorMaterial.java (部分)

@OnlyIn(Dist.CLIENT)
public String getName() {
    return ModderGuide.MODID + ":" + this.name;
}

打开游戏,就可以看到我们的护甲材质已经正常显示出来了。
image2


食物

Minecraft中有蘑菇煲、兔肉煲、甜菜根汤,为什么就没有鱼肉汤?因此,下文以鱼肉汤为例,教读者制作食物。

首先,就是食物的实例,只是一个普通的Item

public static final RegistryObject<Item> FISH_SOUP = ITEMS.register("fish_soup", () -> {
    return new Item(new Item.Properties().group(ItemGroup.FOOD).food(...));
});

我们可以看到,食物相比普通物品,不仅指定了group,还指定了food。通过参考Minecraft源代码,我们发现,原版食物填入的是Foods.<food>。因此,我们也仿照Minecraft的方式,添加一个food

public static final Food FISH_SOUP = (new Food.Builder()).hunger(8).saturation(0.6F).build();

hunger指饱食度,saturation则是饱和度。关于饱和度,不懂的读者可以参阅以下内容:

食物饱和度(foodSaturationLevel):它表示玩家目前的饱和度等级,决定了饥饿度下降的速度,吃不同种类的食物补充的饱和度不同。这是一项隐藏的食物变量,这个变量的值是无法超过食物水平的,其初始值为5。当饱和度降至0时,饥饿条会规律地颤抖。

原文:Minecraft Wiki

实际上,Food不仅可以指定食物的饱食度,还可以指定吃完食物后玩家获得的药水效果等,这些由读者自己摸索

再添加模型、材质,我们的食物就做好了,先打开游戏试试吧!

一些细节性问题

虽然我们的鱼肉汤做好了,但还是有一个细节,就是当玩家食用完鱼肉汤时,并不会把碗还给玩家。显然,我们喝汤不可能把碗也一起吃下去。因此,我们要覆写onItemUseFinish(...)方法,在玩家食用完鱼肉汤时,还给玩家一个碗。

Minecraft中已经有一个类覆写好了,那就是SoupItem,我们只需要将物品实例中的new Item(...)换成new SoupItem(...)即可。

启动游戏,当我们把食用完鱼肉汤后,就会自动把碗还给我们了。

results matching ""

    No results matching ""