本篇教程由作者设定未经允许禁止转载。


前言

自版本1.9.4开始的NTM支持使用crafttweaker对一些机器配方进行魔改。


官方wiki见github页面的CraftTweakerWIKI.md


*所有配方都无法使用IIngredient类型,不能使用" | "对多个物品匹配。(其本质上还是IIngredient类型)


装配机

导包:

import mods.ntm.Assembler;

添加配方:(版本1.9.7无效)1.9.8及以后版本已修复

mods.ntm.Assembler.addRecipe(IItemStack 输出, IItemStack[] 多个输入, int 持续时间tick);
mods.ntm.Assembler.addRecipe(<minecraft:apple>, [<minecraft:iron_ingot> * 2, <minecraft:gold_ingot>], 100);

    *由于装配机配方使用HashMap进行存储,而key使用产物的物品栈而非配方名,故产物不能重复(即物品id与数量、meta、nbt不能均相同),否则最终加载的只是最后一个生成该产物的配方。

删除配方:

mods.ntm.Assembler.removeRecipe(IItemStack 输出);  //需匹配物品数量
mods.ntm.Assembler.removeRecipe(<minecraft:apple>);


增殖

导包:

import mods.ntm.BreedingReactor;

添加配方:

mods.ntm.BreedingReactor.addRecipe(IItemStack 输入, IItemStack 输出, int 热量需求);  //热量需求须在1~4
mods.ntm.BreedingReactor.addRecipe(<minecraft:apple>, <minecraft:gold_ingot>, 2);

删除配方:

mods.ntm.BreedingReactor.removeRecipe(IItemStack 输入);
mods.ntm.BreedingReactor.removeRecipe(<minecraft:apple>);

添加燃料:

mods.ntm.BreedingReactor.addFuel(IItemStack 输入, int 热量, int 可用次数);  //热量须在1~4,可用次数须大于等于1
mods.ntm.BreedingReactor.addFuel(<minecraft:apple>, 4, 3);

删除燃料:

mods.ntm.BreedingReactor.removeFuel(IItemStack 输入);
mods.ntm.BreedingReactor.removeFuel(<minecraft:apple>);


离心机

导包:

import mods.ntm.Centrifuge;

添加配方:

mods.ntm.Centrifuge.addRecipe(IItemStack 输入, IItemStack[] 多个输出);  //输出的物品栈不能多于四个
mods.ntm.Centrifuge.addRecipe(<minecraft:apple>, [<minecraft:iron_ingot> * 2, <minecraft:iron_ingot> * 2, <minecraft:iron_ingot> * 2, <minecraft:gold_ingot>]);

删除配方:

mods.ntm.Centrifuge.removeRecipe(IItemStack 输入);
mods.ntm.Centrifuge.removeRecipe(<minecraft:apple>);


DFC钨箱

导包:

import mods.ntm.DFC;

添加配方:

mods.ntm.DFC.addRecipe(IItemStack 输入, IItemStack 输出, long Spk);
mods.ntm.DFC.addRecipe(<minecraft:apple>, <minecraft:iron_ingot>, 100);

删除配方:

mods.ntm.DFC.removeRecipe(IItemStack 输入);
mods.ntm.DFC.removeRecipe(<minecraft:apple>);


RBMK辐照通道

导包:

import mods.ntm.IrradiationChannel;

添加配方:

mods.ntm.IrradiationChannel.addRecipe(IItemStack 输入, IItemStack 输出, int 中子通量);
mods.ntm.IrradiationChannel.addRecipe(<minecraft:apple>, <minecraft:iron_ingot>, 100);

删除配方:

mods.ntm.IrradiationChannel.removeRecipe(IItemStack 输入);
mods.ntm.IrradiationChannel.removeRecipe(<minecraft:apple>);


粉碎机

导包:

import mods.ntm.Shredder;

添加配方:

mods.ntm.Shredder.addRecipe(IItemStack 输入, IItemStack 输出);
mods.ntm.Shredder.addRecipe(<minecraft:apple>, <minecraft:iron_ingot>);

删除配方:

mods.ntm.Shredder.removeRecipe(IItemStack 输入);
mods.ntm.Shredder.removeRecipe(<minecraft:apple>);


激光同位素分离

导包:

