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