Skip to content

Releases

JCM v2.3.0-1.0.0

Choose a tag to compare

@github-actions github-actions released this 13 Nov 23:37

JCM Yanyang 2.3.0-1.0.0 正式版,基于上游 JCM v2.3.0。

主要更新

  • 新增屏蔽门 JS / C++ 脚本:玻璃与顶部面板可绑定专用脚本或脚本化 PIDS 预设,支持连续面板画布、服务端保存与同步,以及车站、线路、到站和门状态数据。
  • 修复屏蔽门朝向与上下半块分组、长段画布、门状态匹配、绑定同步和切换世界后的缓存问题;改进背板边界、渲染异常恢复与资源重载清理。
  • 加固脚本资源生命周期、文件访问与原生桥边界校验,修复重复站台、终点信息及模型向量顶点坐标,并改善文档站点的导航、复制与移动端交互。

下载与兼容

提供 12 个 jar:Minecraft 1.17.1、1.18.2、1.19.2、1.19.4、1.20.1、1.20.4,各含 Fabric / Forge 版本;另附 native SDK zip。

每个 jar 内置八个平台的原生桥:Windows、Linux、macOS 的 x64 / ARM64,以及 Android ARM64、iOS ARM64。C++ 资源包需提供对应平台的脚本模块。

依赖 MTR 4.0.5 ≤ 版本 < 4.1;Fabric 版另需 Fabric API。与原版 JCM 共用 jsblock,只能安装其中一个。实际画面仍受资源包、光影及运行环境影响。

开发文档 · 完整更新日志

JCM v2.3.0-prerelease.2-yanyang.1-hotfix.2

Choose a tag to compare

JCM Yanyang 2.3.0-prerelease.2-yanyang.1-hotfix.2 — 原生层两轮人工审查修复(8 项 + 3 项回归修复)的首次发布:直接调用模式的内存安全、模块内存治理、字符串缓存与阴影渲染等 11 项缺陷全部关闭。

第一轮:8 项审查修复(2×P1 + 5×P2 + 1×P3)

  • [P1] 直接调用模式 arena 偏移解析错误:C++ 直接调用结果布局为「偏移 0 状态码 / 偏移 4 记录数 / 偏移 8 起五组 arena 描述符」,而共享内存路径的描述符镜像在偏移 0——描述符解析现在显式接收起始偏移(shm 传 0、direct 传 8),状态码不再被拼成地址;绑定前校验地址/长度/容量组合,杜绝 limit > capacity 的 NIO 视图。
  • [P1] 桥接层记录类型最小长度校验:patch_frame_handles 此前仅检查 8 字节记录头就强转 JcmDrawModel / JcmDrawTextureUpload 访问字段——现在按 kind 校验 record_size ≥ sizeof(对应结构体),边界判断改用剩余字节数(不再有可溢出的指针加法),畸形记录零内存访问即停止。
  • [P2] 重载代际的模块堆内存滞留:SDK 新增可选导出 mtrCleanup(旧模块无此导出则行为不变),桥接在全部实例销毁且旧帧消费完毕后调用,释放模块级 HostBuffers 与峰值增长的像素 arena;代码映射与堆内存生命周期分离,keep-loaded 策略与 ABI 10 兼容性不变。
  • [P2] 合法空字符串中断 PIDS 帧:字符串区末尾的空串(offset == limit)是合法空范围,但旧哈希无条件 arena.get(offset) 抛越界异常、中断整帧并触发 4 秒错误退避——现在范围校验后长度为 0 直接返回共享空条目,不读 arena 任何字节。
  • [P2] 字符串缓存哈希集中冲突:哈希从「长度 + 首字节」改为完整 UTF-8 内容 FNV-1a(scratch 内直算、零新分配);等长中文站名不再集中到同一探测区间。
  • [P2] 原生装饰物脚本阴影阶段重复执行:fabric / forge 两端 RenderEyeCandyMixin 的原生分支补上与 JS 分支一致的阴影阶段保护——阴影 pass 不重跑脚本、不消费事件、不重放声音、不上传纹理,仅回放已捕获绘制。
  • [P2] 无原生脚本车辆的缓存无淘汰路径:脚本 ID 缓存增加独立存活信息(render 命中刷新),5 秒未见即清理,不再只能等资源重载;不禁止空结果缓存(避免每帧重建解析)。
  • [P3] 变换对象池回收滞留:TransformCapturePool.recycleAll 取出对象后立即置空 inFlight[i] 槽位——超上限对象不再被静态数组钉住,1024 上限真正生效。

第二轮:3 项回归修复(1×P1 + 2×P2,修复上一轮修复引入的问题)

  • [P1] 每帧重新 attach 丢失扩容像素 arena:install_frame 此前每帧调用 attach(),把像素 arena 重置回 1 MiB 内联块并清掉所有权标志——一旦像素数据超过 1 MiB,扩容出的堆内存下一帧即成无主泄漏。现在 attach 仅在首次分配(及 cleanup 后重分配)时执行一次,普通帧只 begin_frame();cleanup 时先 detach() 释放 recorder 拥有的增长块再删除 HostBuffers。
  • [P2] 字符串缓存满后新条目插入不可找回的位置:开放寻址表到达上限后,初始槽为空的新 key 会被放到后方占用槽,下次查找在初始空槽处提前退出、永远到不了新条目——相同文本从此每帧重复分配。改为 16 组 × 8 路固定分组缓存(总量仍 128):查找 / 插入 / 淘汰都只发生在本组 8 槽内,组满轮转淘汰一个槽位;空槽只记录候选位置、绝不提前结束扫描,刚插入的条目保证立即可查回。
  • [P2] 关闭一个句柄提前清理同一动态库的其他句柄:同一路径多次打开时系统加载器返回同一底层 DSO,多个模块句柄共享 SDK 的静态 recorder 与 HostBuffers——旧实现任一句柄关闭都调 mtrCleanup(),可能释放仍存活句柄正在使用的 arena(且各持不同的锁)。现在以加载器句柄为键共享锁与成功打开计数,只有最后一个句柄关闭才执行清理;锁序为「共享模块锁 → 注册表锁」,注册表条目随 keep-loaded 映射终身保留。

验证:ASAN 行为 harness(真实桥接,44 项:同库双句柄共享状态、兄弟句柄关闭不触发清理、末句柄恰清理一次、8 轮重开 + 双活句柄交替渲染、arena 容量跨 23 帧稳定零泄漏);字符串缓存行为套件(10312 项:5000 独立串 + 300 同首字节 CJK 突发全部即时可找回、占用精确封顶 128);native_regression / native_sdk_test / native_abi_layout(全部 ABI 偏移不变)/ native_ffm_test / native_poller_test 全绿。

交付物:12 个 jar(6 个 MC 版本 × Fabric / Forge,均内置 8 平台原生桥)+ native SDK zip。mod id 仍为 jsblock(与原版 JCM 互斥),依赖 MTR 4.0.5+;fabric 版另需 Fabric API。

JCM v2.3.0-prerelease.2-yanyang.1-hotfix.1

Choose a tag to compare

