1962 字
10 分钟
CraftTweaker使用教程
CraftTweaker(以下简称CrT)是由麦穗开发与同名的Java版模组有类似功能的魔改类模组。
本文将简要介绍如何编写和使用CrT脚本。
加载脚本
CrT在运行时会读取当前加载模组集对应文件夹下script文件夹内的所有后缀为js的文件并为每一个脚本创建独立的沙盒以独立运行。
你可以在包对应文件夹内的innercore/preferences.json文件中的pack_selected键对应的属性得知当前所加载的模组集对应的路径,无论如何,script文件夹都应与mods文件夹在同一级文件夹内。
//可能放置脚本的文件夹//mod_pack_name/script/编写脚本
编程语言
与ICMod一样,CrT脚本使用Rhino引擎运行,语言为JavaScript,支持ES5与部分ES6特性。
预置函数
CrT为CrT脚本提供了两个预置函数,分别为$和require,下文将分别介绍这两个函数的详细用法:
$
$用于创建ItemStack对象,是CrT和ICMod通用的物品格式。
格式:
// $ 的格式如下$("type:name:data*count");/* type - ID的类型,分为方块 - block 和 物品 - item * name - ID的名称,如bedrock, stick等 * data - 物品的特殊值/损坏值(可选) * count - 物品的数量(可选) *///举例:$("block:bedrock"); //基岩$("block:wool:6*32"); //半组粉红色羊毛$("item:stick*64"); //一组木棍$("item:diamond_shovel:1560"); //一把快要坏掉的钻石锹
// ItemStack 对象包含的值如下{ index: string, //索引,即ID的名称 id: number, //物品的数字ID data: number, //物品的特殊值/损坏值 count: number, //物品的数量 _condition: function, //合成条件,物品在工作台中参与合成时执行,详见下文}用法:
// ItemStack 对象有以下方法toItem(); //返回 toItem 对象,详见下文toBlock(); //返回 toBlock 对象,详见下文onUse(state); // state - function 类型,为物品注册使用回调(点击方块时触发),返回该 ItemStack 自身getMaxStack(); //返回 number 类型,该物品的最大堆叠数量only(state); // state - function 类型,合成条件,详见下文,返回该 ItemStack 自身transformDamage(damage); // damage - number 类型,设置物品在合成时增加的损坏值(或指消耗的耐久值),仅调用该方法而不传入参数将设置为1,返回该 ItemStack 自身reuse(); //设置该物品在合成中不会消耗,返回该 ItemStack 自身
// toItem 对象有以下方法getMaxDamage(); //返回 number 类型,该物品的最大特殊值/损坏值isTool(); //返回 boolean 类型,该物品是否为工具(包含武器,装备等)
// toBlock 对象有以下方法onPlace(state); // state - function 类型,为方块注册放置回调,返回该 toBlock 自身getTileID(); //返回 number 类型,该方块的数字ID(范围[0, 2048])
//回调相关示例,合成相关示例见下文
//极为经典的铁剑点地爆炸,因为在CrT所创建的沙盒中无法使用CEAPI,因此使用Rhino提供的调用Java的功能直接调用Java方法$("item:iron_sword").onUse(function (coords, item, block, isExternal, player) { com.zhekasmirnov.innercore.api.NativeAPI.explode(coords.x, coords.y, coords.z, 10, true);});
//在基岩上放置基岩时爆炸$("block:bedrock").toBlock().onPlace(function (coords, item, block, player, region) { let pos = coords.relative; if (!region.getBlock(pos.x, pos.y, pos.z).id) { region.setBlock(pos.x, pos.y, pos.z, $("block:bedrock").id, 0); if (block.id === $("block:bedrock").id) { region.explode(pos.x, pos.y + 1, pos.z, 100, false); } }});require
require可用于获取CrT的自定义API,在没有其他模组添加API的情况下,默认可获取的API有furnace和recipes
格式:
require("api_name"); //返回 api_name 对象用法:
//因为一般情况下只需要获取一次API对象,而且没有修改名称的必要,故赋值为常量const Furnace = require("furnace"); //CrT预置的熔炉类const Recipes = require("recipes"); //CrT预置的合成类下面将详细介绍furnace和recipes的详细用法
furnace
//我们已经获取到了 furnace 对象并赋值给 Furnace,为方便,下文均使用 Furnace
// Furnace 有三条函数可用Furnace.remove(input); // input - ItemStack 类型,输入物品,移除某物品的熔炉配方Furnace.addRecipe(input, output); // input - ItemStack 类型,输入物品,output - ItemStack 类型,输出物品,添加一条熔炉配方Furnace.setFuel(input, time); // input - ItemStack 类型,燃料物品,time - number 类型,燃烧时间,设置某物品作为燃料的燃烧时间
//举例:Furnace.remove($("block:iron_ore")); //移除铁矿石的熔炉配方Furnace.addRecipe($("item:rotten_flesh"), $("item:leather")); //经典的腐肉烧皮革Furnace.setFuel($("block:hay_block"), 900); //将干草块设置为燃料,燃烧时间为4.5个物品
//注:200燃烧时间为一个物品recipes
//同上,下文均使用Recipes//至此,我们可以说明上文的一些“详见下文”了
// Recipes 有三条函数可用Recipes.remove(output); // output - ItemStick 类型,输出物品,移除某物品的合成配方Recipes.addShaped(output, input); // output - ItemStack 类型,输出物品,input - array 类型,包含输入物品的二维数组,添加有序合成Recipes.addShapeless(output, item); // output - ItemStack 类型,输出物品,input - array 类型,包含输入物品的一维数组,添加无序合成
//举例://移除工业模组中铜块合成配方(该函数在目前版本的IC暂不可移除原版合成配方)Recipes.remove($("block:blockCopper"));
/* 添加基岩的合成配方,摆放方式如下所示 * ABA * BAB * ABA * 其中 A 代表黑曜石,B 代表石头 */Recipes.addShaped($("block:bedrock*3"), [[$("block:obsidian"), $("block:stone"), $("block:obsidian")], [$("block:stone"), $("block:obsidian"), $("block:stone")], [$("block:obsidian"), $("block:stone"), $("block:obsidian")]]);//你可以像下面这样写成多行以便阅读Recipes.addShaped($("block:bedrock*3"), [ [$("block:obsidian"), $("block:stone"), $("block:obsidian")], [$("block:stone"), $("block:obsidian"), $("block:stone")], [$("block:obsidian"), $("block:stone"), $("block:obsidian")]]);
//对于不需要放物品的格子,留空或者填null即可/* 添加用石头合成石镐的合成配方,摆放方式如下所示 * AAA * B * B * 其中 A 代表石头,B 代表木棍 *///如果你有够强迫症可以写这样(虽然对于强迫症我更建议写到一行,眼不见心不烦)Recipes.addShaped($("item:stone_pickaxe"), [ [$("block:stone"), $("block:stone"), $("block:stone")], [null , $("item:stick") , null ], [null , $("item:stick") , null ]]);
//添加有不被消耗物品的合成//使用铁锭和海洋之心合成三叉戟,其中海洋之心可以重复使用Recipes.addShaped($("item:trident"), [[$("item:iron_ingot"), $("item:iron_ingot"), $("item:iron_ingot")], [null, $("item:heart_of_the_sea").reuse(), null], [null, $("item:iron_ingot"), null]]);
//添加无序合成与有序合成的方式十分相像,而且在添加输入物品时可以设置数量(有序合成则只能设置输出物品的数量),但要注意的是输入物品的总数不能超过9个//截止至V1.1.0版本的CrT,有设置输入物品数量的配方会有部分物品不会消耗的BUG
//为蘑菇煲添加两条合成配方,使其只需要任意两个蘑菇即可合成Recipes.addShapeless($("item:mushroom_stew"), [$("block:brown_mushroom"), $("block:brown_mushroom"), $("item:bowl")]);Recipes.addShapeless($("item:mushroom_stew"), [$("block:red_mushroom"), $("block:brown_mushroom"), $("item:bowl")]);
//添加消耗物品耐久的配方//使用毒马铃薯合成马铃薯,并消耗剪刀1耐久值//特殊值-1代表任意特殊值均可Recipes.addShapeless($("item:potato"), [$("item:shears:-1").transformDamage(), $("item:poisonous_potato")]);
//自定义合成事件//使用水桶与爆裂紫颂果合成紫颂果,并返还桶Recipes.addShapeless($("item:chorus_fruit"), [$("item:chorus_fruit_popped"), $("item:water_bucket").only(function (api, index, item, output) { item.id = $("item:bucket").id;})]);
//木板与剪刀合成随机1-4根木棍并消耗剪刀相应的耐久值Recipes.addShapeless($("item:stick"), [$("block:planks"), $("item:shears:-1").only(function (api, index, item, output) { let count = Math.floor(Math.random() * 4) + 1; let max = $("item:shears").toItem().getMaxDamage(); item.data += count; if (item.data >= max) { count += max - item.data; item.id = item.data = item.count = 0; } output.count = count;})]);模组联动
如果你是模组开发者,你可以通过ModAPI调用CrT提供的方法来拓展CrT
//CrT有以下方法可以通过ModAPI调用addAPI(name, state); // name - string 类型,API名称,state - object 类型,API对象,像CrT添加自定义API以在脚本中使用require(name); // name - string 类型,API名称,同上文requirerequireGlobal(command); // command - string 类型,要执行的代码,在CrT的中执行一段代码,慎用好了,你已经学会如何使用CrT了,快去试着制作整合包吧!
CraftTweaker使用教程
https://fuwari.vercel.app/posts/crafttweaker/