import mods.ntm.SILEX;

添加配方:

mods.ntm.SILEX.addRecipe(int 激光类型, int 酸化产生溶液mB, int 每次配方消耗溶液mB, IItemStack 输入
, IItemStack[] 多个输出, int[] 多个输出概率%);
//激光类型在1~8,依次为无线电、微波、红外线、可见光、紫外线、X射线、Y射线、迪Y射线
//流体的数量均须小于等于16000,输出物品栈的个数须小于等于6,输出概率数须与输出物品栈数相同且相加等于100
mods.ntm.SILEX.addRecipe(2, 900, 100, <minecraft:apple>, [<minecraft:apple>, <minecraft:apple>, <minecraft:apple>
, <minecraft:apple>, <minecraft:apple>, <minecraft:apple>], [20, 20, 20, 20, 10, 10]);

*其实激光类型输入0也是可以的,但是它不属于任何一种激光,名字是"la creatura"。作者写在后面的注释是:why do you exist?

删除配方:

mods.ntm.SILEX.removeRecipe(IItemStack 输入);
mods.ntm.SILEX.removeRecipe(<minecraft:apple>);


乏燃料池

导包:

import mods.ntm.WasteDrum;

添加配方:

mods.ntm.WasteDrum.addRecipe(IItemStack 输入, IItemStack 输出);  //输入输出物品个数均只能为1
mods.ntm.WasteDrum.addRecipe(<minecraft:apple>, <minecraft:iron_ingot>);

*目前无法删除配方


高炉

导包:

import mods.ntm.BlastFurnace;

添加配方:

mods.ntm.BlastFurnace.addRecipe(IItemStack 输入1, IItemStack 输入2, IItemStack 输出);
mods.ntm.BlastFurnace.addRecipe(<minecraft:apple>, <minecraft:iron_ingot>, <minecraft:gold_ingot>);

删除配方:(版本1.9.7无效,其他版本未测试,解决方法见最下)

mods.ntm.BlastFurnace.removeRecipe(IItemStack 输入1, IItemStack 输入2);  //需匹配物品数量
mods.ntm.BlastFurnace.removeRecipe(<minecraft:apple>, <minecraft:iron_ingot>);

添加燃料:

mods.ntm.BlastFurnace.addFuel(IItemStack 输入, int 燃烧时间tick);  //燃烧时间须在1~12800之间
mods.ntm.BlastFurnace.addFuel(<minecraft:apple>, 200);

删除燃料:

mods.ntm.BlastFurnace.removeFuel(IItemStack 输入);
mods.ntm.BlastFurnace.removeFuel(<minecraft:apple>);


化工厂

导包:

import mods.ntm.Chemplant;