JCM Yanyang 2.3.0-prerelease.2-yanyang.1-hotfix.1 — yanyang.1 定向热修:MTR 4 原生路线类别(高铁 / 轻轨)流入换乘类型链,原版高铁、轻轨线路正确从车侧线路图去除;Axiom 区块批量编辑纳入开门方向重扫;iOS 交叉编译腿回归 macos-latest(arm)runner。

原版高铁 / 轻轨正确按类型隐藏(修复「线路图去不掉原版高铁、轻轨」)

车侧 LCD 换乘过滤按类型串判定,但 MTR 4 路线编辑器的原生「类别」(普通 / 通勤 / 区域 / 城际 / 高铁 / 轻轨,随 Route 与 VehicleExtraData 逐车同步)此前从不参与类型解析——解析链只查 MAGIC 边车覆盖,而 MAGIC 下拉框选中高铁 / 轻轨时恰好清除边车、只留原生枚举,这些线路在数据快照里全部退化为基础 train,于是按「保留原版默认 Train」规格随普通地铁一起放行。修复(产出串与既有词汇表完全一致,脚本侧零改动):

  • 类型解析新增原生 RouteType 入参:MAGIC 边车覆盖仍优先(镜像其 UI 优先级),其次非 NORMAL 原生类别产出 train_high_speed / train_light_rail 等键(与 MTR 自家 getRouteTypeKey() 同格式),NORMAL 仍为基础模式 id——vanilla 默认 Train 行为不变。
  • 三条数据链全部类型感知:服务端全量数据预解析(MTRDatasetHolder.addStation)、客户端有限数据拼装(buildLimitedStopsData,站内换乘两组 + 相连车站换乘)、车辆自身线路(VehicleExtraData 逐车同步的类别);类型串随 JSON 同步,新服务端 + 旧客户端同样正确。
  • MAGIC 未安装 / 未覆盖线路、pre-ABI-9 旧数据回退行为不变;train_high_speed / train_light_rail 本就在脚本侧隐藏集——车侧 LCD 线路图与开门换乘面板无需任何改动即恢复正确过滤。

开门方向重扫补上 Axiom 区块批量编辑

高度图追踪现在按改动块收敛 world / chunk / section 三级写入(Axiom set-block-buffer 批量放置的每个方块都会更新高度图),配合区块本地坐标、归属 chunk 路由与服务端线程守卫。手动编辑、WorldEdit、Mishang UC 摆放此前已经由 world-API 钩子覆盖,本次补齐批量写入的最后缺口——开门方向服务端记忆对区块编辑器的批量改动同样即时生效。

构建与工程

  • iOS 交叉编译腿回归 macos-latest(arm)runner:撤除 2026-10-28 / 10-30 两日 arm 供给拥堵期间临时钉上的 macos-15-intel(release.yml 与 complete-build.yml 同步撤除);iPhoneOS SDK 随 arm 宿主 Xcode 同样随附,cross 腿跳过 ctest 不变。
  • model-upload 测试台架补 JSUtil stub(恢复前置依赖齐备后的全绿)。
  • README 补记上游 prerelease.2 基线对照。

交付物:12 个 jar(6 个 MC 版本 × Fabric / Forge,均内置 8 平台原生桥)+ native SDK zip。mod id 仍为 jsblock(与原版 JCM 互斥),依赖 MTR 4.0.5+;fabric 版另需 Fabric API。

JCM v2.3.0-prerelease.2-yanyang.1

Pre-release

Choose a tag to compare

JCM Yanyang 2.3.0-prerelease.2-yanyang.1 — 上游 v2.3.0-prerelease.2 全量同步(61 个提交);脚本化 PIDS 文字乱飘修复;C++ SDK 与上游 API 面同步。

脚本化 PIDS 文字乱飘修复(yanyang.8 回归,jsblock:pids_1a 报告)

脚本化 PIDS 的文字与贴图随玩家移动满处乱飘、大小异常。根因:yanyang.8 的变换快照对象池在把 base 变换捕获进回收实例时只复制了 consumer 列表,丢失了 MTR 4 参构造器承载的世界锚点——锚点是 flush 时相机偏移补偿的唯一通道,丢失后每次绘制都渲染在渲染实体(相机)位置。修复:acquire() 现按上游 copy() 的字段语义重新播种锚点,保持零稳态分配;同因修复 eyecandy 变换缓存(世界坐标此前被错误塞进不参与补偿的 consumer,几何体被平移渲染实体位置)。车辆 / 电梯 / 原生脚本路径行为不变。新增 S6 / S7 回归测试(锚点存活 + 回收实例逐帧重锚定),六平台 CI 全绿,红绿验证确保旧代码必然触发断言。

上游同步:2.3.0-beta.3 → v2.3.0-prerelease.2(61 个提交)

  • 脚本执行防护:新增 scriptRateLimit 预设字段与全局速率限制;解析阶段超时不再挂起游戏;无限循环可被检测并中止。
  • 脚本诊断:解析错误以游戏内悬停文本展示;仅运行时错误输出 JS 堆栈;console 对象转 JSON 输出。
  • 脚本缓存:同一脚本不再重复编译(重载时重置);DataReader 运行时缓存按 tick 过期自动重置。
  • 脚本核心与 Rhino 解耦:ParsedScript 抽象化 + ScriptingLanguage 多语言地基(scriptLang 字段);Rhino 实现移入 core.rhinojs 包。
  • 脚本 API:PIDS 绘制类 Rectangle 更名 Rect(避免与 AWT 同名冲突);id() / idr() 长形式标记弃用,新增字符串等价形式与 JSUtil.parseId(支持 "./" 脚本相对路径);Resources.id(id, suffix)、Resources.mgr() 别名、Resources.ANTE_FLAG、Java 数组创建等 ANTE 兼容与工具 API;ConfigResponder(装饰物自定义配置注册)、SoundHelper / TickableSound 兼容层。
  • 渲染与修补(上游):MTR 4 著名的 BVE 电机声音卡死修复(被剔除车辆的声音不再永久滞留);Iris / OptiFine 阴影 pass 重复执行脚本修复扩展至电梯 / 车辆 / 装饰物 / PIDS 全部脚本渲染面;贴墙方块面朝向检查修复;GraphicsTexture 新增 fullAA() / noAA();装饰物配置界面重做(布尔开关、ConfigCheckbox、ANTE 多配置注册);运行时阶段读取资源不再抛 ConcurrentModificationException。
  • Forge(上游):mixin 构建设置修复,refmap 统一为 jsblock.refmap.json。
  • 翻译(上游):新增爱尔兰语(ga_ie)与捷克语(cs_cz);更新日语、简体中文。
  • 晏阳适配:上游全部改动与原生 C++ 脚本管线(车辆 / PIDS / 装饰物 / 电梯的 JS + C++ 混合条目)、零分配渲染路径、标识符缓存融合;willInvokeRender、takeFrom 交换、TransformCapturePool 等晏阳机制经新抽象层继续生效;yanyang 全部自有特性(共享内存 / FFM 双传输、C++ 原生脚本、服务端门向持久记忆、8 平台原生桥)完整保留。

