EM.Framework — 电竞经理2026模组共享框架目标游戏: 电竞经理2026 Steam零售版补丁1.0.4(Unity 6000.3.20f1 / IL2CPP元数据v39)
需要: BepInEx(IL2CPP,BE#785)
当前版本: 0.2.3
公告/通知:如果你有任何错误报告或想讨论任何内容,可以加入这个Discord服务器:
https://discord.gg/MgvmC9RE83
如果您有bug反馈或者交流的需求,您可以加入这个Discord服务器:
https://discord.gg/MgvmC9RE83
▶ 新内容(0.2.3 / 2026-07-23)兼容游戏 1.0.4 补丁。 该补丁将Unity引擎从6000.3.12f1升级到了6000.3.20f1,触发了每个插件兼容性自检中的Unity版本硬性校验(此前要求与6000.3.12f1完全匹配)。结果所有依赖此框架的插件被同时禁用,并降级为“仅警告,不打补丁”。
此版本放宽了Unity版本要求,从
“精确匹配”改为“按 6000.3. 前缀匹配”,因此 6000.3.x 的小版本游戏更新不再会禁用所有插件。钩子签名自检与存档保护逻辑保持不变——真正移动了钩子目标的大型更新仍会禁用插件以保障存档安全。
- 已在1.0.4游戏内验证:所有插件均报告Unity匹配=真,钩子签名自检11/11存在,全部正常加载,无错误。
- 反编译签名级差异交叉校验:1.0.4 未更改任何插件所依赖的钩子目标方法签名。
- 仅Unity版本判定条件发生了变化,未更改任何公共方法签名。 二进制兼容,不换行 对于现有插件。插件通过 GUID 依赖框架(无版本约束),因此其他内容无需更改——只需替换这五个框架文件。
如何更新: 用此包中的 EM.Framework 文件夹覆盖你游戏的 BepInEx/plugins/EM.Framework/ 目录。功能插件无需更改。
▶ 这是什么EM.Framework 是本工具包中所有模组共用的运行时基础。它为三个核心库(EM.Core / EM.Data / EM.Sdk)提供了一个具有 BepInEx 插件身份的宿主,因此每个功能插件都依赖它,并在游戏内共享同一份框架副本,而无需各自携带独立的副本。
它为什么存在: 在BepInEx运行时中,同一名称的程序集只会被加载一次——即最先遇到的那一份副本。当每个插件都附带自己的一份核心库副本时,按字母顺序更靠前的插件所提供的旧版本会胜出,而后续插件调用较新方法时就会抛出MissingMethodException/TypeLoadException。此框架在游戏中只保留恰好一份副本,从设计上消除了同名程序集遮蔽问题。
这五个文件:- EM.Framework.dll — 宿主插件(具有 BepInPlugin 标识,加载时打印一行版本信息,自身不安装任何钩子)。
- EM.Sdk.dll ——共同基础:钩子、兼容性门控、配置覆盖、本地化以及测试基类。
- EM.Core.dll — 纯逻辑:评级基线、兼容性检查、游戏常量(类型/方法名称的唯一真实来源),零Unity依赖。
- EM.Data.dll — 数据格式层:EMDB 打包/解包、玩家 CSV schema 等。
- BouncyCastle.Cryptography.dll — EM.Data 的传递依赖(AES-GCM)。
▶ 安装- 确保已安装 BepInEx(IL2CPP,BE#785)且游戏能正常启动。
- 将此包中的 EM.Framework/ 文件夹复制到游戏的 BepInEx/plugins/ 目录中。
- 将你想要的功能插件文件夹也复制到 BepInEx/plugins/ 中(每个功能插件文件夹只包含其自身的 dll)。
- 启动游戏并检查 BepInEx/LogOutput.log:EM.Framework 应先打印其版本行,然后各功能插件正常加载。
▶ 致模组作者:EM.Sdk API某个功能插件声明其依赖项的方式为
[BepInDependency(EM.Framework.FrameworkInfo.Guid)],然后调用 EM.Sdk 公开的各项能力。下方为概览(完整的逐项参考及最简代码见包内 docs/sdk-reference.en.md 与 docs/plugin-authoring.en.md)。
1) 身份与常量- EM.Framework.FrameworkInfo.Guid — 框架插件 GUID(在 [BepInDependency] 中引用它)。
- EM框架信息名称 — 显示名称“EM框架”。
- EM.Sdk.Sdk.PluginGuidPrefix — 官方模组GUID前缀 com.esportsmanager.modkit。
2) 兼容性检查 EM.Sdk.CompatibilityGate将每个插件的启动自检(读取运行中的 Unity 版本 + 哈希 global-metadata.dat + 关键钩子签名检查)合并为一次调用:在你的 Load() 中调用 CompatibilityGate.Check(Log, PluginName),返回一个 GateResult(Passed / UnityMatches / MetadataMatches / ReportedUnityVersion 等)。策略:Unity 版本是硬性门槛,按 6000.3. 前缀匹配(自 0.2.3 起);主要标准是 key hook 目标是否能按名称解析;metadata 哈希降级为已知/未知环境的备注,不再单独禁用。
3) 现成钩子(EM.Sdk.Hooks 命名空间;每个钩子通过幂等的 TryInstall(Harmony, ManualLogSource?) 安装,若目标缺失则返回 false 而非抛出异常)- 锦标赛钩子 — DataTournament.Finish:一场锦标赛刚刚结束。触发事件 OnTournamentCompleted,上下文为 TournamentInstance(原生 DataTournament)。
- 训练钩子 — TrainingEventEngine.NextDay:体力/属性训练日已推进。事件 OnDayAdvanced。
- 训练地图钩子 — MapTrainingEngine.NextDay:地图训练日推进。事件 OnDayAdvanced。
- 评分钩子 — MapRecord.GetImpactRating:事件式重塑(OnImpactRatingComputed、Postfix、编辑 Result)或引擎替换(InstallReplacer、Prefix 完全接管;返回 true 使用你的值,返回 false 则继续执行原逻辑)。
- 胜率插件 — MatchesEngine.GetTeamOneWinPercentage:快速/自动模拟胜率已计算,可重写。事件 OnWinPercentageComputed,上下文 Original / Result(均在 [0,1] 区间)/ RawWasPercent。
- 玩家导入钩子 — ImportDataEMDBPlayer.ImportCSVData:已导入一批EMDB玩家。事件 OnPlayersImported。
共享契约:上下文中的游戏对象以 object 形式传递,由订阅者进行强制转换;订阅者异常按订阅者隔离,绝不破坏游戏的关键路径。
4) 配置覆盖 EM.Sdk.Config一个L1覆盖引擎:加载em-overrides/*.json,进行校验,并分发到已注册的应用器,支持热重载。OverrideEngine.Register(IOverrideApplier) / Initialize(dir, log) / Reload(log)。内置BalanceApplier(评级部分,复用RatingHooks)和BuyConfigApplier(购买部分)。非常适合零代码行为调整模组。
5) 本地化 EM.Sdk.Localization语言包注入。LocalizationOverlay.LoadFrom(dir, log) 加载语言包(默认文件夹 em-locale);LocalizationInjector.Inject(localeCode, log) 将条目写入游戏当前 Unity StringTable(原生值路径,占位符可用;必须在主线程调用);LocalizationFunnel 是开发/回退值通道。
6) 测试基础 EM.Sdk.Testing游戏内自动化测试运行器基础设施(仅限开发使用,绝不出现在用户版本中):TestRunnerPluginBase / TestAssert / TestResults。
▶ 约定与边界- 该框架不改变任何游戏业务逻辑,仅提供入口点。评分计算、模拟和经济系统均保持原样。
- 所有类型/方法均按名称解析(Harmony AccessTools),绝不使用硬编码地址或偏移量;名称统一存放于EM.Core.GameConstants中作为唯一数据源。
- 钩子上下文中的游戏对象始终以对象形式承载,因此 EM.Sdk 在编译时无需引用游戏互操作程序集,从而能够持续适应游戏更新。
- 每个功能插件在加载时会运行兼容性自检;若不匹配,则降级为仅警告模式且不应用任何补丁,从而确保存档免受半兼容逻辑的影响。
许可证:MIT
EM.Framework — 电竞经理2026模组共享框架适配游戏:电竞经理2026 Steam 正版补丁 1.0.4(Unity 6000.3.20f1 / IL2CPP 元数据 v39)
前置:BepInEx(IL2CPP,BE#785)
当前版本:0.2.3
▶ 更新信息(0.2.3 / 2026-07-23)适配游戏补丁 1.0.4。该更新将 Unity 引擎从 6000.3.12f1 升级至 6000.3.20f1,触发了各插件兼容性自检中的 Unity 版本硬性门槛(此前要求精确等于 6000.3.12f1),导致依赖本框架的所有插件被整体误停用,退化为“只警告不打补丁”的状态。
本版把兼容自检的 Unity 版本判据从
将「精确等于某一版本」放宽为「按 6000.3. 前缀匹配」,使 6000.3.x 系列的游戏小版本跳动不再一次次卡停所有插件;hook 签名自检与存档保护逻辑保持不变,仍能在真正改动 hook 目标的大更新时停用以保护存档。
- 经真机验证(1.0.4):全部插件 Unity 匹配 = True、hook 签名自检 11/11 全部就位、各插件正常加载、无报错。
- 反编译签名级 diff 复核:1.0.4 未改动任何插件依赖的 hook 目标方法签名。
- 仅调整 Unity 版本判据,不改动任何公开方法签名,对既有插件二进制兼容、无破坏。各插件依赖方式(按 GUID 依赖、无版本约束)不变,直接替换本框架五个文件即可。
如何更新:用本包内 EM.Framework 目录整体覆盖游戏 BepInEx/plugins/EM.Framework/ 即可,功能插件无需改动。
▶ 这是什么EM.Framework 是本套件所有 mod 共用的运行时地基。它为三个核心库(EM.Core / EM.Data / EM.Sdk)提供一个具备 BepInEx 插件身份的宿主,让每个功能插件都依赖它、在游戏内共用同一份框架,而不再各自携带一份。
为什么需要它:BepInEx 运行时中,同名程序集只会加载最先遇到的那一份。早期每个插件各带一份三件套时,字母序靠前的旧副本会抢占加载,导致后加载的插件调用新方法时抛出 MissingMethodException / TypeLoadException。本框架让三件套全局只有一份,从结构上根治同名程序集抢占问题。
包内五个文件:- EM.Framework.dll — 框架承载插件(带 BepInPlugin 身份,加载时打一行版本日志,本身不装任何钩子)。
- EM.Sdk.dll — 共享地基:钩子、兼容自检门、配置覆盖、本地化、测试基类。
- EM.Core.dll — 纯逻辑层:评分基线、兼容判定、游戏常量(类名/方法名单一事实源),零 Unity 依赖。
- EM.Data.dll — 数据格式层:EMDB 打解包、选手 CSV schema 等。
- BouncyCastle.Cryptography.dll — EM.Data 的传递依赖(AES-GCM)。
▶ 安装- 确认已装好 BepInEx(IL2CPP,BE#785),游戏能正常启动。
- 将本包内的 EM.Framework/ 目录整体复制到游戏的 BepInEx/plugins/ 目录中。
- 把要用的各功能插件目录也拷进 BepInEx/plugins/(每个功能插件目录只含它自己的 dll)。
- 启动游戏,查看 BepInEx/LogOutput.log:应先看到 EM.Framework 打出版本日志,随后各功能插件正常加载。
▶ 面向 Mod 作者:EM.Sdk 提供的 API功能插件通过
[BepInDependency(EM.Framework.FrameworkInfo.Guid)] 声明依赖本框架,再调用 EM.Sdk 暴露的能力。以下为对外 API 概览(详见包内 docs/sdk-reference.md 与 docs/plugin-authoring.md,含最小可用代码)。
1) 框架身份与常量- 框架插件 GUID(功能插件在 [BepInDependency] 里引用它)。
- EM.Framework.FrameworkInfo.Name — 框架显示名“EM Framework”。
- EM.Sdk.Sdk.PluginGuidPrefix — 官方 mod GUID 前缀 com.esportsmanager.modkit。
2) 兼容性自检门 EM.Sdk.CompatibilityGate将“读取运行中的 Unity 版本 + 计算 global-metadata.dat 的 SHA-256 + 关键 hook 签名自检”这套启动自检统一收敛到一处,插件 Load() 里一行 CompatibilityGate.Check(Log, PluginName) 即可,返回 GateResult(Passed / UnityMatches / MetadataMatches / ReportedUnityVersion 等)。判定规则:Unity 版本按 6000.3. 前缀匹配(0.2.3 起)为硬性门槛;主判据为关键 hook 目标能否按名称定位;metadata 哈希降级为“已知/未知环境”信息,不再单独停用。
3) 现成钩子(EM.Sdk.Hooks 命名空间,均为 TryInstall(Harmony, ManualLogSource?) 幂等安装,找不到目标返回 false 不抛异常)- 锦标赛钩子 — 挂载 DataTournament.Finish:一个赛事刚结算完成。事件 OnTournamentCompleted,上下文 TournamentInstance(原生 DataTournament)。
- 训练钩子 — 挂 TrainingEventEngine.NextDay:体能/属性训练日推进结束。事件 OnDayAdvanced。
- 训练地图钩子 — 挂载 MapTrainingEngine.NextDay:地图训练日推进结束。事件 OnDayAdvanced。
- 评分钩子 — 挂 MapRecord.GetImpactRating:事件式重塑(OnImpactRatingComputed,Postfix 改 Result)或引擎替换式(InstallReplacer,Prefix 整体接管;回调返回 true 用替换值、false 放行原实现)。
- 胜率钩子 — 挂 MatchesEngine.GetTeamOneWinPercentage:快速/自动模拟胜率算完可改写。事件 OnWinPercentageComputed,上下文 Original / Result(均以 [0,1] 为口径)/ RawWasPercent。
- 玩家导入钩子 — 挂 ImportDataEMDBPlayer.ImportCSVData:一批 EMDB 选手导入完成。事件 OnPlayersImported。
钩子共有约定:上下文里的游戏对象以 object 承载、订阅方自行转型;订阅者异常被逐个隔离,绝不反向打断游戏关键路径。
4) 配置覆盖 EM.Sdk.ConfigL1 覆盖引擎:从 em-overrides/*.json 加载、校验后分发给注册的 applier,支持热重载。OverrideEngine.Register(IOverrideApplier) / Initialize(dir, log) / Reload(log)。内置 BalanceApplier(rating 段,复用 RatingHooks 重标定)与 BuyConfigApplier(buy 段)。适合“零代码改行为”的配置类 mod。
5) 本地化 EM.Sdk.Localization语言包注入能力。LocalizationOverlay.LoadFrom(dir, log) 加载语言包(默认目录 em-locale);LocalizationInjector.Inject(localeCode, log) 把条目写进游戏当前 Unity StringTable(走原生取值路径,占位符自然生效,须主线程调用);LocalizationFunnel 为开发/兜底取值漏斗。
6) 测试基类 EM.Sdk.Testing游戏内自动化测试运行器基础设施(仅供开发使用,不随用户版分发):TestRunnerPluginBase / TestAssert / TestResults。
▶ 约定与边界- 框架不改任何游戏业务逻辑,只提供接入点。评分数学、模拟、经济等一律不碰。
- 所有类型/方法一律按名解析(Harmony AccessTools),绝不硬编码地址或偏移;类名/方法名集中在 EM.Core.GameConstants 作为单一事实源。
- 钩子上下文里的游戏对象一律用 object 承载,订阅方自行转型——这样 EM.Sdk 不在编译期引用游戏 interop 程序集,抗游戏更新。
- 每个功能插件加载时进行兼容性自检;不匹配时降级为仅警告、不打补丁,以保护存档不被半兼容逻辑污染。
许可证:MIT