添加配方:(模板紫黑块警告,和之前的装配机一模一样的问题,模型无法加载,解决方法有空再想,咕

mods.ntm.Chemplant.addChemplantRecipe(int 数字ID, String 配方名, IItemStack[] 输入, String[] 流体输入, int[] 输入流体量
, IItemStack[] 输出, String[] 流体输出, int[] 输出流体量, int 持续时间);
mods.ntm.Chemplant.addChemplantRecipe(373, "TEST_NAME", null, ["steam", "oil"], [800, 200]
, [<minecraft:boat>], ["water", "lava"], [500, 600], 100);

    *数字ID不能与现有配方相同,现有配方的数字ID为对应模板的meta值(通过F3+H可查看)

    *配方名为大写英文字母、数字、下划线的组合,不能有空格。

    *流体使用字符串和整数进行表示,而不是通常的ILiquidStack相当有风格其中字符串为流体的注册名,即ILiquidStack表示中 "liquid:" 后面的内容;整数为流体量,单位为mB。

    **化工厂的模板需要提供材质和本地化名,本地化名可以通过更改lang文件指定(格式为 chem.配方名=本地化名;例:chem.KEVLAR=凯夫拉生产);材质分为两部分,json格式的模型与png格式的贴图。推荐使用ResourceLoader模组处理本地化与材质,具体操作参考该模组教程在此不过多赘述。

    **但是!由于模组代码问题,就算添加了与现有配方相同格式的模型与贴图文件,实际上也不会加载。

删除配方:

mods.ntm.Chemplant.removeChemplantRecipe(int 数字ID);
mods.ntm.Chemplant.removeChemplantRecipe(370);


流体加热

导包:

import mods.ntm.FluidHeating;

添加配方:

*热量TU仅影响使用热量体系的多方块锅炉,单方块锅炉的工作温度与输出流体的温度属性一致。(配合ILiquidDefinition食用更佳)

//加热配方
mods.ntm.FluidHeating.addBoilRecipe(String 流体输入, int 输入流体量, String 流体输出, int 输出流体量, int 吸收热量TU);
mods.ntm.FluidHeating.addBoilRecipe("oil", 10, "lava", 10, 800);
//冷却配方
mods.ntm.FluidHeating.addCoolRecipe(String 流体输入, int 输入流体量, String 流体输出, int 输出流体量, int 放出热量TU);
mods.ntm.FluidHeating.addCoolRecipe("lava", 10, "oil", 10, 600);
//同时添加加热与冷却(熵:请好好地看着我)
mods.ntm.FluidHeating.addBoilAndCoolRecipe(String 冷流体, int 冷流体量, String 热流体, int 热流体量, int 吸/放热量TU);
mods.ntm.FluidHeating.addBoilAndCoolRecipe("oil", 10, "lava", 10, 700);

删除配方:

//加热配方
mods.ntm.FluidHeating.removeBoilRecipe(String 流体输入);
mods.ntm.FluidHeating.removeBoilRecipe("water");
//冷却配方
mods.ntm.FluidHeating.removeCoolRecipe(String 流体输入);
mods.ntm.FluidHeating.removeCoolRecipe("hot_coolant");


流体燃料

导包:

import mods.ntm.FluidCombustion;

添加配方:

mods.ntm.FluidCombustion.addBurnableFluid(String 流体输入, int 热值TU/mB);
mods.ntm.FluidCombustion.addBurnableFluid("water", 20);

删除配方:

mods.ntm.FluidCombustion.removeBurnableFluid(String 流体输入);
mods.ntm.FluidCombustion.removeBurnableFluid("gasoline");


进阶(?)

高炉无法删除配方的解决方法:(需要构建模组)

问题原因推测(未证实):默认配方使用矿辞进行添加,而删除配方仅检测配方列表是否有符合的物品栈,故而找不到要删除的配方。

解决方法:直接在源代码里删配方,相关代码在src/main/java/com/hbm/inventory/DiFurnaceRecipes.java。


修改代码使装配机的添加配方函数支持矿辞输入(要求对编程有基础知识)

不支持矿辞本来不是什么大问题,但装配机无法拥有多个产物相同的配方,这使得部分喜欢魔改的玩家及整合包制作者难以发挥。由于要改的代码量比较大,故此处仅提供思路。

hbm对于材料的表示均位于类RecipesCommon中,为材料栈AStack,以及两个派生类:物品栈ComparableStack与矿辞栈OreDictStack;

我们需要用到的crt对于材料的表示为材料IIngredient,及其派生类物品栈IItemStack,矿辞IOreDictEntry与材料栈IngredientStack。

注意,形如“<ore:*>”为矿辞IOreDictEntry,而形如“<ore:*> * 2”为材料栈IngredientStack而不是矿辞。

魔改实现过程为从zs的材料表示方法翻译为crt的材料表示方法,再翻译为hbm的材料表示方法,最后得以在机器上正确运行。

要做的修改即把类Assembler.ActionAddRecipe中的成员inputs的类型由ComparableStack[]改为AStack[]以适配OreDictStack类型,把原本输入的IItemStack[]改为IIngredient[]以适配IngredientStack与IOreDictEntry类型,并根据输入的IIngredient参数动态类型的不同将其翻译为hbm所使用的ComparableStack或者OreDictStack。

值得注意的是在把IngredientStack翻译为OreDictStack时,你会发现没有合适的接口函数帮你获取矿辞的名称。我们所写的脚本如“<ore:*> * 2”会被翻译为一个由IOreDictEntry与int所构成的IngredientStack类型,而IOreDictEntry可以获取矿辞名称,但它是私有成员,所以需要使用forge中的函数ObfuscationReflectionHelper.getPrivateValue(类,该类对象,String 成员名)来强行访问。


咕咕,爽!