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()可為 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 與宿主服務 —— 模組邊界的完整契約。