C++ SDK:与上游 prerelease.2 JS API 面同步

  • 新增 mtr::Rect(上游 JS 类 Rectangle → Rect 的 C++ 对应物,按 RectangleWrapper 语义全量移植)。
  • Text / Texture / Rect 构建器新增 renderType(String);记录头 flags 字节承载 naturalLight()——结构体尺寸与字段偏移零变化,新旧模块与新旧宿主双向二进制兼容。
  • Gfx2D::full_aa() / no_aa()(一像素覆盖率抗锯齿,默认关闭)、EyeCandy::facing_angle()、mtr::StateTracker<T>(含上游新语义:set_state() 返回是否为进入该状态的首帧)。
  • 修复:Texture::draw 对未调用 .texture() 的构建器不再崩溃整个模块(跳过该记录);Java 回放此前静默丢弃渲染层字段的问题一并修复(旧记录零值恰好映射包装器默认值,行为不变)。

交付物:12 个 jar(6 个 MC 版本 × Fabric / Forge,均内置 8 平台原生桥)+ native SDK zip。mod id 仍为 jsblock(与原版 JCM 互斥),依赖 MTR 4.0.5+;fabric 版另需 Fabric API。

JCM v2.3.0-beta-2.yanyang.8

Pre-release

Choose a tag to compare

JCM Yanyang 2.3.0-beta-2.yanyang.8 — 脚本化 PIDS 渲染修复、开门方向服务端持久记忆、原生桥扩至 8 平台。

PIDS 文字渲染修复(yanyang.4 回归)

脚本化 PIDS 预设(内置 jsblock:pids_1a 及任何自定义 JS / C++ PIDS 预设)的文字与贴图此前按方块原始尺度渲染——文字约放大 96 倍、锚在方块原点,.matrices() 模型姿态丢失。现逐绘制调用捕获变换快照(回收式对象池,稳态零分配保持),缩放与定位恢复正确;JS 装饰物 / 车辆脚本的同源绘制一并修复。JSON 预设 PIDS(rv_pids / lcd_pids / 投影 PIDS 等)与车辆 LCD 不受影响。新增跨平台回归测试 scripted_render_semantics 防止再次回归。

开门方向:服务端持久记忆 + getDirectionOfDoorOpening()

  • 新脚本 API(JS / C++ 一致):返回 "not" / "left" / "right" / "all"——当前站停靠中(与车门开闭阶段无关)或正线运行时预测下一站开门侧;左右相对车头、不受倒行影响;纯查询,不改变 MTR 开门行为。
  • 服务端安装本模组时,预测由服务端逐线路持久记忆作答:首次启动全档扫描(未加载区块按需载入——客户端物理上做不到),站台增删改(含 WorldEdit / Axiom 批量编辑)增量重扫、拆除重建自动收敛,结果持久化在存档内——跨视距、跨会话生效。服务端未装时自动回退客户端视距内扫描。
  • 原生 C ABI 升至 11:车辆快照新增 door_direction 字段(ABI 9/10 旧模块照常工作);SDK 车辆包装类更名 mtr::Vehicle(mtr::Train 保留为别名)。

原生桥扩至 8 平台:windows-arm64

新增 windows-arm64 原生桥,并修复捆绑桥搜索在 ARM64 Windows 上错误指向 x64 DLL 的问题(x64 DLL 无法在 ARM64 JVM 进程内加载,此前该平台永远加载不到桥)。资源包 C++ 模块需提供 natives/windows-arm64/ 副本方可在此平台运行。

全模块执行与性能审计(20+ 项修复)

JS 捕获 / 回放线程竞争(可致渲染崩溃)、ARM64 结果槽内存序(JVM 崩溃向量)、Forge 端原生车辆视锥剔除从未生效、每部件每车厢全树重建、陈旧桥 15 秒冻结、字形掩码内存无上限、批量实例销毁单 tick 倾泻、门向扫描 O(P²) 等——完整清单见仓库 CHANGELOG.md 的 yanyang.8 章节。

交付物:12 个 jar(6 个 MC 版本 × Fabric / Forge,均内置 8 平台原生桥)+ native SDK zip。

JCM v2.3.0-beta-2.yanyang.7

Pre-release

Choose a tag to compare

JCM Yanyang 2.3.0-beta-2.yanyang.7 — 修复间歇性卡顿(yanyang.5 / yanyang.6 已随各自 tag 发布,此处一并概述)。

间歇性卡顿修复 (yanyang.7)

旧实例清扫把「离开视野」误当成「已销毁」:列车离开相机视锥 5 秒后,原生脚本实例即被整体释放(十余张 GL 纹理、全部已上传模型、脚本画布);重新入镜的第一帧一次性支付 mtrCreate + createResources + 整幅画布重绘。转头一次即触发多列车同时重建——多毫秒级掉帧、反复出现、日志无报错。

  • 清扫区分「存在」与「可见」:镜头后的列车实例保持热态,重新入镜零成本;仅当车辆真正离开客户端车辆列表 5 秒后才销毁(与 JS 车辆脚本行为一致)。
  • 空闲阀门 -Djcm.nativeIdleMillis(默认 90000)与热实例上限 -Djcm.nativeIdleMax(默认 32)约束不可见实例的内存占用;0 分别表示不按时限释放 / 不设上限。
  • 每 tick 销毁预算 2 个(旧者先),批量退出(世界卸载 / 切维度 / 断线)仍一次性冲刷;PIDS / 装饰 / 电梯清扫套用同一阀门。
  • 清扫工作以每分钟一行的聚合日志输出,销毁流量可直接观测。

LCD 黑屏修复 (yanyang.6)

列车离开视锥后 LCD 永久黑屏(数据正常、无报错)的根因是实例销毁与 Java 侧 id 缓存不同步:重新入镜后每帧携带已被桥遗忘的 id,桥返回 ERR_INSTANCE(4)。现销毁与缓存删除在同一临界区完成,快捷键重载亦接入完整 C++ 卸载路径;JDK 22+ 的共享内存访问器安装失败静默回退问题同步修复。

传输平面健壮性 (yanyang.5)

poller 线程不再被单次异常杀死、被放弃的共享内存区域自愈、CBQ 回调缓冲保留化消除 JVM 崩溃风险、模块回复长度全路径钳制;修复时序缺陷共 9 处,shm 协议(layout v2)不变。

交付物

12 个 jar(6 个 MC 版本 × Fabric/Forge,均内置 7 平台原生桥:windows-x64 / linux-x64 / linux-arm64 / android-arm64 / macos-x64 / macos-arm64 / ios-arm64)+ native SDK zip,见本 Release 附件与 Actions 产物。

JCM v2.3.0-beta-2.yanyang.6

Pre-release

Choose a tag to compare

JCM Yanyang 2.3.0-beta-2.yanyang.4 — GC 与稳态分配优化(yanyang.4):脚本渲染管线(JS + C++)的「捕获→回放」稳态分配降至接近零,从根源消除 GC 周期性停顿导致的瞬时卡顿;含 2 项新发现的正确性修复。本 Release 同时包含 yanyang.3(全代码库审计 + 7 平台原生矩阵)、yanyang.1 与 yanyang.2 的全部内容。

