本篇教程由作者设定使用 CC BY-NC 协议。
仙贝,仙贝,世界合成这个mod确实挺不错的,但限制还是太多了,有没有限制更少功能更多的世界合成方式呢。有的,兄弟,有的,像这么强力的魔改,仙贝一共写了六种,个个都是非常的好用,只要你复制粘贴进zs文件里就能成为世界合成大王。?
世界合成这mod虽然提供了非常方便的方式来添加配方,但同样他的局限性太大了,比如无法添加多个输出,无法设置输入消耗概率,无法随机输出等等等等。所以我就搓了个魔改文件方便大家使用。
魔改文件可以直接复制下面的代码或者去百度网盘下载,也可以加入crt魔改群:624487948后找仙贝要。
刚需mod:CraftTweaker,Zen Utils。
非刚需mod:RandomTweaker。用于添加jei,输入输出不得多于10种(或者你自己加一下jei的槽位,魔改是多少种都能接受的)
#reloadable
// Created by xian_bei010,QQ:2234690032,mcmod:https://center.mcmod.cn/680553/
// 由仙贝010制作,QQ:2234690032,mcmod:https://center.mcmod.cn/680553/,QQ交流群:624487948
import crafttweaker.world.IWorld;
import crafttweaker.item.IItemStack;
import crafttweaker.item.WeightedItemStack;
import crafttweaker.item.IIngredient;
import crafttweaker.oredict.IOreDictEntry;
import crafttweaker.world.IBlockPos;
import crafttweaker.data.IData;
import crafttweaker.liquid.ILiquidStack;
import crafttweaker.entity.IEntityItem;
import crafttweaker.entity.IEntity;
import crafttweaker.entity.IEntityMob;
import crafttweaker.util.IAxisAlignedBB;
import crafttweaker.util.Math;
import crafttweaker.event.WorldTickEvent;
import crafttweaker.event.EntityJoinWorldEvent;
import crafttweaker.event.ExplosionDetonateEvent;
import crafttweaker.event.IExplosionEvent;
import crafttweaker.event.EntityStruckByLightningEvent;
import mods.zenutils.event.EntityItemDeathEvent;
import mods.zenutils.DataUpdateOperation.MERGE;
zenClass Craft{//用来存储合成时的各种变量
var world as IWorld;
var pos as IBlockPos;
var entityItems as IEntityItem[]=[];
var ExplosionEvent as IExplosionEvent=null;
var LightningEvent as EntityStruckByLightningEvent=null;
var fallingBlock as IEntity=null;
var dynamicOutputs as IItemStack[]=[];
var dynamicOutputsMap as IItemStack[IItemStack]={};
var shouldCancel as bool=false;
zenConstructor(w as IWorld,p as IBlockPos,e as IEntityItem[]){
world=w;
pos=p;
entityItems=e;
}
function addExplosionEvent(event as IExplosionEvent)as Craft{
ExplosionEvent=event;
return this;
}
function addLightningEvent(event as EntityStruckByLightningEvent)as Craft{
LightningEvent=event;
return this;
}
function addFallingBlock(block as IEntity)as Craft{
fallingBlock=block;
return this;
}
function changeItemOutput(items as IItemStack)as Craft{//更改合成时的物品输出 在此更改输出只影响当前合成,如果在recipe中更改则为全局更改
this.dynamicOutputs=[items];
return this;
}
function changeItemOutputs(items as IItemStack[])as Craft{//同样为更改输出
this.dynamicOutputs=items;
return this;
}
function changeItemOutputs(itemsMap as IItemStack[IItemStack])as Craft{//更改输出,但只会将配方中含有的物品替换成另一个物品
this.dynamicOutputs=itemsMap.values;
this.dynamicOutputsMap=itemsMap;
return this;
}
function cancel()as void{//取消本次合成
shouldCancel=true;
}
}
//刚需mod:CraftTweaker,Zen Utils。
//非刚需mod:RandomTweaker。用于添加jei。输入输出需要小于等于10种。
//----------需要安装RandomTweaker!否则需要删除这部分魔改----------↓
val xBIWCF=mods.jei.JEI.createJei("xian_bei010_InWorldCrafting_fluid","世界合成-流体");
xBIWCF.setModid("crafttweaker");
xBIWCF.setIcon(<minecraft:water_bucket>);
xBIWCF.setBackground(mods.randomtweaker.jei.IJeiUtils.createBackground(130,175));
xBIWCF.addElement(mods.randomtweaker.jei.IJeiUtils.createArrowElement(57,37,3));
xBIWCF.addElement(mods.randomtweaker.jei.IJeiUtils.createArrowElement(57,78,3));
xBIWCF.addElement(mods.randomtweaker.jei.IJeiUtils.createArrowElement(74,60,0));
xBIWCF.addSlot(mods.randomtweaker.jei.IJeiUtils.createLiquidSlot(57,60,16,16,1000,false,true));
// xBIWCF.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(55,60,true));
for y in 0 to 2{
for x in 0 to 5{
xBIWCF.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(20 + (18 * x),(18 * y),true));
}
}
xBIWCF.addSlot(mods.randomtweaker.jei.IJeiUtils.createLiquidSlot(99,60,16,16,1000,false,false));
// xBIWCF.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(101,60,false));
for y in 0 to 2{
for x in 0 to 5{
xBIWCF.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(6 + (25 * x),105 + (25 * y),false));
}
}
xBIWCF.register();
val xBIWCE=mods.jei.JEI.createJei("xian_bei010_InWorldCrafting_explosion","世界合成-爆炸");
xBIWCE.setModid("crafttweaker");
xBIWCE.setIcon(<minecraft:tnt>);
xBIWCE.setBackground(mods.randomtweaker.jei.IJeiUtils.createBackground(130,175));
xBIWCE.addElement(mods.randomtweaker.jei.IJeiUtils.createArrowElement(57,37,3));
xBIWCE.addElement(mods.randomtweaker.jei.IJeiUtils.createArrowElement(57,78,3));
xBIWCE.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(55,60,true));
for y in 0 to 2{
for x in 0 to 5{
xBIWCE.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(20 + (18 * x),(18 * y),true));
}
}
for y in 0 to 2{
for x in 0 to 5{
xBIWCE.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(6 + (25 * x),105 + (25 * y),false));
}
}
xBIWCE.register();
val xBIWCFire=mods.jei.JEI.createJei("xian_bei010_InWorldCrafting_fire","世界合成-火焰");
xBIWCFire.setModid("crafttweaker");
xBIWCFire.setIcon(<minecraft:flint_and_steel>);
xBIWCFire.setBackground(mods.randomtweaker.jei.IJeiUtils.createBackground(130,175));
xBIWCFire.addElement(mods.randomtweaker.jei.IJeiUtils.createArrowElement(57,37,3));
xBIWCFire.addElement(mods.randomtweaker.jei.IJeiUtils.createArrowElement(57,78,3));
xBIWCFire.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(55,60,true));
for y in 0 to 2{
for x in 0 to 5{
xBIWCFire.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(20 + (18 * x),(18 * y),true));
}
}
for y in 0 to 2{
for x in 0 to 5{
xBIWCFire.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(6 + (25 * x),105 + (25 * y),false));
}
}
xBIWCFire.register();
val xBIWCLightning=mods.jei.JEI.createJei("xian_bei010_InWorldCrafting_lightning","世界合成-闪电");
xBIWCLightning.setModid("crafttweaker");
xBIWCLightning.setIcon(<minecraft:nether_star>.withDisplayName("雷击"));
xBIWCLightning.setBackground(mods.randomtweaker.jei.IJeiUtils.createBackground(130,175));
xBIWCLightning.addElement(mods.randomtweaker.jei.IJeiUtils.createArrowElement(57,37,3));
xBIWCLightning.addElement(mods.randomtweaker.jei.IJeiUtils.createArrowElement(57,78,3));
xBIWCLightning.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(55,60,true));
for y in 0 to 2{
for x in 0 to 5{
xBIWCLightning.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(20 + (18 * x),(18 * y),true));
}
}
for y in 0 to 2{
for x in 0 to 5{
xBIWCLightning.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(6 + (25 * x),105 + (25 * y),false));
}
}
xBIWCLightning.register();
val xBIWCAnvil=mods.jei.JEI.createJei("xian_bei010_InWorldCrafting_anvil","世界合成-铁砧");
xBIWCAnvil.setModid("crafttweaker");
xBIWCAnvil.setIcon(<minecraft:anvil>);
xBIWCAnvil.setBackground(mods.randomtweaker.jei.IJeiUtils.createBackground(130,175));
xBIWCAnvil.addElement(mods.randomtweaker.jei.IJeiUtils.createArrowElement(57,19,3));
xBIWCAnvil.addElement(mods.randomtweaker.jei.IJeiUtils.createArrowElement(57,78,3));
xBIWCAnvil.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(55,0,true));
for y in 0 to 2{
for x in 0 to 5{
xBIWCAnvil.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(20 + (18 * x),42 + (18 * y),true));
}
}
for y in 0 to 2{
for x in 0 to 5{
xBIWCAnvil.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(6 + (25 * x),105 + (25 * y),false));
}
}
xBIWCAnvil.register();
val xBIWCFalling=mods.jei.JEI.createJei("xian_bei010_InWorldCrafting_falling","世界合成-坠落");
xBIWCFalling.setModid("crafttweaker");
xBIWCFalling.setIcon(<minecraft:sand>);
xBIWCFalling.setBackground(mods.randomtweaker.jei.IJeiUtils.createBackground(130,175));
xBIWCFalling.addElement(mods.randomtweaker.jei.IJeiUtils.createArrowElement(57,19,3));
xBIWCFalling.addElement(mods.randomtweaker.jei.IJeiUtils.createArrowElement(57,78,3));
xBIWCFalling.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(55,0,true));
for y in 0 to 2{
for x in 0 to 5{
xBIWCFalling.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(20 + (18 * x),42 + (18 * y),true));
}
}
for y in 0 to 2{
for x in 0 to 5{
xBIWCFalling.addSlot(mods.randomtweaker.jei.IJeiUtils.createItemSlot(6 + (25 * x),105 + (25 * y),false));
}
}
xBIWCFalling.register();
//----------需要安装RandomTweaker!否则需要删除这部分魔改----------↑
zenClass InWorldCrafting{
zenConstructor(){}
var itemInputs as IIngredient[]=[];
var itemOutputs as IItemStack[]=[];
var fluid as ILiquidStack;
var fluidOutput as ILiquidStack;
var type as string="fluid";
var consumef as bool=false;
var map3 as int[string]={};
var crafted as bool=false;
var preViewItems as IIngredient[]=[];
var fontInfo as string=null;
var anvil as IIngredient=<minecraft:anvil>;
var anvilN as string[]=["minecraft:anvil"];
var falling as IIngredient=null;
var preViewFalling as IIngredient=null;
var crafting as function(InWorldCrafting,Craft)void=null;
var consumeAll as bool=false;
function addItemInput(item as IIngredient)as InWorldCrafting{//添加单个物品输入
itemInputs += item;
preViewItems += item;
return this;
}
function setPreViewNBT(nbt as IData)as InWorldCrafting{//为上一个输入物品设置配方预览时显示的 NBT,不影响配方 NBT 匹配
if(preViewItems.length == 0){
logger.logError("InWorldCrafting.zs:itemInputs is null!!!");
}else{
val ii=preViewItems[preViewItems.length - 1];
if(ii instanceof IItemStack){
val item as IItemStack=ii;
preViewItems[preViewItems.length - 1]=item.withTag(nbt);
}
}
return this;
}
function addItemInputs(items as IIngredient[])as InWorldCrafting{//添加多个物品输入
for item in items{
itemInputs += item;
preViewItems += item;
}
return this;
}
function addItemOutput(item as IItemStack)as InWorldCrafting{//添加一个物品输出
itemOutputs += item;
return this;
}
function addItemOutputs(items as IItemStack[])as InWorldCrafting{//添加多个物品输出
for item in items{
itemOutputs += item;
}
return this;
}
function setFluid(fluidi as ILiquidStack)as InWorldCrafting{//设置合成时的流体
fluid = fluidi;
return this;
}
function addFluidOutput(fluido as ILiquidStack)as InWorldCrafting{//添加一个流体输出,若不输出新的流体,则可以不添加流体输出。默认仅流体合成生效,若要其他类型合成生成流体输出请使用下方的onCrafting函数
fluidOutput = fluido;
return this;
}
function setType(t as string)as InWorldCrafting{//设置合成方式,一共有五种,分别是:"fluid"流体合成,"explosion"爆炸合成,"fire"火焰合成,"lightning"闪电合成,"anvil"铁砧合成,"falling"坠落合成。
type=t.toLowerCase();
return this;
}
function canConsumeAllItemInput(consumeAll as bool)as InWorldCrafting{//是否消耗所有物品输入,如果设置为true,那么有多少份材料就会输出多少份输出
this.consumeAll=consumeAll;
return this;
}
function consumeFluid(consume as bool)as InWorldCrafting{//是否消耗流体,默认不消耗。他的优先级比流体输出低,假如你添加了流体输出,那么他会先把原流体设置为空气,然后设置为新流体。
consumef=consume;
return this;
}
function setFontInfo(f as string)as InWorldCrafting{//设置jei信息,会在jei下面加一行字
fontInfo=f;
return this;
}
function addAnvil(i as IItemStack)as InWorldCrafting{//添加铁砧,仅合成方式为铁砧合成时有效,默认为原版铁砧,你可以加eio或者其他模组的铁砧。
anvil=anvil.or(i);
anvilN += i.definition.id;
return this;
}
function setAnvil(i as IItemStack)as InWorldCrafting{//设置为指定铁砧,仅合成方式为铁砧合成时有效。会清除默认以及你添加的铁砧。
anvil=i;
anvilN=[i.definition.id];
return this;
}
function addFallingBlock(b as IItemStack)as InWorldCrafting{//添加坠落方块,仅合成方式为坠落合成时有效,坠落合成与铁砧合成有一定区别,如铁砧合成不会匹配铁砧的meta(即就算你指定铁砧为严重损坏的,但完好的铁砧仍能进行合成)但坠落合成会
falling=isNull(falling) ? b as IIngredient : falling.or(b);
preViewFalling=isNull(preViewFalling) ? b as IIngredient : preViewFalling.or(b);
return this;
}
function addFallingBlocks(bs as IItemStack[])as InWorldCrafting{//添加多个坠落方块,仅合成方式为坠落合成时有效。
for b in bs{
falling=isNull(falling) ? b as IIngredient : falling.or(b);
preViewFalling=isNull(preViewFalling) ? b as IIngredient : preViewFalling.or(b);
}
return this;
}
function setFallingBlockMeta(m as int[])as InWorldCrafting{//设上一个置坠落方块的meta,仅合成方式为坠落合成时有效。如上面所说,坠落合成是匹配meta的,但有些方块的物品meta和方块meta不一样,如铁砧(完好的物品铁砧meta为0,方块则根据facing而分为0,1,2,3),当物品meta和方块meta不一样时你就需要使用这个函数
if(isNull(falling)){
logger.logError("InWorldCrafting.zs:fallingBlock is null!!!");
}else{
val items=falling.items;
var newFalling as IIngredient=null;
for i in 0 to items.length{
if(i == items.length - 1){
for meta in m{
newFalling=isNull(newFalling) ? items[i].withDamage(meta)as IIngredient : newFalling.or(items[i].withDamage(meta)as IIngredient);
}
}else newFalling=isNull(newFalling) ? items[i]as IIngredient : newFalling.or(items[i]as IIngredient);
}
falling=newFalling;
}
return this;
}
function onCrafting(craft as function(InWorldCrafting,Craft)void=null)as InWorldCrafting{//当合成时xxx
crafted=true;
crafting=craft;
return this;
}//以下的函数你都不用看了,可以直接跳到最下面去看使用示例!
function containsAll(a as IItemStack[])as bool{//不用管
for input in this.itemInputs{
var matched=false;
for item in a{
if(input.matches(item)){
matched=true;
map3[item.tag.uuid.asString()]=item.amount - input.amount;
break;
}
}
if(!matched)return false;
}
return true;
}
function calculateMaxRatio(a as IItemStack[])as int{//不用管
var minRatio=1000000.0f;
for itemStack in a{
var totalA=0.0f;
for ing in this.itemInputs{
if(ing.matches(itemStack)){
totalA += ing.amount;
}
}
if(totalA <= 0.0f)return 0;
var ratio=(itemStack.amount as float) / totalA;
if(ratio < minRatio)minRatio = ratio;
}
return (minRatio == 1000000.0f ? 0 : Math.floor(minRatio as double)as int);
}
function getEntityItems(w as IWorld,maxRatio as int)as IEntityItem[]{//不用管
var eIs as IEntityItem[]=[];
for uuid,amount in map3{
for e in w.getEntityItems(){
if(!isNull(e)&&e.uuid == uuid){
val need=consumeAll ? e.item.amount - (amount * maxRatio) : amount;
e.update({"craftedAmount": need});
eIs += e;
}
}
}
return eIs;
}
function processCrafting(w as IWorld,pos as IBlockPos,items as IItemStack[],craftObj as Craft)as void{//不用管
if(!containsAll(items)||map3.length == 0)return;
val maxRatio=consumeAll ? calculateMaxRatio(items) : 1;
val eIs=getEntityItems(w,maxRatio);
craftObj.entityItems=eIs;
crafting(this,craftObj);
if(craftObj.shouldCancel){
for eI in eIs{
eI.update({"craftedAmount":eI.item.amount});
}
}else{
for eI in eIs{
val amount=eI.forgeData.craftedAmount.asInt();
if(amount > 0)eI.setItem(eI.item.withAmount(amount));
else eI.setDead();
}
var outputs as IItemStack[]=[];
if(craftObj.dynamicOutputs.length > 0){
if(craftObj.dynamicOutputsMap.length > 0){
for i in itemOutputs{
if(craftObj.dynamicOutputsMap.keys has i){
if(!isNull(craftObj.dynamicOutputsMap[i])) outputs += craftObj.dynamicOutputsMap[i];
}else outputs += i;
}
}else outputs=craftObj.dynamicOutputs;
}else outputs=itemOutputs;
for i in outputs{
w.spawnEntity(i.withAmount(i.amount * maxRatio).createEntityItem(w,pos));
}
if(type == "fluid"){
if(consumef)w.setBlockState(<blockstate:minecraft:air>,pos);
if(!isNull(fluidOutput))w.setBlockState(fluidOutput.definition.block.definition.defaultState,pos);
}
}
}
function handleFluidCrafting(event as WorldTickEvent)as void{//不用管
val w=event.world;
if(w.remote||event.phase == "END"||w.getEntityItems().length == 0) return;
if(w.worldInfo.worldTotalTime % 5 != 0) return;
val map2 as IItemStack[][IBlockPos]={};
for i in w.getEntityItems(){
if(i.forgeData.asString() has "InWorldCrafting"){
val b=w.getBlock(i.position);
if(!isNull(b)&&!isNull(b.fluid)&&b.fluid.name == fluid.definition.name){
val pos=i.position;
if(isNull(map2[pos])) map2[pos]=[];
map2[pos]=map2[pos] + i.item.updateTag({"uuid": i.uuid} as IData);
}
}
}
for pos, items in map2{
processCrafting(w,pos,items,Craft(w,pos,[]));
}
}
function handleFireCrafting(event as WorldTickEvent)as void{//不用管
val w=event.world;
if(w.remote||event.phase == "END"||w.getEntityItems().length == 0) return;
if(w.worldInfo.worldTotalTime % 5 != 0) return;
val map2 as IItemStack[][IBlockPos]={};
for i in w.getEntityItems(){
if(i.forgeData.asString() has "InWorldCrafting"&&i.isBurning){
val pos=i.position;
if(isNull(map2[pos])) map2[pos]=[];
map2[pos]=map2[pos] + i.item.updateTag({"uuid": i.uuid} as IData);
}
}
for pos, items in map2{
processCrafting(w,pos,items,Craft(w,pos,[]));
}
}
function hadleExplosionCrafting(event as ExplosionDetonateEvent)as void{//不用管
val w=event.world;
if(w.remote||event.affectedEntities.length == 0) return;
var ei as IEntityItem[]=[];
for e in event.affectedEntities{
if(e instanceof IEntityItem&&e.forgeData.asString() has "InWorldCrafting"){
val eee as IEntityItem=e;
ei += eee;
}
}
if(ei.length > 0){
var items as IItemStack[]=[];
for e in ei{
items += e.item.updateTag({"uuid": e.uuid} as IData);
}
val craftObj=Craft(w,event.position,ei).addExplosionEvent(event);
processCrafting(w,event.position,items,craftObj);
}
}
function handleLightningCrafting(event as EntityStruckByLightningEvent)as void{//不用管
val e=event.entity;
val w=e.world;
if(w.remote||!(e instanceof IEntityItem))return;
val ei as IEntityItem=e;
var valid=false;
for item in itemInputs{
if(item.matches(ei.item)){
valid=true;
break;
}
}
if(valid){
val pos=ei.position;
var items as IItemStack[]=[];
for i in w.getEntitiesWithinAABB(IAxisAlignedBB.create(pos)){
if(i instanceof IEntityItem&&i.forgeData.asString() has "InWorldCrafting"&&i.alive){
val iii as IEntityItem=i;
items += iii.item.updateTag({"uuid": i.uuid} as IData);
}
}
val craftObj=Craft(w,pos,[]).addLightningEvent(event);
processCrafting(w,pos,items,craftObj);
}
}
function handleFallingCrafting(event as WorldTickEvent)as void{//不用管
val w=event.world;
if(w.remote||event.phase == "END")return;
var entities as IEntity[]=[];
for e in w.getEntities(){
if(!isNull(e.definition)&&e.definition.id == "minecraft:falling_block"){
if(type == "anvil"){
if(anvilN has e.nbt.Block.asString())entities += e;
}else if(!isNull(falling)&&falling.matches(itemUtils.getItem(e.nbt.Block.asString(),e.nbt.Data.asByte()))) entities += e;
}
}
if(entities.length > 0){
val map2 as IItemStack[][IBlockPos]={};
val fallingMap as IEntity[IBlockPos]={};
for e in entities{
val pos=e.position;
if(!w.isAirBlock(pos.down())){
var itemsInArea as IItemStack[]=[];
for i in w.getEntitiesWithinAABB(IAxisAlignedBB.create(pos)){
if(i instanceof IEntityItem&&i.forgeData.asString() has "InWorldCrafting"){
val iii as IEntityItem=i;
itemsInArea += iii.item.updateTag({"uuid": i.uuid} as IData);
}
}
if(itemsInArea.length > 0){
map2[pos]=itemsInArea;
fallingMap[pos]=e;
}
}
}
for pos,items in map2{
val craftObj=Craft(w,pos,[]).addFallingBlock(fallingMap[pos]);
processCrafting(w,pos,items,craftObj);
}
}
}
function craft() as void{//不用管
if(type == "fluid"&&isNull(fluid)){
logger.logError("InWorldCrafting.zs: fluid is null!!!");
return;
}
if(type == "fluid"){
events.onWorldTick(function(event as WorldTickEvent){
this.handleFluidCrafting(event);
});
}
else if(type == "explosion"){
events.onExplosionDetonate(function(event as ExplosionDetonateEvent){
this.hadleExplosionCrafting(event);
});
}
else if(type == "fire"){
events.onEntityItemDeath(function(event as EntityItemDeathEvent){
val ei=event.item;
val w=ei.world;
if(!w.remote&&event.damageSource.fireDamage){
for item in itemInputs {
if(item.matches(ei.item)){
val e=ei.item.createEntityItem(w,ei.position);
e.native.setPickupDelay(15);
e.native.setEntityInvulnerable(true);
w.spawnEntity(e);
break;
}
}
}
});
events.onWorldTick(function(event as WorldTickEvent){
this.handleFireCrafting(event);
});
}
else if(type == "lightning"){
events.onEntityStruckByLightning(function(event as EntityStruckByLightningEvent){
this.handleLightningCrafting(event);
});
}
else if(type == "anvil"||type == "falling"){
events.onWorldTick(function(event as WorldTickEvent){
this.handleFallingCrafting(event);
});
}
}
//----------需要安装RandomTweaker!否则需要删除这部分魔改----------↓
function addJeiRecipe()as void{
val info=this.fontInfo;
if(type == "fluid"){
val IWCF=mods.jei.JEI.createJeiRecipe("xian_bei010_InWorldCrafting_fluid");
IWCF.addInput(fluid.withAmount(1000));
for input in preViewItems{
IWCF.addInput(input);
}
IWCF.addOutput((isNull(fluidOutput) ? fluid.withAmount(1000) : fluidOutput.withAmount(1000)));
for output in itemOutputs{
IWCF.addOutput(output);
}
if(!isNull(info))IWCF.addElement(mods.randomtweaker.jei.IJeiUtils.createFontInfoElement(info,0,155,16711680));
IWCF.build();
}
if(type == "explosion"){
val IWCE=mods.jei.JEI.createJeiRecipe("xian_bei010_InWorldCrafting_explosion");
IWCE.addInput(<minecraft:tnt>);
for input in preViewItems{
IWCE.addInput(input);
}
for output in itemOutputs{
IWCE.addOutput(output);
}
if(!isNull(info))IWCE.addElement(mods.randomtweaker.jei.IJeiUtils.createFontInfoElement(info,0,155,16711680));
IWCE.build();
}
if(type == "fire"){
val IWCFire=mods.jei.JEI.createJeiRecipe("xian_bei010_InWorldCrafting_fire");
IWCFire.addInput(<minecraft:flint_and_steel>);
for input in preViewItems{
IWCFire.addInput(input);
}
for output in itemOutputs{
IWCFire.addOutput(output);
}
if(!isNull(info))IWCFire.addElement(mods.randomtweaker.jei.IJeiUtils.createFontInfoElement(info,0,155,16711680));
IWCFire.build();
}
if(type == "lightning"){
val IWCLghtning=mods.jei.JEI.createJeiRecipe("xian_bei010_InWorldCrafting_lightning");
IWCLghtning.addInput(<minecraft:nether_star>.withDisplayName("雷击"));
for input in preViewItems{
IWCLghtning.addInput(input);
}
for output in itemOutputs{
IWCLghtning.addOutput(output);
}
IWCLghtning.addElement(mods.randomtweaker.jei.IJeiUtils.createFontInfoElement("需要最上方物品被闪电击中",0,155,10975722));
if(!isNull(info))IWCLghtning.addElement(mods.randomtweaker.jei.IJeiUtils.createFontInfoElement(info,0,165,16711680));
IWCLghtning.build();
}
if(type == "anvil"){
val IWCAnvil=mods.jei.JEI.createJeiRecipe("xian_bei010_InWorldCrafting_anvil");
IWCAnvil.addInput(anvil);
for input in preViewItems{
IWCAnvil.addInput(input);
}
for output in itemOutputs{
IWCAnvil.addOutput(output);
}
if(!isNull(info))IWCAnvil.addElement(mods.randomtweaker.jei.IJeiUtils.createFontInfoElement(info,0,155,16711680));
IWCAnvil.build();
}
if(type == "falling"){
if(isNull(preViewFalling)){
logger.logError("InWorldCrafting.zs:falling block is null!!!");
return;
}
val IWCFalling=mods.jei.JEI.createJeiRecipe("xian_bei010_InWorldCrafting_falling");
IWCFalling.addInput(preViewFalling);
for input in preViewItems{
IWCFalling.addInput(input);
}
for output in itemOutputs{
IWCFalling.addOutput(output);
}
if(!isNull(info))IWCFalling.addElement(mods.randomtweaker.jei.IJeiUtils.createFontInfoElement(info,0,155,16711680));
IWCFalling.build();
}
}
//----------需要安装RandomTweaker!否则需要删除这部分魔改----------↑
function register()as void{//注册这个配方
events.onEntityJoinWorld(function(event as EntityJoinWorldEvent){
val e=event.entity;
val w=e.world;
if(!w.remote&&!isNull(e)&&e instanceof IEntityItem){
val ei as IEntityItem=e;
val item=ei.item;
for i in itemInputs{
if(i.amount(1).matches(item)){
e.update({"InWorldCrafting":1}as IData);
return;
}
}
}
});
//----------需要安装RandomTweaker!否则需要删除这部分魔改----------↓
this.addJeiRecipe();
//----------需要安装RandomTweaker!否则需要删除这部分魔改----------↑
if(!crafted) this.onCrafting(function(recipe as InWorldCrafting,crafting as Craft)as void{});
this.craft();
}
}
function createNewInWorldCrafting()as InWorldCrafting{//建一个函数声明返回类型,不然就没有补全或者你加配方时前面写成这样也行(InWorldCrafting() as InWorldCrafting)
return InWorldCrafting();
}
createNewInWorldCrafting()
.addItemInput(<minecraft:enchanted_book>)//添加一个附魔书输入
.addItemInput(<minecraft:diamond_sword>).setPreViewNBT({display:{Lore:["将会继承附魔书的附魔"]}})//添加一个钻石剑输入,并设置配方预览时的nbt,给钻石剑设置一个lore
.addItemOutputs([<minecraft:diamond_sword>])//添加一个物品输出
.onCrafting(function(recipe as InWorldCrafting,crafting as Craft)as void{//添加一个函数,当运行这个配方时xxxx。
val itemInputs=recipe.itemInputs;//获取配方的输入,由于这个事件是已经开始运行这个配方时发生的,所以已经完成过输入匹配了,也就是说你对配方的输入做出任何改变都没有用。
//如果你想在配方运行时改变输入那你需要用crafting.entityItems获取输入物品的物品实体,在这个实体的forgeData有个craftedAmount名称的IData,他就是配方运行完成后输入物品的数量,你可以对其进行更改。
var data={}as IData;
var diamond_sword as IItemStack=null;//先提前声明俩变量,懒得在循环里面做事。
val entityItems=crafting.entityItems;//获取合成时的输入物品的物品实体。
for ei in entityItems{//遍历
if(<minecraft:enchanted_book>.matches(ei.item)&&ei.item.hasTag&&!isNull(ei.item.tag.StoredEnchantments)){//如果这个物品实体里的物品是附魔书且有附魔属性
data=ei.item.tag.StoredEnchantments as IData;//data赋值为附魔属性
}
if(<minecraft:diamond_sword>.matches(ei.item)){//如果这个物品实体里的物品是钻石剑
diamond_sword=ei.item;//赋值
if(!ei.item.hasTag)crafting.cancel();//如果这个钻石剑没有nbt,那就取消配方
}
}
crafting.changeItemOutput(diamond_sword.updateTag(diamond_sword.tag.deepUpdate({ench:data},MERGE)));//更改本次合成的输出
})
.setFluid(<liquid:water>)//设置流体输入为水
.setType("fluid")//设置合成方式为流体合成
.addFluidOutput(<liquid:brine>)//设置一个流体输出
.register();//注册配方
createNewInWorldCrafting()
.addItemInput(<minecraft:gravel>)
.addItemOutput(<minecraft:iron_nugget>)
.addItemOutput(<minecraft:redstone>).setPreViewNBT({display:{Lore:["有50%概率产出"]}})
.onCrafting(function(recipe as InWorldCrafting,crafting as Craft)as void{
val w=crafting.world;
if(w.random.nextFloat() < 0.5f){
crafting.changeItemOutputs({<minecraft:redstone>:null}as IItemStack[IItemStack]);
//有50%的概率将本次合成输出中的红石粉替换为null 也就是50%概率产出。要替换为null时请在后面加上as IItemStack[IItemStack],不转类型会报错
}
})
.setFluid(<liquid:water>)
.setType("fluid")
.register();
createNewInWorldCrafting()
.addItemInput(<minecraft:sand>)
.addItemOutput(<minecraft:gold_nugget>)
.setFluid(<liquid:water>)
.setType("fluid")
.canConsumeAllItemInput(true)//此配方的每次合成都会消耗最大份数的材料,并产出对应的输出
.register();//可以不添加onCrafting函数
createNewInWorldCrafting()
.onCrafting(function(recipe as InWorldCrafting,crafting as Craft)as void{
val w=crafting.world;//获取合成时的世界
val random=w.random.nextFloat();//获取一个随机数
if(random < 0.5f)w.setBlockState(<blockstate:minecraft:air>,crafting.pos);//有50%概率在合成时的位置放置一个空气方块,也就是50%概率消耗流体
})
.addItemInput(<minecraft:stone>).setPreViewNBT({display:{Lore:["有50%概率消耗流体"]}})
.addItemOutput(<minecraft:iron_nugget>)
.setFluid(<liquid:water>)
.setType("fluid")
.register();
createNewInWorldCrafting()
.addItemInputs([<minecraft:wooden_shovel>])//添加一个木锹输入
.addItemOutputs([<minecraft:wooden_shovel>.withLore(["根据燃烧时下面的方块来决定生成什么,","如钻石块则生成钻石锹"])])//添加一个木锹输出
.setType("fire")//设置合成方式为火焰合成
.onCrafting(function(recipe as InWorldCrafting,crafting as Craft)as void{
val itemInputs=recipe.itemInputs;
val pos=IBlockPos.create(crafting.pos.x,crafting.pos.y - 1,crafting.pos.z);//获取合成时合成位置下面一格的位置
val w=crafting.world;//获取合成时的世界
val b=w.getBlock(pos);//获取下面一格位置的方块
var map as IItemStack[string]={//创建一个map,让一个方块id对应一个物品
"minecraft:diamond_block":<minecraft:diamond_shovel>,
"minecraft:iron_block":<minecraft:iron_shovel>,
"minecraft:gold_block":<minecraft:golden_shovel>
};
recipe.itemOutputs[0]=(map.keys has b.definition.id ? map[b.definition.id] : <minecraft:wooden_shovel>);//将这个配方的输出物品设置为(map的keys里包含下面一格位置的方块的id吗,如果包含则为方块id对应物品,否则为木锹)
//建议是使用crafting.changeItemOutput来更改输出,这样不容易出错
//if(!isNull(map[b.definition.id]))crafting.changeItemOutput(map[b.definition.id]);
})
.register();
createNewInWorldCrafting()
.onCrafting(function(recipe as InWorldCrafting,crafting as Craft)as void{
val itemInputs=recipe.itemInputs;
val event=crafting.ExplosionEvent;//获取合成时的事件(仅合成方式为爆炸时可以调用,其他合成方式均返回null)
val entity=event.explosion.placedBy;//获取爆炸事件的造成者
recipe.itemOutputs[0]=!isNull(entity) ? <minecraft:paper>.withDisplayName(entity.displayName) : <minecraft:paper>.withDisplayName("未找到爆炸源");//如果有爆炸事件的造成者那么就把纸命名为造成者的名字,否则则为未找到爆炸源。
})
.addItemInputs([<minecraft:paper>])
.addItemOutputs([<minecraft:paper>.withLore(["将会命名为爆炸源的名字"])])
.setType("explosion")//设置合成方式为爆炸
.register();
createNewInWorldCrafting()
.addItemInput(<minecraft:golden_apple:1>)
.setType("lightning")//设置合成方式为雷劈
.setFontInfo("附近存在僵尸村民时会转换成村民")//添加一个jei信息,会在配方下面显示
.onCrafting(function(recipe as InWorldCrafting,crafting as Craft)as void{
val w=crafting.world;
val pos=crafting.pos;
for i in w.getEntitiesWithinAABB(IAxisAlignedBB.create(IBlockPos.create(pos.x - 3,pos.y - 3,pos.z - 3),IBlockPos.create(pos.x + 3,pos.y + 3,pos.z + 3))){//遍历合成时的位置附近的实体
if(i instanceof IEntityMob&&i.definition.id == "minecraft:zombie_villager"){//如果是怪物实体且他的id是僵尸村民
w.removeEntity(i);//移除这个实体
<entity:minecraft:villager>.spawnEntity(w,i.position);//生成一个村民
}
}
})
.register();
createNewInWorldCrafting()
.addItemInput(<ore:ingotIron>*2)//添加两个铁锭矿词输入
.addItemOutput(<thermalfoundation:material:32>)//添加一个铁板输出
.addAnvil(<enderio:block_dark_steel_anvil>)//铁砧添加一个eio的玄钢钢
.setType("anvil")//设置合成方式为铁砧砸
.setFontInfo("当下方方块为铁块时,产出*2")//添加一个jei信息,会在配方下面显示
.onCrafting(function(recipe as InWorldCrafting,crafting as Craft)as void{
val w=crafting.world;
val pos=crafting.pos;
val downPos=IBlockPos.create(pos.x,pos.y - 1,pos.z);//获取合成时位置下面的pos
recipe.itemOutputs[0]=(w.getBlock(downPos).definition.id == "minecraft:iron_block" ? recipe.itemOutputs[0].withAmount(2) : recipe.itemOutputs[0].withAmount(1));//如果下面的方块是铁块,那就输出*2
})
.register();
createNewInWorldCrafting()
.addItemInput(<minecraft:stone>*2)//添加两个石头输入
.addItemOutput(<minecraft:gravel>)//添加一个沙砾输出
.addFallingBlock(<minecraft:sand>)//添加一个会坠落的方块 沙子
.setType("falling")//设置方式为坠落
.canConsumeAllItemInput(true)//此配方的每次合成都会消耗最大份数的材料,并产出对应的输出
.register();
createNewInWorldCrafting()
.addItemInput(<minecraft:sand>)//添加一个沙子输入
.addItemOutput(<minecraft:glass>)//添加一个玻璃输出
.addFallingBlock(<minecraft:anvil:2>).setFallingBlockMeta([8,9,10,11]as int[])//添加一个会坠落的方块 严重损坏铁砧,由于物品铁砧只有3个meta值(即0,1,2)但方块铁砧有12个meta值(即0,1...10,11)所以你需要设置他的方块meta,即8,9,10,11
.setType("falling")
.setFontInfo("当下方方块为岩浆块时,才会合成")//添加一个jei信息,会在配方下面显示
.onCrafting(function(recipe as InWorldCrafting,crafting as Craft)as void{
val pos=crafting.pos;//获取合成时的位置
val world=crafting.world;//获取合成时的世界
val downPos=IBlockPos.create(pos.x,pos.y - 1,pos.z);//获取合成时位置下面的pos
val isMagma=world.getBlock(downPos).definition.id == "minecraft:magma";//判断下面的方块是不是岩浆块
recipe.itemOutputs[0]=isMagma ? <minecraft:glass> : <minecraft:sand>;//如果是岩浆块,则输出玻璃,否则为沙子
})
.canConsumeAllItemInput(true)//此配方的每次合成都会消耗最大份数的材料,并产出对应的输出
.register();
最终效果如下:
![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
百度网盘链接:https://pan.baidu.com/s/1sqs8C4BEqGwsLwaI4mIY4g?pwd=xb66
最后感谢友谊妈的帮助~


![[1.12.2]魔改分享~使用crt实现世界合成功能-第1张图片](https://i.mcmod.cn/editor/upload/20250320/1742442292_680553_znbL.webp)
![[1.12.2]魔改分享~使用crt实现世界合成功能-第2张图片](https://i.mcmod.cn/editor/upload/20250201/1738394036_680553_xyJD.webp)
![[1.12.2]魔改分享~使用crt实现世界合成功能-第3张图片](https://i.mcmod.cn/editor/upload/20250201/1738394043_680553_CSaI.webp)
![[1.12.2]魔改分享~使用crt实现世界合成功能-第4张图片](https://i.mcmod.cn/editor/upload/20250201/1738394056_680553_MHHQ.webp)
![[1.12.2]魔改分享~使用crt实现世界合成功能-第5张图片](https://i.mcmod.cn/editor/upload/20250201/1738394067_680553_CndE.webp)
![[1.12.2]魔改分享~使用crt实现世界合成功能-第6张图片](https://i.mcmod.cn/editor/upload/20250320/1742441498_680553_PbmO.webp)
