本篇教程由作者设定使用 CC BY-NC-SA 协议。

因为 KJS 6 把 WrapperClass 全删了,给 KJS 6 写脚本可能需要一个 MC 反编译环境。

如希望添加自己的教程请在下方留言或电邮 colinxu2020@gmail.com。

TrashJS

  • 作者:Colinxu2020

  • 作用:一个不完整的KJS版的Scavenge(Fabric理论可用)JEI支持正在写

  • 协议:GNU Lesser Public License Version 3.0

  • 支持版本:KJS6

  • 运行位置:服务器脚本

代码:

// priority: 0

// Copyright© 2023 Colinxu2020
// 本程序是自由软件:你可以再分发之和/或依照由自由软件基金会发布的 GNU 宽松通用公共许可证修改之,无论是版本 3 许可证,还是(按你的决定)任何以后版都可以。
// 发布该程序是希望它能有用,但是并无保障;甚至连可销售和符合某个特定的目的都不保证。请参看 GNU 宽松通用公共许可证,了解详情。
// 你应该随程序获得一份 GNU 宽松通用公共许可证的复本。如果没有,请看 < 
// This program is free software: you can redistribute it and/or modify it under the terms of the GNU Leser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.

const ItemStack=Java.loadClass("net.minecraft.world.item.ItemStack");
const Registry = Java.loadClass("net.minecraft.core.Registry");
const ResourceLocation=Java.loadClass("net.minecraft.resources.ResourceLocation");
const InteractionHand=Java.loadClass("net.minecraft.world.InteractionHand")
const gives=new Map();
const limits=new Map();
const toolreq=new Map();

var inited=false;
var init_callback=[];
var init=function(){
    console.log('trashjs loading');
    inited=true;
    //using example
    
    init_callback.forEach((k)=>k(gives,limits,toolreq));
}
var add_init_callback=function(func){
    init_callback.push(func);
}
global.trashjs=add_init_callback;
var gettoolreq=function(idn){
    if(!toolreq.has(idn))return ItemStack.EMPTY;
    return ItemStack(Registry.ITEM.get(ResourceLocation(toolreq.get(idn))),1);
}


BlockEvents.rightClicked(event => {
    if(!inited)init();// 推迟初始化已确保拓展已初始化完毕
    if(event.getHand()!=InteractionHand.MAIN_HAND)return;
    var idn=String(Registry.BLOCK.getKey(event.getBlock().getBlockState().getBlock())).toString();
    if(event.getItem()!=gettoolreq(idn))return;
    if(!gives.has(idn))return;
    var entity=event.getBlock().getEntity();
    if(entity!=null){
        var data=entity.getPersistentData();
        data.putInt("state",data.getInt("state")+1);
    }else{
        if(limits.get(idn)!=-1)console.log('trashjs error: limit neq to -1 but block is not block entity.')
    }
    gives.get(idn).forEach((info,idn,mp)=>{
        if(Math.random()<info[0]){
            event.getEntity().getInventory().add(ItemStack(Registry.ITEM.get(ResourceLocation(idn)),info[1]));
        }
    })
    if(limits.get(idn)!=-1&&data.getInt("state")>=limits.get(idn)){
        event.getBlock().getLevel().removeBlock(event.getBlock().getPos(),false);
    }
});

核心部分逐行解释:

if(event.getHand()!=InteractionHand.MAIN_HAND)return;

如果不是主手产生的事件就直接返回

var idn=String(Registry.BLOCK.getKey(event.getBlock().getBlockState().getBlock())).toString();

通过神奇的 coremodding 获取目标方块的方块ID

if(event.getItem()!=gettoolreq(idn))return;

检查工具需求(gettoolreq就是通过toolreq构建ItemStack)

if(!gives.has(idn))return;

如果没有注册这个物品就退出

var entity=event.getBlock().getEntity();

获取方块实体

    if(entity!=null){
        var data=entity.getPersistentData();
        data.putInt("state",data.getInt("state")+1);
    }else{
        if(limits.get(idn)!=-1)console.log('trashjs error: limit neq to -1 but block is not block entity.')
    }