GC / 分配优化 (yanyang.4)

  • 变换隔离零拷贝:StoredMatrixTransformationsMixin(新增 mixin,双加载器)暴露 mark/truncate,ScriptRenderManager.invoke 不再为每个绘制调用做 storedMatrixTransformations.copy()(每车每帧 N 次「新对象 + 新 ObjectArrayList + 全元素拷贝」);NativeContentDriver 的逐上下文 transform.copy() 全部移除。
  • 原生绘制调用池化:NativeModelDrawCall / TextWrapper / TextureWrapper(原生记录回放创建的实例)经空闲链表复用,由每帧本就执行的 reset()/takeFrom() 释放回收;JS 脚本持有的 wrapper 不受影响。
  • 零拷贝捕获 takeFrom:ScriptRenderManager/ScriptSoundManager 交换内部列表取代逐车逐脚本的 copy()(VehicleScriptCallsHolder.Captured.capture、PIDSScriptInstance、EyeCandyScriptInstance、LiftScriptInstance);空声音帧不再分配。
  • 矩阵零分配:NativeModelDrawCall.pose 在捕获时把姿态矩阵拷入实例私有可增长存储,持久消费者回放时读取——取代每记录 float[count][16] + 每 pose lambda + 新 SMT(6 节列车 10 个模型记录 ≈ 60fps 下 460 KB/s 短命数组);GraphicsHolderMatrixMixin 复用渲染线程 JOML Matrix4f/Matrix3f。
  • 原生字符串与 Identifier 驻留(NativeStringCache / CachedIdentifiers):C++ 脚本每帧发出的相同字符串/字体 id/声音 id 不再重复解码与解析。
  • 跑马灯字形缓存(TextWrapper):每字符两次「格式化 + 测量」降为内容或样式变化时一次;PIDSDrawCall 的位置/层级消费者改为每实例一次分配。

正确性修复 (yanyang.4)

  • 跨车辆矩阵 arena 别名:C++ 帧的 arena 由模块持有、仅在下一次该模块渲染前有效,而车辆管线先捕获全部再逐车回放——两辆车共享同一脚本模块时回放会读到最后一辆车的矩阵。现捕获时即拷入实例私有存储,结构上不可能串车。
  • WeakHashMap 自引用泄漏(RenderEyeCandyMixin,双加载器):眼糖变换缓存的 lambda 捕获了作为弱键的方块实体,条目永不可回收。现仅捕获基本类型,且位置平移并入缓存,整个基础变换仅在 NBT 变化时重建。
  • 跑马灯缓存补上样式键(font/粗体/斜体):跨帧持有 wrapper 并改样式的 JS 脚本不再绘制过期格式。

yanyang.3 — 全代码库 bug 与性能审计:7 项关键修复 + 30 余项正确性/性能/加固修复;原生脚本平台矩阵扩展至 7 个平台(新增 Linux ARM64、Android、iOS/iPadOS)。

原生平台扩展 / Native platform matrix (yanyang.3)

  • 每个新 jar 内置 7 个平台的 JNI bridge:windows-x64、linux-x64、linux-arm64(ARM 桌面 + Pojav 类 Android 启动器的 glibc JVM)、macos-x64、macos-arm64、android-arm64(NDK arm64-v8a、16 KB page 对齐)、ios-arm64(Mach-O dylib,iOS 与 iPadOS 共用,侧载工具负责重签)。
  • 修复平台键把 Linux/Windows ARM64 一律归为 -x64 的旧 bug(ARM64 Linux 此前永远解析到错误目录);Linux+aarch64 环境按 linux-arm64 → ios-arm64 → android-arm64 依次回退,覆盖 iOS 沙箱内 os.name=Linux 的 JVM。
  • native SDK zip 同步附带 7 平台的示例模块预编译库。

关键修复 / Critical fixes (yanyang.3)

  • F3+T 资源重载从未真正重载 C++ 脚本:NativeScriptManager.reload() 是死代码——更新后的 .so/.dll 被静默忽略,且重载后 NativeHost 继续引用已被 ModelManagerJS.reset() 释放的模型(渲染线程 use-after-free)。现在重载会先释放全部模块再重新解析。
  • 模组记录流越界可崩溃整个 JVM:桥接层 patch_frame_handles 无边界校验地遍历模块提供的 record_count/record_size(在模块崩溃保护之外执行 memmove)。现已逐步校验。
  • 单个损坏的 MTR 4 脚本条目会中止整个资源包的解析(vehicle/eyecandy/lift 三类全部受牵连);NativeScriptManager.load() 遇到非法库标识符(大写路径等)直接逃逸。现逐条目隔离并跳过。
  • C++ Text/Texture 未设置的字段被清零覆盖:未设 color 完全透明、未设 scale 尺寸为零、未设 uv 退化、未设 align 居中——官方示例 pids_arrivals.cpp 即受影响。默认值现由单一来源提供。
  • Forge 端原生车辆脚本只捕获不渲染(VehicleResourceMixin 从未接入原生回放);Forge 端轨道裁剪逻辑反转(限内轨道永远渲染、从不遮挡剔除——原版上游同样存在)。
  • 阴影 pass(Iris/OptiFine)下车辆/电梯脚本每帧被驱动两次;骑乘中被视锥裁剪的电梯会冻结玩家;mtrDispose 永远拿到实例首帧的快照。
  • C++ SDK 访问器(Stop::interchange/exit、Exit::destination、StopList::at、Train::car、Train::rail_progress)全部补齐越界检查——脚本差一即越界读取快照 direct-ByteBuffer 并 SIGSEGV 整个 JVM。

性能 / Performance (yanyang.3):每车每帧一棵共享车厢位置树(原先每车 2N+1 棵,12 节列车 ≈ 每秒 1500 次全树重建)、仅对持有原生脚本的车辆计算视锥盒、零分配一次性追踪、rasterizeText 直读 int[]、gfx2d 复用草稿缓冲、泄漏修剪(SCRIPT_IDS/TRACED/CAR_POSITIONS)、失败加载负缓存、稳定临时文件名、clearDeadInstance 去快照化;font5x7 补齐小写 a-z(原先小写渲染为空白)。


**yanyang.2 — minecraft_custom_resources.json 脚本条目不再需要 language 字段:scriptLocations 逐条目自动判定语言,同一条目可混用任意数量的 JavaScript 与 C++ 脚本。

新版声明格式 / New declaration format

"vehicleScripts": [
    {
        "id": "cst_sp1900_lcd",
        "prependExpressions": ["print('Hello world')"],
        "scriptLocations": ["mtr:my_pack/js/sp1900_lcd/main.js", "mtr:my_pack/natives/sp1900_train_num"],
        "input": { "yearEra": 2004 },
        "dataFetchMode": "ALL"
    }
]
  • *.js(大小写不敏感)→ JavaScript;无扩展名 → C++ 平台无关 stem(natives/{platform}/lib*.so|*.dll|lib*.dylib 自动解析);.so/.dll/.dylib 完整路径与按平台映射表亦可用。
  • vehicle / lift / eyecandy / pids 四类脚本全部支持混合:JS 部分连接成单一 ParsedScript,C++ 模块全部挂到同一脚本 id;两侧各自捕获、各自回放,互不冲突;某一侧缺失或失败只跳过该侧(附提示),另一侧照常渲染。
  • PIDS 预设(joban_custom_resources.json)新增同样的 scriptLocations 键,与老的 scriptFiles 并存。
  • 老格式完全兼容:"language": "cpp" + nativeLibrary/nativeLibraries 仍是纯 C++ 条目(也可与 .js 混用);"language": "javascript" 强制全 JS;MTR 3 script_files 语义不变。
  • 混合电梯条目下内置渲染只抑制一次、乘坐移动每帧只应用一次;eyecandy 方块使用事件同时送达 JS 与 C++。

