这是啥

是一个CrT教程,也是一个编程入门教程。

这个教程中,我们将会完成一些十分cool的事情!


你只需要会添加、删除合成表就行了,最好能够借助其它教程看懂各种模组机器的合成表操作。

另外,最好学会在游戏里使用/ct syntax和/ct hand。


读完这篇教程,你仍然应该频繁地访问docs.blamejared.com,这篇教程也会让你学会如何阅读wiki(待类型章节写完)。


变量

排列组合大师

似乎用木棍和圆石可以组合出很多东西呢……
但是一遍一遍打<minecraft:cobble_stone>似乎很折磨。即使复制粘贴也很糟糕。

var cs=<minecraft:cobble_stone>;
var st=<minecraft:stick>;
recipes.addShaped(<minecraft:stone_pickaxe>,[
    [cs,cs,cs],
    [null,st,null],
    [null,st,null]]);
recipes.addShaped(<minecraft:stone_axe>,[
    [cs,cs,null],
    [cs,st,null],
    [null,st,null]]);



变~

变量自然是可以变的:

var mat=<minecraft:cobble_stone>;
var st=<minecraft:stick>;
recipes.addShaped(<minecraft:stone_pickaxe>,[
    [mat,mat,mat],
    [null,st,null],
    [null,st,null]]);
mat=<minecraft:iron_ingot>;
recipes.addShaped(<minecraft:iron_pickaxe>,[
    [mat,mat,mat],
    [null,st,null],
    [null,st,null]]);

看起来好像没什么用……
但是实际上,变量可以是数字,有七十二变。
现在我们做的似乎都是静态的东西,似乎不需要会变的家伙。
但是这个程序马上就可以动起来了(?)


常量

好吧,上文的正确写法有点吃内存。
我们理应把var cs改成val cs。不过如果你写了val mat=xxx;
后面就不能再让mat=一个新的东西了,因为val说明mat是不会变化的常量。

但是这也是杯水车薪



循环、数组

数字循环

高斯的小学数学老师

众所周知,1+2+3+...+100=5050。

但是高斯的“小学数学老师”似乎并不知道这一点。

那么我们来描述一下高斯的小学数学老师的计算方法吧:

var sum=0;
for i in 1 to 101{
    sum=sum+i;
}
print(sum); //输出到crafttweaker.log

sum:和,数字的和。

zenscript里,i in a to b(a和b都是整数)时,i会依次取a, a+1, a+2, ... , b-1,但不会取b



热力膨胀的齿轮

热力膨胀有很多齿轮,拥有十分愚蠢的合成表,比如为什么银齿轮不能用来暴击吸血鬼?
所以我们 一定要删掉 这些合成表。

你需要知道:

    <xx:yy>.definition.makeStack(i)就是<xx:yy>这个物品下metadata为i的家伙。

    比如说<thermalfoundation:material>.definition.makeStack(258)就是银齿轮,也可以表示成<thermalfoundation:material:258>

    但是如果i是一个变量,你不能直接写<thermalfoundation:material:i>。


经过观察,热力齿轮的id都是thermalfoundation:material,metadata分为几串:

    22~27,256~264,288~295

那么我们写3个循环就好:

for i in 22 to 28{
    recipes.remove(<thermalfoundation:material>.definition.makeStack(i));
}
for i in 256 to 265{
    recipes.remove(<thermalfoundation:material>.definition.makeStack(i));
}
for i in 288 to 296{
    recipes.remove(<thermalfoundation:material>.definition.makeStack(i));
}




数组

什么是数组?大概就是一串同类型的东西吧。
比如说无序合成表的输入就是IIngredient的数组。


构建一个空数组,类型为xxx,使得它里面什么都没有:var a=[] as xxx[];

构建一个有a,b,c的数组,类型为xx: var s=[a,b,c] as xxx[];

访问数组里的元素:s[0],在上文里就是a。

注:数组的下标从0开始。

在数组的末尾追加新的元素:s+=d;



80个粒

为什么是80个粒?因为这是一种手动刷矿物的方法。用极限工作台合成铁块能够增产很合理吧!?呐?
空位必须在中间!

但是如果不想要代码里出现80个<minecraft:iron_nugget>呢?即使是val Fe_n=<minecraft:iron_nugget>然后出现80个Fe_n,也不能接受!

不过呢,极限工作台的输入是IIngredient[][],一个二维数组。
换句话说,是一个数组,里面的每一项都是一个IIngredient[]。

val n=<minecraft:iron_nugget> as IIngredient;
val a=[n,n,n,n,n,n,n,n,n] as IIngredient[];
val b=[n,n,n,n,null,n,n,n,n] as IIngredient[];
mods.avaritia.ExtremeCrafting.addShaped("Iron Duplication",<minecraft:iron_block>,[a,a,a,a,b,a,a,a,a]);


看起来还行?我们换种写法,这次和之前的循环一起写。

val t=[] as IIngredient[][];
for i in 0 to 9{
    t+=[] as IIngredient[];
    for j in 0 to 9{
        t[i]+=<minecraft:iron_nugget>;
    }
}
t[4][4]=null;
mods.avaritia.ExtremeCrafting.addShaped("Iron Duplication",<minecraft:iron_block>,t);

