我的世界从〇开始的编程逻辑
这是啥
是一个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