Skip to content

脚本方块实体渲染器 ​

Since Minecraft 1.21.1 / MBD2 21.1.1

客户端脚本可以注册命名的渲染回调。机器状态再通过 Custom Script 渲染器指向其中一个,回调就能用机器的 PoseStack 和 MultiBufferSource 画任意东西。

这是模型和 GeckoLib 动画都表达不了的视觉效果的出口——光束、激光、投影全息、线框。

1. 注册渲染器 ​

registerCustomRenderers 在客户端脚本加载完成后触发,它不针对某台机器。

js
// kubejs/client_scripts/mbd2_renderers.js
const BeaconRenderer = Java.loadClass('net.minecraft.client.renderer.blockentity.BeaconRenderer')

MBDClientEvents.registerCustomRenderers(event => {
  event.register('mypack:beam', ctx => {
    BeaconRenderer.renderBeaconBeam(ctx.poseStack, ctx.bufferSource, BeaconRenderer.BEAM_LOCATION,
      ctx.partialTick, 1, ctx.gameTime, 0, 256, ctx.data.getInt('color'), 0.2, 0.25)
  }).viewDistance(256).boundingBoxInflate(0, 256, 0)
})

register(name) 返回一个 builder;register(name, callback) 是 register(name).onRender(callback) 的简写。

2. 让机器指向它 ​

在机器编辑器里把某个状态的渲染器设为 Custom Script,从下拉里选择已注册的名字,并填写可选的 data 复合标签。查找是逐帧进行的,所以改完脚本重载客户端资源(F3+T)即可生效,不用动机器定义。

data 是交给回调的自由格式 NBT,所以一份脚本可以服务多台机器:

js
MBDClientEvents.registerCustomRenderers(event => {
  event.register('mypack:beam', ctx => {
    const height = ctx.data.contains('height') ? ctx.data.getInt('height') : 64
    // draw something `height` blocks tall
  })
})

Builder ​

方法默认效果
onRender(callback)—必填;没有它的渲染器什么都不画
viewDistance(blocks)64距摄像机多远仍然绘制
renderOffScreen(bool)false包围盒离开屏幕后仍然绘制
boundingBox((be, data) => AABB)一个方块逐方块实体计算可见范围
boundingBoxInflate(x, y, z) / (amount)—在默认单方块盒上外扩
infiniteBoundingBox()—从不剔除;同时打开 renderOffScreen

优先用 boundingBoxInflate 而不是 infiniteBoundingBox:后者会把机器塞进全局方块实体列表。

渲染上下文 ​

字段类型
blockEntity正在渲染的方块实体——不一定是机器,也可能是代理部件
data渲染器实例上配置的 CompoundTag,永不为 null
partialTickfloat
poseStack一份独立的栈,已经带上当前变换
bufferSourceMultiBufferSource
packedLight、packedOverlayint
方法返回
getPos()BlockPos
getBlockState()BlockState
getLevel()可空的 Level
getMachine()MBDMachine,方块实体不是机器时返回 null
getGameTime()long,方块实体还没进入世界时为 0

抛异常的渲染器会被禁用

第一次异常会带堆栈记录下来,随后该渲染器在本次会话(或直到客户端脚本重载)内被跳过。这是有意的——坏脚本报告一次,而不是让游戏崩溃或每秒刷六十条日志。修好后重载客户端脚本即可恢复。

PoseStack 安全性

回调拿到的是一份独立的、已带当前变换的 PoseStack,所以脚本里不配对的 pushPose 不会触发原版的 "Pose stack not empty" 检查。

边界 ​

  • 仅客户端。这里不改变世界状态,需要改就用机器事件。
  • getMachine() 可能返回 null,读机器状态之前先判断。
  • 渲染器名字保存在机器定义里;在脚本里改名会让所有指向它的机器失效,下拉框会把旧名字显示为缺失。
  • 需要 KubeJS:custom_script 渲染器是以 modID = "kubejs" 注册的。

Released under the MIT License.