生命周期与线程
四个入口函数、调用时机、以及一个必须知道的事实:脚本不在主线程跑。
四个入口函数
function create(ctx, state, train) { }
function render(ctx, state, train) { }
function dispose(ctx, state, train) { }
function use(ctx, state, train, event) { }
| 函数 | 调用时机 |
|---|---|
create | 该车首次进入渲染范围时调用一次。用来初始化 state。 |
render | create 成功后每帧调用。 |
dispose | 该车不再需要渲染时调用。之后若再次进入范围,会重新走 create。 |
use | 玩家右键命中脚本登记的可点击区域时调用。见交互与 use 回调。 |
带后缀的变体
列车脚本的上下文类型名是 Train,所以下面这组函数名同样会被调用:
function createTrain(ctx, state, train) { }
function renderTrain(ctx, state, train) { }
function disposeTrain(ctx, state, train) { }
function useTrain(ctx, state, train, event) { }
两组都定义时两组都会执行(先无后缀、后带后缀)。 多个脚本文件里定义同名函数时,也是全部按加载顺序依次调用 —— 后者不会覆盖前者。
参数
| 参数 | 说明 |
|---|---|
ctx | 脚本上下文。承载绘制调用缓冲区等运行时对象。 |
state | 每辆车独立的空对象,跨帧保留。放你自己的状态。 |
train | 列车包装对象,见列车 API。 |
脚本跑在独立线程
脚本不在渲染主线程执行。
它被提交到专用线程池,与渲染并发。这带来两个后果。
后果一:不能直接碰渲染状态
要在主线程做的事,交给 MinecraftClient:
MinecraftClient.execute(function() {
// 这里在主线程
});
MinecraftClient.recordRenderCall(function() {
// 这里在渲染阶段
});
后果二:一帧可能跳过
上一帧的脚本还没跑完时,本帧不会重复提交。所以 render 的实际调用频率
不等于帧率。不要用调用次数当计时器 —— 用 Date.now()。
失败退避
脚本抛异常会被捕获并写日志。同一函数连续失败会被暂停一段时间, 避免坏脚本每帧每车抛异常拖垮整局游戏。
日志里搜 Error in RTE Resource Pack JavaScript 可看到栈。
修好后按 F7 重载即可恢复。
重载
按 F7 重载 RTE 客户端资源。脚本会被关闭并重新加载,
所有 state 清空,下一帧重新走 create。