core 与 samp-node 的双向桥接

core 与 samp-node 的双向桥接 由 Archify 生成的时序图。 Load(ppData) 插件导出 InitializeOncePerProcess + NewIsolate CreateEnvironment(bootstrap) 后动态 import entry_file registerEvent + on(name, trigger) OnPlayerConnect(playerid) events[name]->call,AMX 参数转 V8 调用 trigger,跑中间件链 callNative(name, fmt, args) InvokeNativeArray 打到 open.mp 驱动事件循环,等 Promise 完成 把结果作为 0 / 1 返回给 open.mp 插件启动与 bootstrap 原生回调进入 JS 返回值回传 open.mp open.mp · 原生回调 · 时序参与者 open.mp 原生回调 samp-node · events.cpp · 时序参与者 samp-node events.cpp libnode V8 · nodeimpl Tick · 时序参与者 libnode V8 nodeimpl Tick 全局 samp · functions.cpp · 时序参与者 全局 samp functions.cpp @infernus/core · bus.ts trigger · 时序参与者 @infernus/core bus.ts trigger 图例 请求 返回 异步追踪 默认消息

bootstrap 做了什么

  • • LoadResource 进 while(esmLoading) 循环,调 Tick 并每毫秒让出 CPU,等模块加载完才返回
  • • bootstrap 设 ipv4first、import entry_file,再调 __internal_esmLoaded 结束等待
  • • 此后每帧 ProcessTick 驱动 Tick:微任务、uv_run(NOWAIT)、DrainTasks

core 怎么架在这层上

  • • core 的 defineEvent 在 import 时调 samp.registerEvent 与 samp.on
  • • 原生回调先经 convertAmxParamsToV8 把 AMX cell 转成 V8 值
  • • beforeEach 再解析成上下文对象,事件系统即注册表上的一层中间件

同步桥与边界

  • • 同一线程:没有跨线程队列,Tick 在服务器主线程上跑 JS
  • • async 监听器返回 Promise 时,循环驱动事件循环直到它完成:resolve 取其布尔值,reject 为 0
  • • callNative 按 i/f/s/a/v 传值、I/F/A/V/S 取回;callPublic 遍历所有 AMX