mtr::Api 与 Java 互操作
热路径禁令

每次 Api 调用 = 一次 JSON 编码 + 反射 + JSON 解码往返。只在 create()、后台任务、或每秒屈指可数的低频调用里用;绝不放进逐绘制调用——历史上「每帧每车一次 Api」正是周期性 GC 卡顿的来源。高频数据读快照,高频绘制走记录流。

什么时候用 Api

需求通道
车辆 / 到站 / 电梯 / 装饰的逐帧状态快照包装器(零成本)
文字 / 贴图 / 模型 / 声音绘制绘制记录流(零 JVM 穿越)
脚本 input 配置、一次性资源创建、跨帧缓存的对象句柄Api(create 时调用,句柄存 State)
网络请求、文件、BackgroundWorker、声音管理器等深接口Api(后台任务中调用)

对象与调用

用当前帧的输入构造 Api;从根对象(context() / wrapper())、静态类或 new 出发导航:

struct State { mtr::Api::Object tracker; };

struct Example : mtr::PidsScript<State> {
    static constexpr auto ID = "example:arrivals";

    void create(mtr::PidsContext& ctx, State& state, const mtr::Pids&) override {
        mtr::Api api(ctx.input());
        state.tracker = api.create("StateTracker");            // new StateTracker()
        api.context().call("setZOrderStep", {0.0002});         // ctx.setZOrderStep(0.0002)
    }

    void render(mtr::PidsContext& ctx, State& state, const mtr::Pids&) override {
        mtr::Api api(ctx.input());
        auto arrivals = api.wrapper().call("arrivals");        // wrapper.arrivals()
        if (arrivals.call("size").as<int>() == 0) return;
        auto arrival = arrivals.call("get", {0});
        if (arrival.is_null()) return;

        auto text = api.call("Text", "create");                // new Text()
        text.call("text", {arrival.call("destination")});
        text.call("pos", {2.0, 3.0});
        text.call("draw", {api.context()});
    }
};
MTR_REGISTER_PIDS_SCRIPT(Example)
Api 成员作用
api.context() / api.wrapper()当前脚本的上下文 / 包装器(与 JS 同一对对象)
api.input()资源包声明里的 input JSON(= JS 的 SCRIPT_INPUT)
api.create(class, args)new 一个 Java 对象
api.call(class, member, args) / api.get(class, member)静态方法 / 静态字段
api.root(name)按名字取根对象:api.root("console")、api.root("Timing")…
Object 成员作用
obj.call(member, args)实例方法调用,返回新 Object
obj.get(member) / obj.set(member, value)字段读 / 写(含继承的公开成员、标准集合)
obj.as<T>()取原始值(int、double、bool、std::string…)
obj.is_null()可空判空
obj.enum_name()Java 枚举的名字(如 "BOAT")
obj.close()显式调用 close()(会话清理也会兜底关闭遗留资源)
句柄语义

Java 对象由会话按引用计数管理,句柄用十进制字符串表示;Object 析构即释放引用,把要跨帧保留的对象存进 State。数值 id(含 64 位)全程不丢精度。字段与方法按真实 Java 类型解析,含继承的公开成员与标准 Java 集合。

JS ↔ C++ 对照表

JavaScriptC++
Resources.id("example:file")api.call("Resources", "id", {"example:file"})
new Matrices()api.create("Matrices")
ctx.getRenderManager()api.context().call("getRenderManager")
obj.method(a, b)obj.call("method", {a, b})
obj.field / obj.field = vobj.get("field") / obj.set("field", v)
TransportMode.BOATapi.get("TransportMode", "BOAT")
SCRIPT_INPUTapi.input()(JSON 值)
console.log(...) / print(...)api.root("console").call("log", {...})
Timing.delta()api.root("Timing").call("delta").as<double>()
array.length / array[i]array.call("length") / array.call("get", {i})
include(...)C++ 编译期 #include

AWT 类用全限定名:java.awt.Color、java.awt.Font、java.awt.BasicStroke、java.awt.geom.AffineTransform。GraphicsTexture 的公开字段 graphics / bufferedImage 暴露真实 Java2D 对象。资源路径解析:Resources.idr 按本模块的声明路径解析(多库声明时各用各的);Resources.manager() 与 JS 在 MTR 4 上一样为 null。上游 v2.3.0-prerelease.2 新增的成员——Resources.id(id, suffix) 拼接形式、Resources.mgr() 别名(ANTE 资源包兼容)、VanillaText.withFont(String) 等字符串参数变体——经同一 JSON-RPC 通道开箱可用。上游文档标注为未实现的能力(车辆连接件的 drawConnModel / drawConnStretchTexture)本模组同样不虚构行为。

后台回调

Api::Callback 把 C++ 函数包装成 Java 函数式接口(Runnable / Consumer / Function…)。回调对象必须存活到 Java 不再可能调用为止——放进 State:

struct State {
    std::unique_ptr<mtr::Api::Callback> task;   // 保存到销毁
};

void create(mtr::PidsContext& ctx, State& s, const mtr::Pids&) {
    mtr::Api api(ctx.input());
    s.task = std::make_unique<mtr::Api::Callback>([api](mtr::Json) {
        auto response = api.call("Networking", "fetch",
                                 {"https://example.org/data"});
        // 把结果发布进自己的同步状态;render 里读
        return mtr::Json();
    });
    api.root("BackgroundWorker").call("submit", {*s.task});
}
  • render 与回调可能并发——共享可变 C++ 状态自己加锁。
  • 重载会先停回调、等在途调用返回,再销毁状态与卸载代码。
  • 后台准备好的 GPU 模型用 DynamicModelHolder.uploadLater 上传;直接 ModelManager.upload 仍要求 Java 渲染线程(从 create 或主线程回调里调用)。

覆盖范围

常用 API 面:console、Resources、ModelManager / Model / RawModel / RawMeshBuilder / DynamicModelHolder、Vector3f、Matrices、GraphicsTexture 与 Java2D、RenderManager / QuadDrawCall、SoundManager / TickableSoundInstance、MinecraftClient、PlayerEntity / ItemStack / VanillaText / VoxelShape、Files、Networking、BackgroundWorker、TextUtil / Timing / StateTracker / CycleTracker / RateLimit、DataReader、MTRClientData、TSC 数据类与 DisplayHelper。PIDS / 装饰 / 车辆的可调用成员清单记录在仓库的 bench/api-coverage.json,电梯以其 Java 包装器为准。

编译后可对照真实 MTR jar 审计你的调用面:

python native/bench/api_coverage.py \
    --classes fabric/build/classes/java/main \
    --jar path/to/mtr.jar
版本稳定性

MTRClientData 的内部字段与 JS 侧一样受版本稳定性限制;标注 deprecated 的方法仍可调用。快照与包装器里的等价数据优先——更快也更稳。


接下来:C ABI 与宿主服务 —— 模块边界的完整契约。