En (summary): script entries no longer declare language — each scriptLocations entry is auto-classified (*.js = JavaScript, anything else = a C++ module) and any number of both may be mixed in one entry. Vehicles, lifts, eyecandies and PIDS all support it; each side captures into its own replay registry (no draw-call conflicts) and a failed part degrades gracefully. Legacy language: "cpp" / nativeLibrary declarations keep working and may be combined with .js entries. PIDS presets gain the same scriptLocations key.

翻译对齐原版 / Translations aligned with upstream

  • 语言文件与原版 JCM(同样由 BugQuantumCore 维护翻译)逐键对齐、原版优先;本版采纳原版 main 的爱尔兰语(ga_ie)占位与捷克语新键。

保留的全部晏阳能力 / All Yanyang features retained

  • getTransportType() 返回 MAGIC MTR Addon 车辆类型 + 4 种基础类型(JS / Java / C++,ABI 9;可选反射集成,无硬依赖)。
  • 原生脚本零 GC 卡顿:StopsData 跨帧复用、零分配快照 Builder、JNI 边界收窄(无 256 KB 拷贝)、1 MB 按需像素 arena。
  • 原生车辆视锥剔除(VehicleCulling)与原版 beta.2 的 MTR 层剔除互补;ABI 6/7/8 模块与 ABI 9 并存。
  • 12 jar(6 MC 版本 × Fabric/Forge,各 ~24.6 MB,内置 4 平台 bridge)+ native SDK zip,随本 Release 附带。

JCM v2.3.0-beta-2.yanyang.5

Pre-release

Choose a tag to compare

JCM Yanyang 2.3.0-beta-2.yanyang.4 — GC 与稳态分配优化(yanyang.4):脚本渲染管线(JS + C++)的「捕获→回放」稳态分配降至接近零,从根源消除 GC 周期性停顿导致的瞬时卡顿;含 2 项新发现的正确性修复。本 Release 同时包含 yanyang.3(全代码库审计 + 7 平台原生矩阵)、yanyang.1 与 yanyang.2 的全部内容。

GC / 分配优化 (yanyang.4)

  • 变换隔离零拷贝:StoredMatrixTransformationsMixin(新增 mixin,双加载器)暴露 mark/truncate,ScriptRenderManager.invoke 不再为每个绘制调用做 storedMatrixTransformations.copy()(每车每帧 N 次「新对象 + 新 ObjectArrayList + 全元素拷贝」);NativeContentDriver 的逐上下文 transform.copy() 全部移除。
  • 原生绘制调用池化:NativeModelDrawCall / TextWrapper / TextureWrapper(原生记录回放创建的实例)经空闲链表复用,由每帧本就执行的 reset()/takeFrom() 释放回收;JS 脚本持有的 wrapper 不受影响。
  • 零拷贝捕获 takeFrom:ScriptRenderManager/ScriptSoundManager 交换内部列表取代逐车逐脚本的 copy()(VehicleScriptCallsHolder.Captured.capture、PIDSScriptInstance、EyeCandyScriptInstance、LiftScriptInstance);空声音帧不再分配。
  • 矩阵零分配:NativeModelDrawCall.pose 在捕获时把姿态矩阵拷入实例私有可增长存储,持久消费者回放时读取——取代每记录 float[count][16] + 每 pose lambda + 新 SMT(6 节列车 10 个模型记录 ≈ 60fps 下 460 KB/s 短命数组);GraphicsHolderMatrixMixin 复用渲染线程 JOML Matrix4f/Matrix3f。
  • 原生字符串与 Identifier 驻留(NativeStringCache / CachedIdentifiers):C++ 脚本每帧发出的相同字符串/字体 id/声音 id 不再重复解码与解析。
  • 跑马灯字形缓存(TextWrapper):每字符两次「格式化 + 测量」降为内容或样式变化时一次;PIDSDrawCall 的位置/层级消费者改为每实例一次分配。

正确性修复 (yanyang.4)

  • 跨车辆矩阵 arena 别名:C++ 帧的 arena 由模块持有、仅在下一次该模块渲染前有效,而车辆管线先捕获全部再逐车回放——两辆车共享同一脚本模块时回放会读到最后一辆车的矩阵。现捕获时即拷入实例私有存储,结构上不可能串车。
  • WeakHashMap 自引用泄漏(RenderEyeCandyMixin,双加载器):眼糖变换缓存的 lambda 捕获了作为弱键的方块实体,条目永不可回收。现仅捕获基本类型,且位置平移并入缓存,整个基础变换仅在 NBT 变化时重建。
  • 跑马灯缓存补上样式键(font/粗体/斜体):跨帧持有 wrapper 并改样式的 JS 脚本不再绘制过期格式。

yanyang.3 — 全代码库 bug 与性能审计:7 项关键修复 + 30 余项正确性/性能/加固修复;原生脚本平台矩阵扩展至 7 个平台(新增 Linux ARM64、Android、iOS/iPadOS)。

原生平台扩展 / Native platform matrix (yanyang.3)

  • 每个新 jar 内置 7 个平台的 JNI bridge:windows-x64、linux-x64、linux-arm64(ARM 桌面 + Pojav 类 Android 启动器的 glibc JVM)、macos-x64、macos-arm64、android-arm64(NDK arm64-v8a、16 KB page 对齐)、ios-arm64(Mach-O dylib,iOS 与 iPadOS 共用,侧载工具负责重签)。
  • 修复平台键把 Linux/Windows ARM64 一律归为 -x64 的旧 bug(ARM64 Linux 此前永远解析到错误目录);Linux+aarch64 环境按 linux-arm64 → ios-arm64 → android-arm64 依次回退,覆盖 iOS 沙箱内 os.name=Linux 的 JVM。
  • native SDK zip 同步附带 7 平台的示例模块预编译库。

