ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

tModPorter 使用与原理全解:让 Terraria Mod 一键跟随 tModLoader API 演进

tModPorter 使用与原理全解:让 Terraria Mod 一键跟随 tModLoader API 演进 游戏开发插件系统【免费下载链接】tModLoaderA mod to make and play Terraria mods. Supports Terraria 1.4 (and earlier) installations项目地址https://gitcode.com/gh_mirrors/tm/tModLoader点击查看免费下载tModPorter 是 tModLoader 官方仓库中随发行版一并发布的迁移辅助工具它的唯一职责是帮助 Mod 开发者把因 tModLoader / Terraria API 变更而无法编译的旧代码自动改写为符合新 API 的代码。本文以仓库内 release_extras/tModPorter/README.md 为骨架结合其源码实现完整说明 tModPorter 的使用前置条件、运行方式、输出行为、备份机制与底层重写原理读完后你可以安全、正确地用它完成一次 Mod 升级。tModPorter 是什么只修编译错误的保守迁移器tModPorter 的目标很明确——帮助 Mod 跟上 tModLoader API 的变化原文档第一句即为此定位。它的设计哲学与普通一键升级工具不同有三条核心原则只修编译错误工具只处理导致编译失败的代码不主动重构你风格良好的既有代码无错不动如果项目没有编译错误运行后不会产生任何改动随时可安全运行因为改动是最小干预式的你可以在迁移过程中的任意时刻反复运行它。从源码看这一原则被贯彻到了执行层面。入口 Program.cs 捕获所有异常并打印随后等待按键退出核心处理类 tModPorter.cs 在整个处理流程中不断上报进度最终只统计changedDocs并汇报变了几个文件、花了多长时间。整个工具不会主动删除、移动或合并你的代码逻辑只做语义层面的符号改写。使用前置条件先把 .csproj 升级到 1.4 格式原文档明确列出了运行 tModPorter 之前必须满足的条件缺一不可.csproj 必须是 1.4 格式。判断标准是文件中包含类似下面这一行Import Project..\tModLoader.targets /如果你的 Mod 还是旧版1.3.x 时代的项目格式需要先在tML Mod 开发菜单tModLoader mod development menu里使用升级按钮把 .csproj 升级到 1.4 格式再运行 tModPorter。.csproj 应位于 ModSources 文件夹中。这是 tModLoader 约定的 Mod 源码目录确保能被 tModLoader 的构建目标tModLoader.targets正确解析引用。先打开 Visual Studio 检查项目确认项目没有任何未解析引用unresolved references警告后再运行工具。这一点尤其重要——从实现上看tModPorter.cs 通过MSBuildWorkspace加载项目如果项目本身引用缺失工作区加载阶段就会失败并直接抛出异常根本无法进入重写环节。具备 .NET 运行环境tModPorter 基于 Roslyn 编译平台实现。仓库中的 tModPorter.csproj 声明TargetFramework为net10.0依赖Microsoft.CodeAnalysis.CSharp.Workspaces、Microsoft.CodeAnalysis.Workspaces.MSBuild、Microsoft.Build.Locator以及UTF.Unknown等包因此运行机器上需要有可用的 .NET SDK/运行时。Linux 启动脚本 tModPorter.sh 会优先使用DOTNET_ROOT否则回退到~/.dotnet找不到dotnet时会给出明确提示并退出。运行方式拖放 .csproj或从命令行传入路径原文档提供了两种交互方式源码也完全支持拖放方式把.csproj文件直接拖到tModPorter.bat上运行命令行窗口方式先启动tModPorter.bat再把.csproj拖进命令行窗口回车。对应的启动脚本位于仓库 release_extras/tModPorter/tModPorter.batWindows与 tModPorter.shLinux/macOS。两者最终都会调用同一入口——Windows 脚本通过../start-tModLoader.bat -tModPorter %*把参数透传给 tModLoader 主程序Linux 脚本则直接执行$DOTNET_PATH tModLoader.dll -tModPorter $并把输出同时写入tModLoader-Logs/tModPorter.log。也就是说tModPorter 实际上是作为 tModLoader 的一个内置命令行子命令-tModPorter存在的。入口 Program.cs 的路径解析逻辑值得注意取命令行最后一个参数作为项目路径自动把路径扩展名强制替换为.csproj即使你传了.sln或没有扩展名如果该路径不存在会进入循环交互提示Enter the path to the .csproj of the mod you want to port:直到输入一个真实存在的.csproj路径。处理过程中控制台会实时显示进度[####------] Pass 1, 3/15之类的进度条与文件计数见 Program.cs。Linux 下若没有终端如双击脚本启动脚本会自动尝试用konsole、gnome-terminal、xterm或 macOS 的 Terminal.app 打开新窗口运行。执行过程多 Pass 语义重写与进度汇报真正干活的是 tModPorter.cs 中的Process方法它实现了一套多 Pass 迭代重写循环加载项目后先删除项目obj目录避免陈旧生成缓存干扰 Roslyn 语义分析删除失败仅警告不中断见 tModPorter.cs每一 Pass 内所有文档并行执行一次重写Task.Run并发处理各.cs文件由于更新语义模型semantic model是最昂贵的操作一旦某个文档语法树被改写它的语义模型就失效了——所以只要有任何文档发生变化本 Pass 就结束下一 Pass 只重跑本轮被改过的文档直到某轮没有任何文档再变化全部文档稳定后再对从未变化过的文档补跑一轮检查跨文档依赖例如一个文件里对另一文件内部符号的引用确保不留死角每轮 Pass 都会汇报Pass N, X/Y形式的进度。这个循环保证了重写是收敛的不会出现 A 改完、B 又基于旧语义改一遍导致连锁失效的情况也解释了为什么 README 说可以随时安全运行——每一轮都是全量语义重算后的稳定输出。备份机制.bak 文件与 Git 检测原文档最后一条规则是tModPorter 会为每个被修改的文件生成.bak备份除非.csproj的某个父目录中存在.git文件夹。源码实现印证了这条规则tModPorter.cs 与 tModPorter.csMakeBackups默认值由IsUnderGit(projectPath)决定——IsUnderGit会从 .csproj 所在目录逐级向上递归查找.git目录tModPorter.cs生成备份时若xxx.cs.bak已存在自动递增为xxx.cs.bak2、xxx.cs.bak3……绝不会覆盖旧备份备份采用先改名再写新文件的策略原文件被移动为.bak随后以原路径写入改写后的新内容。对使用 Git 管理源码的 Mod 来说改动历史由版本控制系统负责无需额外备份对没有 Git 的目录.bak文件就是你回退的最后保障。另一个细节是文件编码保护写入前会用CharsetDetectorUTF.Unknown库探测原文件编码置信度低于 95% 时给出警告随后以探测到的编码原样写回tModPorter.cs避免中文注释等非 UTF-8 内容被写坏。底层原理Roslyn 语法树 语义模型 重写器管线tModPorter 不是简单的文本替换而是基于 Roslyn.NET 编译器平台的语法树级语义重写。核心结构在 Config.cs它按固定顺序串联了 7 个重写器重写器职责HookRewriter改写 Mod 钩子方法override的签名、参数、返回类型、访问修饰符并同步改写方法体内对base.XXX(...)的调用参数RenameRewriter依据重命名表批量重命名类型、方法、字段、命名空间MemberTypeRewriter改写成员字段/属性的类型MemberUseRewriter改写成员访问的使用方式如把方法调用改属性、把布尔字段改 ID 常量等InvokeRewriter改写方法调用如Item.NewItem、SoundEngine.PlaySound等签名变化的调用RecipeRewriter改写合成配方Recipe相关 APIHookGenRewriter处理 HookGen 生成代码的重写所有重写器继承自 BaseRewriter.cs它基于CSharpSyntaxRewriter遍历语法树并通过GetSemanticModelAsync()取得语义模型来判断每个符号的真实类型、是否为无效符号IInvalidOperation或已过时IsObsolete——这正是只修编译错误的实现根基只有语义层面解析失败invalid或标记为 obsolete 的调用才会被重写见 BaseRewriter.cs。以 HookRewriter.cs 为例钩子签名改写会做三件事按基类新签名重排参数列表、修正返回类型、补齐override与访问修饰符若钩子在新版本中已删除还会在方法上附加一行注释说明替代方案HookRemoved。改写表本身集中在 Config.ModLoader.cs 与 Config.Terraria.cs 两个分部类中你可以直接查看当前版本 tModPorter 支持的完整迁移清单。迁移效果示例从重命名表看典型改动为了直观理解 tModPorter 会帮你做什么这里从源码中的重写表摘录几类典型迁移完整清单见 Config.ModLoader.cs 与 Config.Terraria.cs1. 字段命名规范化小写 → 大写属性风格// 旧写法1.3.x 时代 public class MyItem : ModItem { public override void SetDefaults() { item.width 32; // item 字段 item.maxStack 99; } }tModPorter 会把ModItem.item重命名为Item、ModNPC.npc重命名为NPC、ModPlayer.player重命名为Player、ModProjectile.projectile重命名为Projectile对应 Config.ModLoader.cs 的RenameInstanceField表同时把Terraria.Item.modItem、Terraria.NPC.modNPC等反向字段也一并更新。2. 类型整体改名// ModWorld → ModSystem public class MyWorld : ModSystem { ... } // ModHotKey → ModKeybind public class MyKeybind : ModKeybind { ... } // ModMountData → ModMount public class MyMount : ModMount { ... }对应 Config.ModLoader.cs 的RenameType表继承关系、引用处的类型标识都会被同步改写。3. 钩子方法改名 注释引导// NPCLoot → OnKillPreNPCLoot → PreKill public override void OnKill(NPC npc) { ... } // 若某个钩子在新版本中被移除会自动加上提示注释 // Note: Removed. Spawn the treasure bag alongside other loot via npcLoot.Add(ItemDropRule.BossBag(type))对应 Config.ModLoader.cs 的RenameMethod与HookRemoved机制。注意HookRewriter在管线中被刻意放在RenameRewriter之前Config.cs 的注释因为类型改名会改变钩子签名匹配顺序颠倒会导致参数重命名被跳过。4. 方法调用 → 属性Terraria.Tile 大量案例// 旧tile.active() → 新tile.HasTile // 旧tile.lava() → 新tile.LiquidType LiquidID.Lava // 旧tile.slope() → 新tile.Slope // 旧tile.wire2() → 新tile.BlueWire对应 Config.Terraria.cs 的GetterSetterToProperty/GetterToProperty表——这是 1.4 重构中改动面最大的部分手改极易遗漏交给工具处理最稳妥。5. 伤害/暴击字段 → 伤害类 API// 旧player.meleeDamage * 1.1f; // 新player.GetDamage(DamageClass.Melee) 0.1f; // 旧item.melee true; // 新item.DamageType DamageClass.Melee;对应 Config.Terraria.cs 的DamageTypeField与DamageModifier规则还会附带 Consider MeleeNoSpeed 之类的建议注释。质量保障自动测试与编译验证闭环tModPorter 的可靠性并非空口无凭仓库内置了完整的自动测试工程 tModPorter.TestsAutomaticTest.cs 会把测试数据源中的每个.cs文件反复执行RewriteOnce直到输出稳定与期望输出比对AutomaticTest.cs 的ExpectedModCompiles测试会加载Expected.csproj并调用 Roslyn 编译强制要求迁移后的产物能够编译通过——这正是工具核心目标的自动化验证ProjectWideRefactor测试则模拟真实的多文档项目级重写场景覆盖跨文件依赖AutomaticTest.cs。测试数据位于 tModPorter.Tests/TestData里面是成对组织的迁移前源码 / 期望输出如果你想精确了解某个 API 会被改写成什么样直接翻阅对应测试数据是最权威的方式。使用建议与注意事项综合原文档与源码给出如下实操建议先升级 .csproj 再运行1.4 格式含Import Project..\tModLoader.targets /是硬性前提旧格式项目会直接加载失败运行前保证项目可解析在 Visual Studio 里确认没有未解析引用警告源码会在EnsureTypesResolved阶段对无法解析的类型直接抛错并提示检查TargetFramework与项目引用HookRewriter.cs有 Git 就用 Git工具本身已按 Git 存在与否自动决定是否生成.bak但强烈建议在运行前先提交一次基线便于逐条 review 改动运行后仍需人工 reviewtModPorter 只解决编译错误。它会在无法自动改写的地方插入注释如 Suggestion: ...这些注释指向的新 API 用法需要你按注释与官方迁移指南手工补完逻辑例如被移除的Mod.Properties、ModTile.torch改用TileID.Sets.Torch、NPCSpawnInfo.PlanteraDefeated改用NPC.downedPlantBoss Main.hardMode等场景见 Config.ModLoader.cs可反复运行多 Pass 收敛式设计保证工具幂等安全一次迁移后如果又改了代码引发新错误再次运行即可。小结tModPorter 是 tModLoader 生态中API 迁移这一环节的官方解决方案以 .csproj 为输入单元以 Roslyn 语义分析保证只改编译错误以多 Pass 循环保证收敛以.bak/Git 双轨机制保证可回退。对 Mod 作者而言每次 tModLoader 大版本更新后的升级流程可以简化为升级 .csproj → 运行 tModPorter → 按注释人工补完 → 编译验证其中机械性的重命名与签名改写全部交给工具完成。如果你正在维护一个经历了 1.3 → 1.4 迁移的 ModREADME.md 给出的这四条规则加上 Config.ModLoader.cs 与 Config.Terraria.cs 里的完整迁移表就是你最值得收藏的参考资料。赞分享游戏开发插件系统【免费下载链接】tModLoaderA mod to make and play Terraria mods. Supports Terraria 1.4 (and earlier) installations项目地址https://gitcode.com/gh_mirrors/tm/tModLoader点击查看免费下载相关推荐Sketch批量重命名利器 - Rename It插件Sketch批量重命名利器 Rename It插件 在设计工作流程中保持文件和图层的良好组织性是提高效率的关键步骤。Rename It是一款专为Sketch设游戏开发插件系统nxadm/tail 文件跟踪库全解析从 ChangeLog 看 Go 日志跟随库的关键演进与核心实现nxadm/tail 文件跟踪库全解析从 ChangeLog 看 Go 日志跟随库的关键演进与核心实现 导读本文以 Cilium 仓库所 vendored云原生网络服务网格可观测性网络安全eBPF终极指南如何使用tModLoader解锁Terraria的无限可能终极指南如何使用tModLoader解锁Terraria的无限可能 tModLoader作为Terraria游戏最强大的开源模组加载器为玩家打开了通往无限创游戏开发插件系统上一篇三步在Windows上装好安卓应用APK-Installer 快速上手实践下一篇Wand-Enhancer 使用教程三步解锁 WeMod 高级功能还能用手机远程操控创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表