懂?



斑斓花是16色羊毛

如果没有花药台怎么合成斑斓花比较合理呢?
在符文祭坛聚合16个不同颜色的羊毛!
别问符文祭坛哪来。

var wools = [] as crafttweaker.item.IIngredient[];
for i in 0 to 16{
    wools+=<minecraft:wool>.definition.makeStack(i);
}
mods.botania.RuneAltar.addRecipe(<botania:specialflower>.withTag({type: "spectrolus"}),wools,2000);





列表:别人家的数组

数组有的时候不是我们搞出来的,而是别人给我们的。

比如说一个物品item的所有矿辞并在一起就是一个类似于数组的玩意,用item.ores得到。


列表和数组的区别在于,列表的内部结构比较复杂。故此我们不能像数组一样用[i]访问。
不过我们可以用 for 穷举列表里的每一个元素!



让熔炉不会烧粉!

首先,furnace.all返回所有的熔炉合成表。其次,i作为一个熔炉合成表,i.input表示它的输入原料,i.output表示输出原料。
然后,我们会检查输入物品是否有“xxxdustyyy”的矿物词典。方法是使用上文说的item.ores。
最后,一个字符串st,st.toLowerCase().contains("dust")表示:
    把st所有大写字母换成小写之后,有"dust"这连续的4个字母

for i in furnace.all{                                                    //can can need 合成表
    for j in i.input.ores{                                              //can can need 矿辞
        if(j.name.toLowerCase().contains("dust")){      //你是!你是!
            furnace.remove(i.output,i.input);                //送你离开
            break;                                                          //下一个
        }
    }
}



冶炼炉的流体污染

1.12.2的EnderIO有一个合金,叫做铁合金,十分的离谱。大概是往合金炉里放置了乱七八糟的东西就会变成这玩意。
有的人时常思考一个问题,冶炼炉里面这么多流体就不会混起来吗?
再加上如果有的人把那种生物质流体塞进冶炼炉,是不是也会污染呢……

于是这里弄了几个离谱规则,当然比例是调整过的:

    普通金属+特殊金属=铁合金
    普通金属+水/岩浆=熔融石头

    有机类流体+水/岩浆=水/岩浆
    有机类流体+普通金属=熔融泥土


代码如下,...表省略:

    var Basic=  [] as crafttweaker.liquid.ILiquidStack[];
    var MetalA= [] as crafttweaker.liquid.ILiquidStack[];
    var MetalB= [] as crafttweaker.liquid.ILiquidStack[];
    var Bio=    [] as crafttweaker.liquid.ILiquidStack[];

    Basic+=<liquid:water>;
    Basic+=<liquid:lava>;
    MetalB+=<liquid:silver>;
    MetalB+=<liquid:gold>;
   
    MetalA+=<liquid:copper>;
    MetalA+=<liquid:iron>;
    MetalA+=<liquid:nickel>;
    MetalA+=<liquid:tin>;
    MetalA+=<liquid:zinc>;
    MetalA+=<liquid:aluminum>;
    //...
   
    Bio+=<liquid:syrup>;
    Bio+=<liquid:resin>;
    Bio+=<liquid:sap>;
    //...

    for i in MetalA {
        for j in MetalB {
            mods.tconstruct.Alloy.addRecipe(<liquid:construction_alloy>*7,[i*5,j*2]);
        }
    }

    for i in Basic {
        for j in MetalA {
            mods.tconstruct.Alloy.addRecipe(<liquid:stone>*13,[i*9,j*4]);
        }
        for j in MetalB {
            mods.tconstruct.Alloy.addRecipe(<liquid:stone>*13,[i*9,j*4]);
        }
        mods.tconstruct.Alloy.addRecipe(<liquid:stone>*13,[i*9,<liquid:construction_alloy>*4]);

        for j in Bio{
            mods.tconstruct.Alloy.addRecipe(i*2,[i*1,j*1]);
        }
    }

    for i in Bio {
        for j in MetalA {
            mods.tconstruct.Alloy.addRecipe(<liquid:dirt>*13,[i*11,j*2]);
        }
        for j in MetalB {
            mods.tconstruct.Alloy.addRecipe(<liquid:dirt>*13,[i*11,j*2]);
        }
        mods.tconstruct.Alloy.addRecipe(<liquid:dirt>*13,[i*11,<liquid:construction_alloy>*2]);
    }



AE2的UU物质!

这个想法可能比较极端,甚至比较谔谔:为什么一个物流模组要这么多合成表?
应该让圆石+赛特斯石英+福鲁伊克斯水晶就可以合成绝大部分东西!
不过要进行一些避雷和捡漏。

逻辑:

    穷举AE2的所有物品,带有一个从0开始的计数器c
        如果是要保留原合成表的物品的那就continue;(直接再次循环,这一次循环不要了)
        c=c+1
        把c写成八位三进制,每一位对应3*3合成表里的一个槽,右下角的槽恒定放fluix用来锁科技。
            如果是0就是圆石,如果是1就是certus,如果是2就是fluix。