关键修复 / Critical fixes (yanyang.3)

  • F3+T 资源重载从未真正重载 C++ 脚本:NativeScriptManager.reload() 是死代码——更新后的 .so/.dll 被静默忽略,且重载后 NativeHost 继续引用已被 ModelManagerJS.reset() 释放的模型(渲染线程 use-after-free)。现在重载会先释放全部模块再重新解析。
  • 模组记录流越界可崩溃整个 JVM:桥接层 patch_frame_handles 无边界校验地遍历模块提供的 record_count/record_size(在模块崩溃保护之外执行 memmove)。现已逐步校验。
  • 单个损坏的 MTR 4 脚本条目会中止整个资源包的解析(vehicle/eyecandy/lift 三类全部受牵连);NativeScriptManager.load() 遇到非法库标识符(大写路径等)直接逃逸。现逐条目隔离并跳过。
  • C++ Text/Texture 未设置的字段被清零覆盖:未设 color 完全透明、未设 scale 尺寸为零、未设 uv 退化、未设 align 居中——官方示例 pids_arrivals.cpp 即受影响。默认值现由单一来源提供。
  • Forge 端原生车辆脚本只捕获不渲染(VehicleResourceMixin 从未接入原生回放);Forge 端轨道裁剪逻辑反转(限内轨道永远渲染、从不遮挡剔除——原版上游同样存在)。
  • 阴影 pass(Iris/OptiFine)下车辆/电梯脚本每帧被驱动两次;骑乘中被视锥裁剪的电梯会冻结玩家;mtrDispose 永远拿到实例首帧的快照。
  • C++ SDK 访问器(Stop::interchange/exit、Exit::destination、StopList::at、Train::car、Train::rail_progress)全部补齐越界检查——脚本差一即越界读取快照 direct-ByteBuffer 并 SIGSEGV 整个 JVM。

性能 / Performance (yanyang.3):每车每帧一棵共享车厢位置树(原先每车 2N+1 棵,12 节列车 ≈ 每秒 1500 次全树重建)、仅对持有原生脚本的车辆计算视锥盒、零分配一次性追踪、rasterizeText 直读 int[]、gfx2d 复用草稿缓冲、泄漏修剪(SCRIPT_IDS/TRACED/CAR_POSITIONS)、失败加载负缓存、稳定临时文件名、clearDeadInstance 去快照化;font5x7 补齐小写 a-z(原先小写渲染为空白)。


**yanyang.2 — minecraft_custom_resources.json 脚本条目不再需要 language 字段:scriptLocations 逐条目自动判定语言,同一条目可混用任意数量的 JavaScript 与 C++ 脚本。

新版声明格式 / New declaration format

"vehicleScripts": [
    {
        "id": "cst_sp1900_lcd",
        "prependExpressions": ["print('Hello world')"],
        "scriptLocations": ["mtr:my_pack/js/sp1900_lcd/main.js", "mtr:my_pack/natives/sp1900_train_num"],
        "input": { "yearEra": 2004 },
        "dataFetchMode": "ALL"
    }
]
  • *.js(大小写不敏感)→ JavaScript;无扩展名 → C++ 平台无关 stem(natives/{platform}/lib*.so|*.dll|lib*.dylib 自动解析);.so/.dll/.dylib 完整路径与按平台映射表亦可用。
  • vehicle / lift / eyecandy / pids 四类脚本全部支持混合:JS 部分连接成单一 ParsedScript,C++ 模块全部挂到同一脚本 id;两侧各自捕获、各自回放,互不冲突;某一侧缺失或失败只跳过该侧(附提示),另一侧照常渲染。
  • PIDS 预设(joban_custom_resources.json)新增同样的 scriptLocations 键,与老的 scriptFiles 并存。
  • 老格式完全兼容:"language": "cpp" + nativeLibrary/nativeLibraries 仍是纯 C++ 条目(也可与 .js 混用);"language": "javascript" 强制全 JS;MTR 3 script_files 语义不变。
  • 混合电梯条目下内置渲染只抑制一次、乘坐移动每帧只应用一次;eyecandy 方块使用事件同时送达 JS 与 C++。

En (summary): script entries no longer declare language — each scriptLocations entry is auto-classified (*.js = JavaScript, anything else = a C++ module) and any number of both may be mixed in one entry. Vehicles, lifts, eyecandies and PIDS all support it; each side captures into its own replay registry (no draw-call conflicts) and a failed part degrades gracefully. Legacy language: "cpp" / nativeLibrary declarations keep working and may be combined with .js entries. PIDS presets gain the same scriptLocations key.

翻译对齐原版 / Translations aligned with upstream

  • 语言文件与原版 JCM(同样由 BugQuantumCore 维护翻译)逐键对齐、原版优先;本版采纳原版 main 的爱尔兰语(ga_ie)占位与捷克语新键。

保留的全部晏阳能力 / All Yanyang features retained

  • getTransportType() 返回 MAGIC MTR Addon 车辆类型 + 4 种基础类型(JS / Java / C++,ABI 9;可选反射集成,无硬依赖)。
  • 原生脚本零 GC 卡顿:StopsData 跨帧复用、零分配快照 Builder、JNI 边界收窄(无 256 KB 拷贝)、1 MB 按需像素 arena。
  • 原生车辆视锥剔除(VehicleCulling)与原版 beta.2 的 MTR 层剔除互补;ABI 6/7/8 模块与 ABI 9 并存。
  • 12 jar(6 MC 版本 × Fabric/Forge,各 ~24.6 MB,内置 4 平台 bridge)+ native SDK zip,随本 Release 附带。

JCM v2.3.0-beta-2.yanyang.4

Pre-release

Choose a tag to compare

JCM Yanyang 2.3.0-beta-2.yanyang.4 — GC 与稳态分配优化(yanyang.4):脚本渲染管线(JS + C++)的「捕获→回放」稳态分配降至接近零,从根源消除 GC 周期性停顿导致的瞬时卡顿;含 2 项新发现的正确性修复。本 Release 同时包含 yanyang.3(全代码库审计 + 7 平台原生矩阵)、yanyang.1 与 yanyang.2 的全部内容。

GC / 分配优化 (yanyang.4)

  • 变换隔离零拷贝:StoredMatrixTransformationsMixin(新增 mixin,双加载器)暴露 mark/truncate,ScriptRenderManager.invoke 不再为每个绘制调用做 storedMatrixTransformations.copy()(每车每帧 N 次「新对象 + 新 ObjectArrayList + 全元素拷贝」);NativeContentDriver 的逐上下文 transform.copy() 全部移除。
  • 原生绘制调用池化:NativeModelDrawCall / TextWrapper / TextureWrapper(原生记录回放创建的实例)经空闲链表复用,由每帧本就执行的 reset()/takeFrom() 释放回收;JS 脚本持有的 wrapper 不受影响。
  • 零拷贝捕获 takeFrom:ScriptRenderManager/ScriptSoundManager 交换内部列表取代逐车逐脚本的 copy()(VehicleScriptCallsHolder.Captured.capture、PIDSScriptInstance、EyeCandyScriptInstance、LiftScriptInstance);空声音帧不再分配。
  • 矩阵零分配:NativeModelDrawCall.pose 在捕获时把姿态矩阵拷入实例私有可增长存储,持久消费者回放时读取——取代每记录 float[count][16] + 每 pose lambda + 新 SMT(6 节列车 10 个模型记录 ≈ 60fps 下 460 KB/s 短命数组);GraphicsHolderMatrixMixin 复用渲染线程 JOML Matrix4f/Matrix3f。
  • 原生字符串与 Identifier 驻留(NativeStringCache / CachedIdentifiers):C++ 脚本每帧发出的相同字符串/字体 id/声音 id 不再重复解码与解析。
  • 跑马灯字形缓存(TextWrapper):每字符两次「格式化 + 测量」降为内容或样式变化时一次;PIDSDrawCall 的位置/层级消费者改为每实例一次分配。

