16 网络包和Painter API
一、网络包
事件:
客户端从服务端侧接收脚本player.data_from_server.<信道ID>
服务端从客户端侧接收脚本player.data_from_server.<信道ID>
// 监听玩家物品右键事件
// 你可以把下面这段脚本放到服务端或客户端脚本中,取决于你想从哪一侧发包
onEvent('item.right_click', event => {
// 监听物品右键事件
if (event.server) {
// 发送 {test: 123} 到信道 "test_channel_1". 信道ID可以为任何字符串, 但还是推荐使用蛇形命名方法
// 接收端为客户端 (发送端为服务端).
event.player.sendData('test_channel_1', { test: 123 });// 发包
} else {
// 推荐使用不同信道 尽管这不是必须的
// 收包 (发送端为客户端).
event.player.sendData('test_channel_2', { test: 456 })// 发包
}
})
// 监听从服务端收到网络包时的事件
// 这段是客户端脚本
onEvent('player.data_from_server.test_channel_1', event => {
log.info(event.data.test) // 打印网络包信息到日志(123)
event.player.tell(`来自客户端的网络包信息:${event.data.test}`)
})
// 监听从客户端收到网络包时的事件
// 这段是服务端脚本
onEvent('player.data_from_client.test_channel_2', event => {
log.info(event.data.test) // 打印网络包信息到日志(456)
event.server.runCommand(`say 来自服务端的网络包信息:${event.data.test}`)
})
二、Painter API
Painter API允许你在客户端屏幕上绘制内容,其可以从服务端控制也可以从客户端直接触发
目前(2022年5月10日)它不支持玩家输入/交互,但以后可能会支持游戏内菜单甚至是渲染引擎
Painter对象是以NBT/Json对象建立的,并且每一个都有自己的ID. 如果你没有提供一个的话,KubeJS就会随机生成一个. x
和 z
是对象在屏幕上的的绝对坐标, 但你能将元素对齐到屏幕的给定位置。你可以在一个json对象中添加多个对象. 所有的属性都是可选的,但是显然你至少应该填写坐标和大小等信息。
paint({...})
遵守更新插入法则,如果对象不存在则创建,若存在则更新其属性:
event.player.paint({example: {type: 'rectangle', x: 10, y: 10, w: 20, h: 20}}); // 新建矩形
event.player.paint({example: {x: 50}}); // 更新先前ID为example的Painter对象的x属性
你可以批量新建/修改Painter对象:
event.player.paint({a: {x: 10}, b: {x: 30}, c: {type: 'rectangle', x: 10}});
你可以使用remove
来移除Painter对象:
event.player.paint({a: {remove: true}}); // 移除ID为a的Painter对象
event.player.paint({a: {remove: true}, b: {remove: true}}); // 批量移除多个对象
event.player.paint({'*': {remove: true}}); //移除全部
还记得在1.1中提到的/kubejs painter <玩家名称> <PainterJS对象>
指令吗?它和上述的函数功能是一样的
/kubejs painter @p {example: {type: 'rectangle', x: 10, y: 10, w: 20, h: 20}}
如果创建对象时多次重复出现,推荐在玩家登录时创建对象并为其设置属性visible: false
,之后在合适时间将该属性改为true以取消隐藏。值得注意的是,Painter对象在玩家离开服务器时会被清除,所以你需要在每次玩家登录时重新为其添加Painter对象。
可用对象
Underlined objects are not something you can create
根
(可用于所有对象)
Boolean visible
屏幕对象
(可用于所有屏幕/2D内容)
Unit x // x坐标
Unit y // y坐标
Unit z // z坐标
Unit w // 宽度
Unit h // 高度
Enum alignX (支持 'left', 'center', 'right') // x方向对齐参数
Enum alignY (支持 'top', 'center', 'bottom') // y方向对齐参数
Enum draw (支持 'ingame', 'gui', 'always') // 绘制场景
Unit moveX
Unit moveY
Unit expandW
Unit expandH
正方形
Color color
String texture
Float u0
Float v0
Float u1
Float v1
渐变(gradient)
Color color
Color colorT
Color colorB
Color colorL
Color colorR
Color colorTL
Color colorTR
Color colorBL
Color colorBR
String texture
Float u0
Float v0
Float u1
Float v1
文本
Text text
Boolean shadow
Float scale
Color color
Boolean centered
官方示例
onEvent('player.logged_in', event => {
// 初始化Painter对象
event.player.paint({
example_rectangle: {
type: 'rectangle',
x: 10,
y: 10,
w: 50,
h: 20,
color: '#00FF00',
draw: 'always'
},
last_message: {
type: 'text',
text: 'No last message',
scale: 1.5,
x: -4,
y: -4,
alignX: 'right',
alignY: 'bottom',
draw: 'always'
}
})
})
onEvent('player.chat', event => {
// 更新 example_rectangle 的 x 值 和 last_message 文本的值为上次聊天文本
event.player.paint({example_rectangle: {x: '(sin((time() * 1.1)) * (($screenW - 32) / 2))', w: 32, h: 32, alignX: 'center', texture: 'kubejs:textures/item/diamond_ore.png'}})
event.player.paint({last_message: {text: `Last message: ${event.message}`}})
// 一次更新两个对象,这两种方式没有区别,你想用哪个都行
// event.player.paint({example_rectangle: {x: 120}, last_message: {text: `Last message: ${event.message}`}})
event.player.paint({lava: {type: 'atlas_texture', texture: 'minecraft:block/lava_flow'}})
})

// TODO: 18.3 Painter API示例:服务器挖掘排行榜(显示挖掘方块最多的人)
最后更新于
这有帮助吗?