tdimino/bg3se-macos
GitHub: tdimino/bg3se-macos
将 Windows 版博德之门 3 脚本扩展器完整移植到 macOS 平台,通过 DYLD 注入和 ARM64 Hook 技术实现约 94% 的 API 功能对等,使依赖脚本扩展的 Mod 能在 Mac 上正常运行。
Stars: 30 | Forks: 5
# BG3SE-macOS
**《博德之门 3》macOS 脚本扩展器**
一款原生的 macOS 版 BG3 Script Extender 实现,致力于全面实现与 Norbyte 的 Windows 版 BG3SE 的功能对等。使需要脚本功能的 Mod 能够在 Mac 上运行——包括随从 Mod、游戏性调整、UI 增强等。
## 快速入门
### 系统要求
- macOS 12+(已在 macOS 15.6.1 和 macOS 26.2 Tahoe 上测试)
- Apple Silicon Mac(推荐)或 Intel Mac(功能受限)
- 《博德之门 3》(Steam 版)
- Xcode 命令行工具:`xcode-select --install`
- CMake:`brew install cmake`
### 构建与安装
```
# 使用 submodules 进行 Clone
git clone --recursive https://github.com/tdimino/bg3se-macos.git
cd bg3se-macos
# 如果您已经 clone 但没有使用 --recursive:
git submodule update --init --recursive
# 使用 CMake 进行 Build
mkdir -p build && cd build
cmake ..
cmake --build .
```
### 验证构建是否成功
```
# 检查输出文件是否存在(应该约为 3MB 的 universal binary)
ls -la build/lib/libbg3se.dylib
# 验证架构(应显示 arm64 和 x86_64)
file build/lib/libbg3se.dylib
```
### 配置 Steam 启动选项
1. 在 Steam 中右键点击 **Baldur's Gate 3** → **属性**
2. 在 **常规** → **启动选项** 下,输入 `bg3w.sh` 的 **完整路径**:
/Users/YOUR_USERNAME/bg3se-macos/scripts/bg3w.sh %command%
**重要提示:** 请将 `YOUR_USERNAME` 替换为您实际的 macOS 用户名。示例:
/Users/john/bg3se-macos/scripts/bg3w.sh %command%
要查找您的路径,请在终端中运行此命令并复制输出:
echo "$(cd bg3se-macos && pwd)/scripts/bg3w.sh %command%"
### 构建问题排查
| 问题 | 解决方案 |
|---------|----------|
| `cmake: command not found` | 安装 CMake:`brew install cmake` |
| `CMake Error: could not find compiler` | 安装 Xcode 工具:`xcode-select --install` |
| 缺少 Dobby/Lua/lz4 错误 | 初始化子模块:`git submodule update --init --recursive` |
| 构建成功但没有 dylib | 检查 `build/lib/` 目录;确保构建已完成 |
| `CMake Error: source directory does not exist` | 移动仓库后存在过期的缓存。删除 `build/` 并重新构建:`rm -rf build && mkdir build && cd build && cmake .. && cmake --build .` |
| 代码更改未在游戏中生效 | CMake 缓存过期。删除 `build/` 目录并从头开始重新构建 |
### 使用 Script Extender Mod
Script Extender (SE) Mod 是需要 BG3SE 才能运行的 Mod——它们使用 Lua 脚本来添加标准 Mod 制作无法实现的功能。安装 BG3SE-macOS 后,这些 Mod 就能像普通 Mod 一样工作:
1. 从 [Nexus Mods](https://www.nexusmods.com/baldursgate3) **下载** Mod 的 `.pak` 文件
2. 将其放入 `~/Documents/Larian Studios/Baldur's Gate 3/Mods/` 进行 **安装**
3. 使用游戏内的 Mod 管理器(或诸如 [BG3 Mod Manager](https://github.com/LaughingLeader/BG3ModManager) 等 Mod 管理工具)**启用** 该 Mod
4. 通过 Steam **启动** 游戏(使用上述配置的启动选项)
### Mod 兼容性
大多数为 Windows 版 Script Extender 设计的 SE Mod 都可以在 macOS 上运行。我们正在积极测试热门 Mod 并追踪其兼容性:
| Mod | 作者 | 状态 | 备注 |
|-----|--------|--------|-------|
| [More Reactive Companions](https://www.nexusmods.com/baldursgate3/mods/5447) | LightningLarryL | ✅ 正常运行 | 队伍闲聊、随从反应 |
这只是一个示例——更多的 Mod 开箱即用。完整兼容性列表、测试说明及已知问题请参阅 **[docs/supported-mods.md](docs/supported-mods.md)**。
**测试过某个 Mod?** 请通过[报告您的结果](https://github.com/tdimino/bg3se-macos/issues/new?template=mod-compatibility.md)来帮助社区!无论它是完美运行还是存在问题,您的反馈都能帮助其他 Mac 玩家。
## 状态
**版本:** v0.36.50 | **功能对等度:** ~94%
| 功能 | 状态 |
|---------|--------|
| DYLD 注入 | ✅ 已完成 |
| Lua 运行时 | ✅ Lua 5.4 及 Ext API |
| Mod 加载 | ✅ PAK 文件读取,自动检测 |
| Ext.Osiris | ✅ 事件监听器,自定义函数 (NewCall/NewQuery/NewEvent/RaiseEvent/GetCustomFunctions),**服务器上下文守卫** |
| Ext.Entity | ✅ GUID 查找,**双 EntityWorld** (客户端 + 服务器),**1,999 个组件已注册** (534 种布局:169 个已验证 + 365 个自动生成),**1,577 个 ARM64 大小** + **702 个 Windows 估算** = **1,730 总计** (87% 覆盖率) |
| Ext.Stats | ✅ **100% 对等** — 15,774 项属性,Get/GetAll/Create/Sync,CopyFrom,SetRawAttribute,ExecuteFunctors,TreasureTable/TreasureCategory 桩代码 |
| Ext.Events | ✅ 33 个事件 (13 个生命周期 + 17 个引擎 + 2 个函子 + 1 个网络) 及 Prevent 模式,**运行时 Mod 归因** + `!mod_diag` |
| Ext.IO | ✅ LoadFile,SaveFile,**AddPathOverride,GetPathOverride** |
| Ext.Timer | ✅ WaitFor,WaitForRealtime,Cancel,Pause,Resume,**MicrosecTime,ClockEpoch,ClockTime,GameTime,DeltaTime,Ticks,持久计时器 (6 个函数)** |
| Ext.Vars | ✅ PersistentVars + 用户变量 + Mod 变量 |
| Ext.Input | ✅ 热键,按键注入 |
| Ext.Math | ✅ 向量/矩阵运算,**16 个四元数函数**,标量工具 |
| Ext.Enums | ✅ 14 种枚举/位域类型 |
| Ext.Types | ✅ 完整反射 API (9 个函数),用于 VS Code IntelliSense 的 **GenerateIdeHelpers** |
| Ext.StaticData | ✅ **全部 9 种类型** (专长、种族、背景、起源、神祇、职业、进度、行动资源、专长描述) 通过 ForceCapture 实现 |
| Ext.Resource | ✅ Get,GetAll,GetTypes,GetCount (34 种资源类型) |
| Ext.Template | ✅ **自动捕获**,迭代 (Cache/LocalCache),GUID 解析 |
| Ext.Level | ✅ **9 个函数** - RaycastClosest,RaycastAny,TestBox,TestSphere,GetHeightsAt,单例访问器 |
| Ext.Audio | ✅ **13 个函数** - PostEvent,Stop,PauseAll,ResumeAll,SetSwitch,SetState,SetRTPC,GetRTPC,ResetRTPC,LoadEvent,UnloadEvent |
| Ext.Net | ✅ **Phase 4I 完成** - 完整的 RakNet 后端,PostMessageToServer/User/Client,BroadcastMessage,IsHost,IsReady,PeerVersion,**请求/回复回调** |
| Ext.RegisterNetListener | ✅ 按频道划分的网络消息监听器 (MCM 骨干) |
| Net.CreateChannel | ✅ **Phase 4I 完成** - 高层 Channel API,包含 SetHandler、**SetRequestHandler**、SendToServer、**带回调的 RequestToServer**、Broadcast |
| Ext.Utils | ✅ Print,PrintWarning,PrintError,Version,MonotonicTime,GetGameState |
| Ext.ModEvents | ✅ 按 Mod 划分的跨 Mod 事件系统 (Subscribe,Throw,Unsubscribe) |
| Ext.Mod | ✅ IsModLoaded,GetLoadOrder,GetMod,GetBaseMod |
| 生命周期作用域 | ✅ 防止过期的对象访问 |
| 上下文系统 | ✅ **服务器/客户端上下文感知**,Ext.IsServer/IsClient/GetContext,两阶段引导 |
| 调试控制台 | ✅ 套接字 + 文件 + 游戏内覆盖层 |
| 崩溃归因 | ✅ **运行时 Mod 追踪** — 按处理程序划分的 Mod 名称,`!mod_diag` 控制台,软禁用,附带 Mod 上下文的增强型崩溃报告 |
| 测试 | ✅ `!test` 测试套件 (85 项测试),`!test_ingame` (40 项测试),Debug.* 助手,Frida 脚本 |
详细进展请参见 [ROADMAP.md](ROADMAP.md)。
## 文档
| 文档 | 描述 |
|----------|-------------|
| **[docs/supported-mods.md](docs/supported-mods.md)** | 已测试的 Mod 兼容性列表 |
| **[docs/getting-started.md](docs/getting-started.md)** | 安装、构建与首次运行 |
| **[docs/api-reference.md](docs/api-reference.md)** | 完整的 Ext.* 和 Osi.* API 文档 |
| **[docs/architecture.md](docs/architecture.md)** | 技术深潜:注入、Hook、ARM64 |
| **[docs/development.md](docs/development.md)** | 贡献、构建功能、调试 |
| **[docs/contributor-workflow.md](docs/contributor-workflow.md)** | 端到端指南:研究、Ghidra、实现 |
| **[docs/reverse-engineering.md](docs/reverse-engineering.md)** | Ghidra 工作流、偏移量发现 |
| **[docs/crash-attribution.md](docs/crash-attribution.md)** | Mod 崩溃归因:三层诊断 |
| **[docs/troubleshooting.md](docs/troubleshooting.md)** | 常见问题与解决方案 |
| **[docs/arm64/](docs/arm64/)** | ARM64 Hook 模式,预防策略 |
| **[docs/solutions/](docs/solutions/)** | 已记录的问题解决方案 |
## 实时控制台
有三种方式可以与 Lua 运行时交互:
1. **游戏内覆盖层** - 按 **Ctrl+`** 切换
2. **套接字控制台** - `./build/bin/bg3se-console`
3. **基于文件的控制台** - 写入至 `~/Library/Application Support/BG3SE/commands.txt`
```
# Socket 控制台(推荐用于开发)
./build/bin/bg3se-console
# 或者通过 socat
socat - UNIX-CONNECT:/tmp/bg3se.sock
```
## 文件结构
```
bg3se-macos/
├── src/
│ ├── injector/
│ │ └── main.c # Core injection, Dobby hooks, Lua state init
│ ├── core/
│ │ ├── logging.c/h # Structured logging (14 modules, 4 levels)
│ │ ├── safe_memory.c/h # Safe memory read/write (mach_vm)
│ │ └── version.h # Version info, data paths
│ ├── lua/
│ │ ├── lua_ext.c/h # Ext.Print, Ext.Utils, Ext.Memory
│ │ ├── lua_stats.c/h # Ext.Stats API
│ │ ├── lua_events.c/h # Ext.Events system
│ │ ├── lua_timer.c/h # Ext.Timer API
│ │ ├── lua_osiris.c/h # Osi.* namespace bindings
│ │ ├── lua_debug.c/h # Ext.Debug memory introspection
│ │ ├── lua_json.c/h # JSON encode/decode
│ │ ├── lua_resource.c/h # Ext.Resource bindings
│ │ ├── lua_template.c/h # Ext.Template bindings
│ │ ├── lua_staticdata.c/h # Ext.StaticData bindings
│ │ └── lua_persistentvars.c/h # Ext.Vars persistence
│ ├── entity/
│ │ ├── entity_system.c/h # Core ECS, Lua bindings
│ │ ├── guid_lookup.c/h # GUID parsing, HashMap ops
│ │ ├── arm64_call.c/h # ARM64 ABI wrappers (x8 indirect return)
│ │ ├── component_*.c/h # Component registry, lookup, TypeId
│ │ ├── generated_typeids.h # Auto-generated 1,999 TypeId addresses
│ │ ├── generated_component_registry.c # Auto-registration code
│ │ └── entity_storage.h # Storage structures, Ghidra base addr
│ ├── stats/
│ │ └── stats_manager.c/h # RPGStats access, property resolution
│ ├── strings/
│ │ └── fixed_string.c/h # GlobalStringTable resolution
│ ├── osiris/
│ │ ├── osiris_functions.c/h # Osiris function lookup/call
│ │ ├── osiris_types.h # FuncDef, OsiArgumentDesc structs
│ │ ├── custom_functions.c/h # Custom Osiris function registration
│ │ └── pattern_scan.c/h # Memory pattern scanning
│ ├── console/
│ │ └── console.c/h # Socket + file-based console
│ ├── input/
│ │ ├── input_hooks.m # macOS input event hooks
│ │ └── lua_input.c # Ext.Input API
│ ├── overlay/
│ │ └── overlay.m/h # In-game debug overlay (NSWindow)
│ ├── timer/
│ │ └── timer.c/h # Timer system implementation
│ ├── game/
│ │ └── game_state.c/h # Game state tracking
│ ├── mod/
│ │ └── mod_loader.c/h # Mod detection, PAK loading
│ ├── pak/
│ │ └── pak_reader.c/h # LSPK v18 PAK file parsing
│ ├── math/
│ │ └── math_ext.c/h # Ext.Math vector/matrix ops
│ ├── resource/
│ │ └── resource_manager.c/h # Ext.Resource (34 resource types)
│ ├── staticdata/
│ │ └── staticdata_manager.c/h # Ext.StaticData (Feats, etc.)
│ ├── template/
│ │ └── template_manager.c/h # Ext.Template (auto-capture)
│ └── hooks/
│ └── osiris_hooks.c/h # Osiris event interception
│
├── ghidra/
│ ├── scripts/ # Ghidra Python analysis scripts
│ │ ├── run_analysis.sh # Headless analyzer wrapper
│ │ ├── find_rpgstats.py # Discover gRPGStats global
│ │ ├── find_entity_offsets.py
│ │ └── ...
│ └── offsets/ # Discovered offset documentation
│ ├── STATS.md # RPGStats, FixedStrings (0x348)
│ ├── ENTITY_SYSTEM.md # ECS architecture
│ ├── RESOURCE.md # ResourceManager (0x08a8f070)
│ ├── TEMPLATE.md # Template managers
│ └── ...
│
├── docs/
│ ├── components/ # Component documentation by namespace
│ │ ├── README.md # Component reference overview
│ │ ├── eoc-components.md # 701 eoc:: components
│ │ ├── esv-components.md # 596 esv:: components
│ │ ├── ecl-components.md # 429 ecl:: components
│ │ └── ls-components.md # 233 ls:: components
│ └── ... # Other user-facing documentation
│
├── tools/
│ ├── bg3se-console.c # Standalone readline console client
│ ├── extract_pak.py # PAK file extractor
│ ├── extract_typeids.py # Generate TypeId header from binary
│ └── frida/ # Frida instrumentation scripts
│
├── scripts/
│ ├── build.sh # Build script
│ ├── bg3w.sh # Steam launch wrapper (ARM64)
│ ├── bg3w-intel.sh # Steam launch wrapper (Intel)
│ └── launch_bg3.sh # Direct launch for testing
│
├── lib/ # Third-party libraries
│ ├── Dobby/ # Inline hooking framework
│ ├── lua/ # Lua 5.4
│ └── lz4/ # Compression for PAK files
│
├── agent_docs/ # Claude Code context docs
├── plans/ # Implementation plans
└── test-mods/ # Test mod examples
```
## 致谢
### 特别感谢
如果没有 **[Norbyte](https://github.com/Norbyte)** 以及他们在原始 Windows 版 [BG3 Script Extender](https://github.com/Norbyte/bg3se) 上的开创性工作,这个项目是不可能实现的。他们对拉瑞安 Osiris 脚本引擎的逆向工程、全面的 API 设计,以及多年来对 Mod 社区的无私奉献,为这个 macOS 移植版奠定了基础。我们对他们为 BG3 Mod 生态系统所作出的开源贡献表示最深切的感激。
### 贡献者
- [Norbyte 的 BG3SE](https://github.com/Norbyte/bg3se) - 原始的 Windows 版 Script Extender
- [Dobby](https://github.com/jmpews/Dobby) - ARM64/x86_64 内联 Hook 框架
- [fishhook](https://github.com/facebook/fishhook) - 符号重绑定库
- [LZ4](https://github.com/lz4/lz4) - 用于 PAK 文件读取的快速压缩库
- [Dear ImGui](https://github.com/ocornut/imgui) - 调试覆盖层 UI 框架
## 许可证
MIT 许可证
## 作者
- Tom di Mino (曾用名 [Pnutmaster](https://wiki.twcenter.net/index.php?title=Blood_Broads_%26_Bastards) / [Nexus](https://next.nexusmods.com/profile/Pnutmaster/mods?gameId=130))
- [Claude Code](https://claude.ai/claude-code) (Anthropic)
### 附言
我还要感谢这篇 BG3SE issue 的发帖人和评论者:**["[Feature Bounty - $350] MacOS Supported Version of BG3 SE"](https://github.com/Norbyte/bg3se/issues/162)**。是你们开启了这项任务 :)
## 题词
标签:Apple Silicon, Baldur's Gate 3, Bash脚本, BG3, C++, CMake, CVE监控, dylib, Intel, Lua, Mod, RPG, Script Extender, Steam, UI增强, 动态链接库, 客户端加密, 开源, 数据擦除, 注入, 游戏修改, 游戏开发, 游戏模组, 游戏辅助工具, 脚本扩展器