正确性修复 (yanyang.4)

  • 跨车辆矩阵 arena 别名:C++ 帧的 arena 由模块持有、仅在下一次该模块渲染前有效,而车辆管线先捕获全部再逐车回放——两辆车共享同一脚本模块时回放会读到最后一辆车的矩阵。现捕获时即拷入实例私有存储,结构上不可能串车。
  • WeakHashMap 自引用泄漏(RenderEyeCandyMixin,双加载器):眼糖变换缓存的 lambda 捕获了作为弱键的方块实体,条目永不可回收。现仅捕获基本类型,且位置平移并入缓存,整个基础变换仅在 NBT 变化时重建。
  • 跑马灯缓存补上样式键(font/粗体/斜体):跨帧持有 wrapper 并改样式的 JS 脚本不再绘制过期格式。

yanyang.3 — 全代码库 bug 与性能审计:7 项关键修复 + 30 余项正确性/性能/加固修复;原生脚本平台矩阵扩展至 7 个平台(新增 Linux ARM64、Android、iOS/iPadOS)。

原生平台扩展 / Native platform matrix (yanyang.3)

  • 每个新 jar 内置 7 个平台的 JNI bridge:windows-x64、linux-x64、linux-arm64(ARM 桌面 + Pojav 类 Android 启动器的 glibc JVM)、macos-x64、macos-arm64、android-arm64(NDK arm64-v8a、16 KB page 对齐)、ios-arm64(Mach-O dylib,iOS 与 iPadOS 共用,侧载工具负责重签)。
  • 修复平台键把 Linux/Windows ARM64 一律归为 -x64 的旧 bug(ARM64 Linux 此前永远解析到错误目录);Linux+aarch64 环境按 linux-arm64 → ios-arm64 → android-arm64 依次回退,覆盖 iOS 沙箱内 os.name=Linux 的 JVM。
  • native SDK zip 同步附带 7 平台的示例模块预编译库。

关键修复 / Critical fixes (yanyang.3)

  • F3+T 资源重载从未真正重载 C++ 脚本:NativeScriptManager.reload() 是死代码——更新后的 .so/.dll 被静默忽略,且重载后 NativeHost 继续引用已被 ModelManagerJS.reset() 释放的模型(渲染线程 use-after-free)。现在重载会先释放全部模块再重新解析。
  • 模组记录流越界可崩溃整个 JVM:桥接层 patch_frame_handles 无边界校验地遍历模块提供的 record_count/record_size(在模块崩溃保护之外执行 memmove)。现已逐步校验。
  • 单个损坏的 MTR 4 脚本条目会中止整个资源包的解析(vehicle/eyecandy/lift 三类全部受牵连);NativeScriptManager.load() 遇到非法库标识符(大写路径等)直接逃逸。现逐条目隔离并跳过。
  • C++ Text/Texture 未设置的字段被清零覆盖:未设 color 完全透明、未设 scale 尺寸为零、未设 uv 退化、未设 align 居中——官方示例 pids_arrivals.cpp 即受影响。默认值现由单一来源提供。
  • Forge 端原生车辆脚本只捕获不渲染(VehicleResourceMixin 从未接入原生回放);Forge 端轨道裁剪逻辑反转(限内轨道永远渲染、从不遮挡剔除——原版上游同样存在)。
  • 阴影 pass(Iris/OptiFine)下车辆/电梯脚本每帧被驱动两次;骑乘中被视锥裁剪的电梯会冻结玩家;mtrDispose 永远拿到实例首帧的快照。
  • C++ SDK 访问器(Stop::interchange/exit、Exit::destination、StopList::at、Train::car、Train::rail_progress)全部补齐越界检查——脚本差一即越界读取快照 direct-ByteBuffer 并 SIGSEGV 整个 JVM。

性能 / Performance (yanyang.3):每车每帧一棵共享车厢位置树(原先每车 2N+1 棵,12 节列车 ≈ 每秒 1500 次全树重建)、仅对持有原生脚本的车辆计算视锥盒、零分配一次性追踪、rasterizeText 直读 int[]、gfx2d 复用草稿缓冲、泄漏修剪(SCRIPT_IDS/TRACED/CAR_POSITIONS)、失败加载负缓存、稳定临时文件名、clearDeadInstance 去快照化;font5x7 补齐小写 a-z(原先小写渲染为空白)。


**yanyang.2 — minecraft_custom_resources.json 脚本条目不再需要 language 字段:scriptLocations 逐条目自动判定语言,同一条目可混用任意数量的 JavaScript 与 C++ 脚本。

新版声明格式 / New declaration format

"vehicleScripts": [
    {
        "id": "cst_sp1900_lcd",
        "prependExpressions": ["print('Hello world')"],
        "scriptLocations": ["mtr:my_pack/js/sp1900_lcd/main.js", "mtr:my_pack/natives/sp1900_train_num"],
        "input": { "yearEra": 2004 },
        "dataFetchMode": "ALL"
    }
]
  • *.js(大小写不敏感)→ JavaScript;无扩展名 → C++ 平台无关 stem(natives/{platform}/lib*.so|*.dll|lib*.dylib 自动解析);.so/.dll/.dylib 完整路径与按平台映射表亦可用。
  • vehicle / lift / eyecandy / pids 四类脚本全部支持混合:JS 部分连接成单一 ParsedScript,C++ 模块全部挂到同一脚本 id;两侧各自捕获、各自回放,互不冲突;某一侧缺失或失败只跳过该侧(附提示),另一侧照常渲染。
  • PIDS 预设(joban_custom_resources.json)新增同样的 scriptLocations 键,与老的 scriptFiles 并存。
  • 老格式完全兼容:"language": "cpp" + nativeLibrary/nativeLibraries 仍是纯 C++ 条目(也可与 .js 混用);"language": "javascript" 强制全 JS;MTR 3 script_files 语义不变。
  • 混合电梯条目下内置渲染只抑制一次、乘坐移动每帧只应用一次;eyecandy 方块使用事件同时送达 JS 与 C++。

En (summary): script entries no longer declare language — each scriptLocations entry is auto-classified (*.js = JavaScript, anything else = a C++ module) and any number of both may be mixed in one entry. Vehicles, lifts, eyecandies and PIDS all support it; each side captures into its own replay registry (no draw-call conflicts) and a failed part degrades gracefully. Legacy language: "cpp" / nativeLibrary declarations keep working and may be combined with .js entries. PIDS presets gain the same scriptLocations key.

翻译对齐原版 / Translations aligned with upstream

  • 语言文件与原版 JCM(同样由 BugQuantumCore 维护翻译)逐键对齐、原版优先;本版采纳原版 main 的爱尔兰语(ga_ie)占位与捷克语新键。

保留的全部晏阳能力 / All Yanyang features retained

  • getTransportType() 返回 MAGIC MTR Addon 车辆类型 + 4 种基础类型(JS / Java / C++,ABI 9;可选反射集成,无硬依赖)。
  • 原生脚本零 GC 卡顿:StopsData 跨帧复用、零分配快照 Builder、JNI 边界收窄(无 256 KB 拷贝)、1 MB 按需像素 arena。
  • 原生车辆视锥剔除(VehicleCulling)与原版 beta.2 的 MTR 层剔除互补;ABI 6/7/8 模块与 ABI 9 并存。
  • 12 jar(6 MC 版本 × Fabric/Forge,各 ~24.6 MB,内置 4 平台 bridge)+ native SDK zip,随本 Release 附带。