代码:

import crafttweaker.mods.IMod;
import crafttweaker.mods.ILoadedMods;
val ae2=loadedMods["appliedenergistics2"] as IMod;
var c=0 as int;
val m0 = [<minecraft:cobblestone>,<appliedenergistics2:material>,<appliedenergistics2:material:7>] as crafttweaker.item.IIngredient[];
print(ae2.id);
for i in ae2.items{
    print(c);
    if(i.definition.id.contains("facade")){
        continue;}
    if(i.definition.id.contains("material")){
        continue;}        
    if(i.definition.id.contains("seed")){
        continue;}
    //...
    if(i.ores.length<1){
        c+=1;
        recipes.remove(i);
        furnace.remove(i);
        var t=c as int;
        var m = [[null,null,null],[null,null,null],[null,null,null]] as crafttweaker.item.IIngredient[][];
        for j in 0 to 9{
            m[j/3 as int][j%3]=m0[t%3];
            t=t/3 as int;
        }
        m[2][2]=m0[2];
        recipes.addShaped(i,m);
    }
}
recipes.remove(<appliedenergistics2:creative_energy_cell>);
recipes.remove(<appliedenergistics2:matrix_frame>);
recipes.addShaped(<appliedenergistics2:material:28>,[...]);
recipes.addShaped(<appliedenergistics2:material:25>,[...]);
recipes.addShaped(<appliedenergistics2:material:52>,[...]);
recipes.addShaped(<appliedenergistics2:material:42>,[...]);




函数

计算机函数是:
    输入一些数据,执行一些代码,输出一些数据。


那么我们可以拿它干嘛呢?
当然是把模式化而又繁复的东西变成一行代码!

先来看一下格式。

fuction  Name (parameter1 as type,  parameter2 as type, ...)as type{
       //Todo
}

Name是函数的名字。
type是参数/返回值的类型。
多说无益,看例子吧!

怪物压蛋

刷怪蛋的nbt太长了,惹人不喜。
因为CrT给AE2的压印器弄了一个离谱样例,说凋零骷髅头压印(不消耗)鸡蛋得到凋零骷髅刷怪蛋,所以读者大受震撼,做出了以下作品。

import mods.appliedenergistics2.Inscriber;
import crafttweaker.item.IIngredient;
val egg=<minecraft:egg>;
function InEgg(a as string, b as IIngredient, c as IIngredient = null, d as bool = false) as void{
//    定义InEgg,a是怪物id,可以在游戏里拿着刷怪蛋/ct hand看到
//    b和c都是材料,d说明是否是压印,如果是那么就不消耗“压印板”
    Inscriber.addRecipe(<minecraft:spawn_egg>.withTag({EntityTag: {id: a}}),
        <minecraft:egg>,d,b,c);
}
InEgg("minecraft:chicken",egg,egg);
InEgg("minecraft:sheep",<minecraft:wool>,<minecraft:wool>);
InEgg("minecraft:skeleton",<minecraft:bone>,<minecraft:bone>);
InEgg("minecraft:creeper",<minecraft:gunpowder>,<enderio:item_material:20>);
InEgg("minecraft:villager",<minecraft:emerald>,<minecraft:emerald>);

(挖坑)


气血宝珠

我们想要大规模地定义 气血宝珠 参与的合成。
高级的气血宝珠应当可以完成低级气血宝珠的任务。
但是每次都写一大堆“或”判断太复杂了。
所以我们可以写一个函数,输入一个整数,表示气血宝珠的最低等级,输出一个IIngredient,即可以参与合成的几种气血宝珠。

function orb(n as int=1)as IIngredient{
    var orbs as IIngredient[]=[<bloodmagic:blood_orb>.withTag({orb: "bloodmagic:weak"}),
    <bloodmagic:blood_orb>.withTag({orb: "bloodmagic:apprentice"}),
    <bloodmagic:blood_orb>.withTag({orb: "bloodmagic:magician"}),
    <bloodmagic:blood_orb>.withTag({orb: "bloodmagic:master"}),
    <bloodmagic:blood_orb>.withTag({orb: "bloodmagic:archmage"})];
    var r as IIngredient=orbs[4];
    for i in (n- 1) to 4{
        r=r.or(orbs[i]);     //or,表示如果是括号里那个东西也可以。
    }
    return r;
}


自动配方名称

1.12.2的终极工作台在配方添加时,必须填写配方名称。

但是绝大多数情况下,手动填写很麻烦,而且可能手残写了两个配方名称一样的配方。

所以……

static numberOfSARecipes as int[]=[0];
function ShapedAvaritia(o as IItemStack,i as IIngredient[][])as int{
    mods.avaritia.ExtremeCrafting.addShaped("ArtOfEnigma9C3BLv1Orb"~numberOfSARecipes[0],o,i);
    numberOfSARecipes[0]=numberOfSARecipes[0]+1;
    return 1;
}

类型理论

//ToDo

事件

//ToDo