如果目标方块确实为方块实体,就记录右击次数(用于实现点击次数限制)。

    gives.get(idn).forEach((info,idn,mp)=>{
        if(Math.random()<info[0]){
            event.getEntity().getInventory().add(ItemStack(Registry.ITEM.get(ResourceLocation(idn)),info[1]));
        }
    })

枚举这个方块可能产生的所有掉落,如果运气够好就向物品栏添加物品(又是神奇的 coremodding)。

    if(limits.get(idn)!=-1&&data.getInt("state")>=limits.get(idn)){
        event.getBlock().getLevel().removeBlock(event.getBlock().getPos(),false);
    }

如果设置了点击次数限制且达到了就移除这个方块。

API用法

下面是固定的代码高仿KJS内置

global.trashjs((gives,limits,toolreq)=>{
    //Your Code There
});

举例来说,如果要注册通过木剑右键土方块有 20% 的概率获得树苗可以这么做


注意:你在此处注册的匿名函数会在进入存档后的第一次右键时被调用。

global.trashjs((gives,limits,toolreq)=>{
    gives.set('minecraft:dirt',new Map()); // 注册,固定格式:gives.set(<方块ID>,new Map());
    gives.get('minecraft:dirt').set('oak_sapling',[0.05,1]); // 添加掉落 固定格式:gives.get(<方块ID>).set(<物品ID>,[<掉落概率>,<掉落数量>])
    limits.set('minecraft:dirt',-1); // 设置可以右键无限次 固定格式:limits.set(<方块ID>,<可以右键的次数>)(无限就设置成-1)
    toolreq.set('minecraft:dirt','minecraft:wooden_sword'); // 设置需要木剑 固定格式 toolreq.set(<方块ID>,<物品ID>)
});

UtilJS

  • 作者:Colinxu2020

  • 作用:把一些旧版 KJS 的实用方法移植到了 KJ6。

  • 协议:GNU Lesser Public License Version 3.0

  • 支持版本:KJS6

  • 运行位置:起始脚本

// Copyright© 2023 Colinxu2020
// 本程序是自由软件:你可以再分发之和/或依照由自由软件基金会发布的 GNU 宽松通用公共许可证修改之,无论是版本 3 许可证,还是(按你的决定)任何以后版都可以。
// 发布该程序是希望它能有用,但是并无保障;甚至连可销售和符合某个特定的目的都不保证。请参看 GNU 宽松通用公共许可证,了解详情。
// 你应该随程序获得一份 GNU 宽松通用公共许可证的复本。如果没有,请看 <https://www.gnu.org/licenses/>。
// This program is free software: you can redistribute it and/or modify it under the terms of the GNU Leser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License along with t

var server_cache = undefined;
global.server = function(lv){
    if(lv==undefined){
        return null;
    }
    if(server_cache!=undefined)return server_cache;
    if(lv.ANONYMOUS_PLAYER_PROFILE!=undefined){
        server_cache = lv;
        return server_cache;
    }
    if(lv.getLevel!=undefined){
        lv = lv.getLevel();
    }
    if(lv.getServer==undefined){
        return null;
    }
    server_cache = lv.getServer();
    return server_cache;
}
global.runCommand = function(lv, cmd){
    if(cmd == undefined)cmd = lv, lv=undefined;
    var server = global.server(lv);
    if(server == null)return null;
    return server.getCommands().performCommand(server.createCommandSourceStack(), cmd);
}
global.runCommandSilent = function(lv, cmd){
    if(cmd == undefined)cmd = lv, lv=undefined;
    var server = global.server(lv);
    if(server == null)return null;
    return server.getCommands().performCommand(server.createCommandSourceStack().withSuppressedOutput(), cmd);
}

API用法:

获取服务器:

global.server(event); // 通过事件查服务器
global.server(level); // 通过世界查服务器

执行指令:

global.runCommand(server_or_level_or_event, command)

执行指令(无显示):

global.runCommandSilent(server_or_level_or_event, command)