JCM v2.3.0-beta-2.yanyang.3

Pre-release

Choose a tag to compare

JCM Yanyang 2.3.0-beta-2.yanyang.3 — 全代码库 bug 与性能审计(yanyang.3):7 项关键修复 + 30 余项正确性/性能/加固修复;原生脚本平台矩阵扩展至 7 个平台(新增 Linux ARM64、Android、iOS/iPadOS)。本 Release 同时包含 yanyang.1(原版 2.3.0-beta.2 整合)与 yanyang.2(scriptLocations 自动语言判定与 JS + C++ 混合条目)。

原生平台扩展 / Native platform matrix (yanyang.3)

  • 每个新 jar 内置 7 个平台的 JNI bridge:windows-x64、linux-x64、linux-arm64(ARM 桌面 + Pojav 类 Android 启动器的 glibc JVM)、macos-x64、macos-arm64、android-arm64(NDK arm64-v8a、16 KB page 对齐)、ios-arm64(Mach-O dylib,iOS 与 iPadOS 共用,侧载工具负责重签)。
  • 修复平台键把 Linux/Windows ARM64 一律归为 -x64 的旧 bug(ARM64 Linux 此前永远解析到错误目录);Linux+aarch64 环境按 linux-arm64 → ios-arm64 → android-arm64 依次回退,覆盖 iOS 沙箱内 os.name=Linux 的 JVM。
  • native SDK zip 同步附带 7 平台的示例模块预编译库。

关键修复 / Critical fixes (yanyang.3)

  • F3+T 资源重载从未真正重载 C++ 脚本:NativeScriptManager.reload() 是死代码——更新后的 .so/.dll 被静默忽略,且重载后 NativeHost 继续引用已被 ModelManagerJS.reset() 释放的模型(渲染线程 use-after-free)。现在重载会先释放全部模块再重新解析。
  • 模组记录流越界可崩溃整个 JVM:桥接层 patch_frame_handles 无边界校验地遍历模块提供的 record_count/record_size(在模块崩溃保护之外执行 memmove)。现已逐步校验。
  • 单个损坏的 MTR 4 脚本条目会中止整个资源包的解析(vehicle/eyecandy/lift 三类全部受牵连);NativeScriptManager.load() 遇到非法库标识符(大写路径等)直接逃逸。现逐条目隔离并跳过。
  • C++ Text/Texture 未设置的字段被清零覆盖:未设 color 完全透明、未设 scale 尺寸为零、未设 uv 退化、未设 align 居中——官方示例 pids_arrivals.cpp 即受影响。默认值现由单一来源提供。
  • Forge 端原生车辆脚本只捕获不渲染(VehicleResourceMixin 从未接入原生回放);Forge 端轨道裁剪逻辑反转(限内轨道永远渲染、从不遮挡剔除——原版上游同样存在)。
  • 阴影 pass(Iris/OptiFine)下车辆/电梯脚本每帧被驱动两次;骑乘中被视锥裁剪的电梯会冻结玩家;mtrDispose 永远拿到实例首帧的快照。
  • C++ SDK 访问器(Stop::interchange/exit、Exit::destination、StopList::at、Train::car、Train::rail_progress)全部补齐越界检查——脚本差一即越界读取快照 direct-ByteBuffer 并 SIGSEGV 整个 JVM。

性能 / Performance (yanyang.3):每车每帧一棵共享车厢位置树(原先每车 2N+1 棵,12 节列车 ≈ 每秒 1500 次全树重建)、仅对持有原生脚本的车辆计算视锥盒、零分配一次性追踪、rasterizeText 直读 int[]、gfx2d 复用草稿缓冲、泄漏修剪(SCRIPT_IDS/TRACED/CAR_POSITIONS)、失败加载负缓存、稳定临时文件名、clearDeadInstance 去快照化;font5x7 补齐小写 a-z(原先小写渲染为空白)。


**yanyang.2 — minecraft_custom_resources.json 脚本条目不再需要 language 字段:scriptLocations 逐条目自动判定语言,同一条目可混用任意数量的 JavaScript 与 C++ 脚本。

新版声明格式 / New declaration format

"vehicleScripts": [
    {
        "id": "cst_sp1900_lcd",
        "prependExpressions": ["print('Hello world')"],
        "scriptLocations": ["mtr:my_pack/js/sp1900_lcd/main.js", "mtr:my_pack/natives/sp1900_train_num"],
        "input": { "yearEra": 2004 },
        "dataFetchMode": "ALL"
    }
]
  • *.js(大小写不敏感)→ JavaScript;无扩展名 → C++ 平台无关 stem(natives/{platform}/lib*.so|*.dll|lib*.dylib 自动解析);.so/.dll/.dylib 完整路径与按平台映射表亦可用。
  • vehicle / lift / eyecandy / pids 四类脚本全部支持混合:JS 部分连接成单一 ParsedScript,C++ 模块全部挂到同一脚本 id;两侧各自捕获、各自回放,互不冲突;某一侧缺失或失败只跳过该侧(附提示),另一侧照常渲染。
  • PIDS 预设(joban_custom_resources.json)新增同样的 scriptLocations 键,与老的 scriptFiles 并存。
  • 老格式完全兼容:"language": "cpp" + nativeLibrary/nativeLibraries 仍是纯 C++ 条目(也可与 .js 混用);"language": "javascript" 强制全 JS;MTR 3 script_files 语义不变。
  • 混合电梯条目下内置渲染只抑制一次、乘坐移动每帧只应用一次;eyecandy 方块使用事件同时送达 JS 与 C++。

En (summary): script entries no longer declare language — each scriptLocations entry is auto-classified (*.js = JavaScript, anything else = a C++ module) and any number of both may be mixed in one entry. Vehicles, lifts, eyecandies and PIDS all support it; each side captures into its own replay registry (no draw-call conflicts) and a failed part degrades gracefully. Legacy language: "cpp" / nativeLibrary declarations keep working and may be combined with .js entries. PIDS presets gain the same scriptLocations key.

翻译对齐原版 / Translations aligned with upstream

  • 语言文件与原版 JCM(同样由 BugQuantumCore 维护翻译)逐键对齐、原版优先;本版采纳原版 main 的爱尔兰语(ga_ie)占位与捷克语新键。

保留的全部晏阳能力 / All Yanyang features retained

  • getTransportType() 返回 MAGIC MTR Addon 车辆类型 + 4 种基础类型(JS / Java / C++,ABI 9;可选反射集成,无硬依赖)。
  • 原生脚本零 GC 卡顿:StopsData 跨帧复用、零分配快照 Builder、JNI 边界收窄(无 256 KB 拷贝)、1 MB 按需像素 arena。
  • 原生车辆视锥剔除(VehicleCulling)与原版 beta.2 的 MTR 层剔除互补;ABI 6/7/8 模块与 ABI 9 并存。
  • 12 jar(6 MC 版本 × Fabric/Forge,各 ~24.6 MB,内置 4 平台 bridge)+ native SDK zip,随本 Release 附带。