mtr::Api 與 Java 互通
JavaScript 腳本所得訪之公開 Java API,C++ 一無所缺。Api 所呼者,與 JS 同批之公開物件也——非使 C++ 以行 JavaScript 也。
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++ 對照表
| JavaScript | C++ |
|---|---|
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 = v | obj.get("field") / obj.set("field", v) |
TransportMode.BOAT | api.get("TransportMode", "BOAT") |
SCRIPT_INPUT | api.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() 於 MTR 4,與 JS 同為 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 與宿主服務 —— 模塊疆界之全約也。