Minecraft 1.12.2 Mod开发笔记——新的合成表、烧炼规则和燃料
新的合成表
在这之前,合成表使用 GameRegistry.addShapedRecipe()
创建,但从 1.12 开始,Minecraft 使用 json 文件创建合成表。Forge 会自动加载在 resources/assets/mymod/recipes/ 下的 json 合成表文件。现在我们来给之前的 Cross Block 创建合成表。
有序合成表
新建目录 resources/assets/mymod/recipes/,新建文件 cross_block.json,文件名无所谓,使用对应产物的名字比较方便。里面写入:
{
"type": "minecraft:crafting_shaped",
"group": "mymod:cross",
"pattern": [
"A B",
" C ",
"B A"
],
"key": {
"A": {"item": "minecraft:redstone"},
"B": {"item": "minecraft:sugar"},
"C": {"item": "minecraft:dirt","data": 0}
},
"result": {"item": "mymod:cross_block","count": 1}
}
-
type 分为有序合成
minecraft:crafting_shaped
和无序合成minecraft:crafting_shapeless
-
group 合成分组,比如各种颜色的床属于同一组,它们的合成表会合并在一起,可省略
-
pattern 有序合成时的材料顺序,排成两行或三行,用空格表示空,随便一种字母/符号表示一种材料
-
key 规定 pattern 中自定义字母代表的材料,如果限定 meta 信息,需要使用 data 键。例如,原版的各种台阶是一个方块的不同 meta 信息的结果,设置了 data 键后,只有特定的台阶才能参与这个合成,否则任何台阶均可参与合成。
-
如果有替代材料,使用列表形式,如:
"key": { "A": [{"item": "minecraft:redstone"}, {"item": "minecraft:sugar"}] }
-
result 产物,但有 meta 信息的产物 data 键是必须的
-
count 产物数量,默认为1,可省略
无序合成表
我们再给铁板添加无序合成表:
新建文件 iron_plate.json,写入:
{
"type": "minecraft:crafting_shapeless",
"result": { "item": "mymod:iron_plate", "count": 18 },
"ingredients": [
{ "item": "minecraft:iron_block" },
{ "item": "minecraft:iron_block" }
]
}
- ingredients 用于无序合成的原料设置
- 其他比如 result/type/group/count 同上
新的烧炼规则
Forge 并没有统一的把各种 recipe 整合到一起,烧炼规则仍然使用 GameRegistry 来添加。在 common 包中新建 Recipes.java,统一管理烧炼和燃料:
public class Recipes {
public Recipes(){
GameRegistry.addSmelting(BlockLoader.cross, new ItemStack(Items.IRON_AXE), 0.5F);
}
}
这里我们设置了一个奇怪的规则:Cross Block 燃烧生成铁斧。
CommonPorxy.java 的 init()
中添加:
new Recipes();
在 GameRegistry.addSmelting(input, output, exp)
中
- input 可以是 Block/Item/ItemStack
- output 是一个 ItemStack
- exp 是烧炼后获得的经验值。具体数值大概没必要计较,原版的数值设定参照 net/minecraft/item/crafting/FurnaceRecipes.java
新的燃料
之前,燃料需要使用 FurnaceRecipes 类管理,不过现在,Forge 将燃料问题整合成了一个事件,修改 Recipes.java 为:
@Mod.EventBusSubscriber
public class Recipes {
public Recipes(){
GameRegistry.addSmelting(BlockLoader.cross, new ItemStack(Items.IRON_AXE), 0.5F);
}
@SubscribeEvent
public static void getVanillaFurnaceFuelValue(FurnaceFuelBurnTimeEvent event) {
if(event.getItemStack().getItem() == Item.getItemFromBlock(BlockLoader.cross)){
event.setBurnTime(200);
}
}
}
- 当有物品尝试放进燃料槽时触发这个事件
event.getItemStack().getItem()
放进去的物品,物品可以直接使用 instanceof 判断物品种类,方块可以用Item.getItemFromBlock()
来判断event.setBurnTime()
用于设置燃烧时间,设置0表示不是燃料,设置为-1表示根据原版内容判断(默认)- 经查看源码发现,Minecraft 设定的值中,原版的煤是16000,烧8个物品,也就是说烧1个物品为200,这样就可以根据需要进行设置了。
- 当然也提供了
event.getBurnTime()
获取当前设置的燃烧时间 - 原版的燃料燃烧时间参照 net/minecraft/tileentity/TileEntityFurnace.java 的
getItemBurnTime()
(353行)