本篇教程由作者设定使用 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();

最终效果如下:

[1.12.2]魔改分享~使用crt实现世界合成功能-第1张图片[1.12.2]魔改分享~使用crt实现世界合成功能-第2张图片
[1.12.2]魔改分享~使用crt实现世界合成功能-第3张图片[1.12.2]魔改分享~使用crt实现世界合成功能-第4张图片[1.12.2]魔改分享~使用crt实现世界合成功能-第5张图片[1.12.2]魔改分享~使用crt实现世界合成功能-第6张图片

百度网盘链接:https://pan.baidu.com/s/1sqs8C4BEqGwsLwaI4mIY4g?pwd=xb66

最后感谢友谊妈的帮助~