模组:创建 SMAPI 模组

来自Stardew Valley Wiki
1059 Studio讨论 | 贡献2021年6月12日 (六) 06:43的版本 →‎疑难解答
跳到导航 跳到搜索

制作SMAPI模组 SMAPI mascot.png


模组:目录

要为游戏创建 SMAPI 模组?教程就在这儿。要使用模组,请参阅 使用指南。要创建内容包模组,请参阅 模组:Content Patcher

介绍

什么是 SMAPI 模组?

SMAPI 模组 使用改装接口来扩展游戏逻辑。可以在游戏中发生某些情况时做出响应(例如,将对象放置在世界中),定期运行代码(例如每个更新周期一次),更改游戏的资源和数据等。SMAPI 模组使用 C# 编写,使用 .NET Framework 和 Stardew Valley 将 XNA / MonoGame 用于游戏逻辑(绘制到屏幕,用户输入等)。

为什么模组使用 SMAPI?

SMAPI 可以做许多事情,例如:

  1. 将模组加载到游戏中。没有 SMAPI 就无法加载代码模组。
  2. 提供接口和事件,能够以其他方式与游戏互动。有一些简化的接口,可用于更改游戏资源/数据,玩家配置,转换,反映等。这些内容将在本指南的后面部分介绍。
  3. 在跨平台兼容时进行重构,这样一来就不必担心游戏在 Linux/Mac/Windows 版本之间的差异。
  4. 重构模组以更新它。在常见情况下,SMAPI 会检测并修复游戏更新所破坏的模组代码。
  5. 拦截错误。如果模组崩溃或发生错误,SMAPI 将拦截该错误,在控制台窗口中显示错误详细信息,并且在大多数情况下自动恢复游戏。这意味着减少游戏意外崩溃,并且可以更轻松地解决错误。
  6. 提供更新检查。当有新版本可用时,SMAPI 会自动提醒玩家。
  7. 提供兼容性检查。SMAPI 会自动检测模组何时不兼容,并在它导致问题之前将其禁用,以防止游戏爆炸。

我能制作一个模组吗?

是的!本指南将帮助你逐步创建一个简单的模组。然后你可以继续学习,让它做您想做的事即可。 如果你是编程新手,许多模组开发人员开始时几乎没有或完全没有编程经验。如果你下定决心,当然可以沿途学习,但是您应该为陡峭的学习曲线做好准备。刚开始时不要太过于自信,弄清楚它的时候,最好从一个小的模组开始。一开始很容易变得不知所措并放弃。模组社区非常热情,所以不要害怕问问题!

如果你已经具备编程经验,那应该没问题。具有 C# 或 Java 的编程经验将使事情变得容易,但这并不重要。如果不熟悉 C#,则可以浏览下面的“学习C#”参考资料以填补所有空白。

我可以不使用 SMAPI 来制作模组吗?

当然。许多的 SMAPI 模组支持 内容包,可以让你提供它们所使用的 JSON 文本文件、图像等。例如,你可以 使用 Content Patcher 来编辑游戏的贴图并且不需要任何编程技术。本指南的其余部分是关于创建新的 SMAPI 模组的。有关内容包,请参阅 模组:Content Patcher (或模组的文档(如果为其他mod创建内容包)).

我在哪里可以得到帮助?

星露谷模组社区欢迎你的到来. Feel free to ask for help in #making-mods on the Stardew Valley Discord.

开始

学习 C#

由于模组是用 C# 编写的,因此最好先熟悉它。无需记住所有内容,但是掌握基础知识(例如字段、方法、变量和类)将使其他所有内容都变得更加容易。

一些有用的资源:

要求

在你开始之前:

  1. 熟悉 模组的使用,本指南的其余部分假定你已经熟悉使用模组。
  2. 安装游戏
  3. 安装 SMAPI
  4. 安装开发环境

如果你不熟悉 Visual Studio (on Windows/Mac) 或者 MonoDevelop (on Linux), 模组:IDE 参考 解释了如何完成本指南所需的重要工作。

创建一个基础的模组

快速开始

如果你有足够的经验来跳过本教程,则此部分的简要概述如下:

快速开始 
  1. 创建一个空的 C#类库 项目
  2. 目标框架选择 .NET Framework 4.5 或者 4.5.1, 建议使用 4.5.2
  3. 参考 Pathoschild.Stardew.ModBuildConfig NuGet package 根据要在其上编译模组的平台自动添加正确的引用。
  4. 创建一个 ModEntry 类,该类将 StardewModdingAPI.Mod 子类化
  5. 覆写 Entry 方法,并使用 SMAPI events and APIs 编写代码
  6. 创建一个 manifest.json 文件 来描述了你的 SMAPI 模组
  7. 创建 一个包含模组文件的zip压缩包 来发布

创建解决方案

一个 SMAPI 模组是具有 SMAPI 调用入口方法的动态链接库(DLL),因此要对其进行设置

  1. 打开 Visual Studio 或者 MonoDevelop.
  2. 创建 类库 项目,选择 .NET Framework 框架 (参阅 如何创建一个项目)。确保你选择的是 .NET Framework 而不是 .NET Core 或者 .NET Standard
  3. 选择目标框架版本为 .NET Framework 4.5 或 4.5.1,使用 4.5.2 最佳 (参阅 如何改变目标框架)
  4. 添加 Pathoschild.Stardew.ModBuildConfig NuGet 包 (参阅 如何添加 NuGet 包).
  5. 安装完包之后重新启动 Visual Studio 或者 MonoDevelop

添加代码

接下来让我们添加一些将运行的 SMAPI 代码

  1. 删除 Class1.cs 或者 MyClass.cs 文件 (参阅 如何删除文件).
  2. 在项目中添加一个 C# 类文件,取名为 ModEntry.cs (参阅 如何添加文件).
  3. 在此文件中输入代码 (把 YourProjectName 换成你的解决方案的名字):
    using System;
    using Microsoft.Xna.Framework;
    using StardewModdingAPI;
    using StardewModdingAPI.Events;
    using StardewModdingAPI.Utilities;
    using StardewValley;
    
    namespace YourProjectName
    {
        /// <summary>模组入口点</summary>
        public class ModEntry : Mod
        {
            /*********
            ** 公共方法
            *********/
            /// <summary>模组的入口点,在首次加载模组后自动调用</summary>
            /// <param name="helper">对象 helper 提供用于编写模组的简化接口</param>
            public override void Entry(IModHelper helper)
            {
                helper.Events.Input.ButtonPressed += this.OnButtonPressed;
                //意思是将 OnButtonPressed 方法绑定到 SMAPI 的 ButtonPressed 按钮按下事件
                //this 表示本对象,也就是当前的 ModEntry 类
            }
    
    
            /*********
            ** 私有方法
            *********/
            /// <summary>在玩家按下键盘、控制器或鼠标上的按钮后引发</summary>
            /// <param name="sender">对象 sender 表示调用此方法的对象</param>
            /// <param name="e">对象 e 表示事件数据</param>
            private void OnButtonPressed(object sender, ButtonPressedEventArgs e)
            {
                // 如果玩家还没有进入存档,则取消执行
                if (!Context.IsWorldReady)
                    return;
    
                // 向控制台输出按下了什么按钮
                this.Monitor.Log($"{Game1.player.Name} 按下了 {e.Button}.", LogLevel.Debug);
            }
        }
    }
    

以下是该代码的功能细分:

  1. using X; (参阅 using directive) 使该命名空间中的类在你的代码中可用
  2. namespace YourProjectName (参阅 namespace keyword) 定义代码的范围,入门时不必担心,因为在新建类文件时 Visual Studio 或 MonoDevelop 会自动添加它
  3. public class ModEntry : Mod (参阅 class keyword) 创建你的模组的主类文件,并继承 SMAPI 的 Mod 类。SMAPI 将自动检测你的 Mod 子类,而 Mod 使你可访问 SMAPI 的接口
  4. public override void Entry(IModHelper helper) 是将模组加载到游戏中时 SMAPI 将调用的方法。这里的 helper 对象提供了对许多 SMAPI 接口的便捷访问
  5. helper.Events.Input.ButtonPressed += this.OnButtonPressed; 添加了一个 '事件绑定' (i.e. a method to call) 到当按下按钮的事件发生时. 换句话说,当一个按钮被按下 (也就是 helper.Events.Input.ButtonPressed 事件触发了), SMAPI 会调用你的 this.OnButtonPressed 方法。参阅 SMAPI 中的事件 获取更多信息

添加你的清单

模组的清单为 SMAPI 提供模组的信息

  1. 向你的解决方案添加一个名为 manifest.json 的文本文件
  2. 将这些代码复制到文件中:(注意要区分键值的大小写,避免出现意外情况)
    {
      "Name": "<模组的名字>",
      "Author": "<你的名字>",
      "Version": "1.0.0",
      "Description": "<一句话简单描述你的模组是干什么的>",
      "UniqueID": "<你的名字>.<模组的名字>",
      "EntryDll": "<你的解决方案的名字>.dll",
      "MinimumApiVersion": "3.0.0",
      "UpdateKeys": []
    }
    
  3. 正确填写其中的信息,不要留着空信息

当游戏启动时,它将在控制台中输出。更多信息请参阅 清单文档

构建你的模组

  1. 构建项目
    如果你不知道怎么构建:在开发工具的菜单栏中选择 项目,然后选择 生成
    如果你已经做了 创建解决方案 这一步,在构建时你的模组会自动安装到游戏的 Mods 文件夹中
  2. 通过 SMAPI 启动游戏

到目前为止,每当按下游戏中的一个键时,该模组会向控制台窗口发送一条消息

疑难解答

如果上述教程创建的模组不能正常运行:

  1. 重复查看以上步骤,以确保你没有跳过任何内容
  2. 检查是否有任何的错误消息,也许可以解释为什么它不起作用:
    • 在 Visual Studio 中尝试重新构建解决方案,查看 输出 面板 或者 错误列表
    • 在 MonoDevelop 中点击 Build > Rebuild All 等待处理完毕。然后点击 "Build: XX errors, XX warnings" 在顶部的条,点击 XX ErrorsBuild Output 选项卡
  3. 参阅 疑难解答.
  4. 如果其他所有方法均失败,请到 Stardew Valley Discord 寻求帮助 :)

常见问题

SMAPI 的文档在哪里?

这只是“入门”教程。更多信息请参阅 SMAPI referencetopics listed on the index page.

我如何使我的模组跨平台工作?

SMAPI 将自动调整模组使其可以在 Linux、MacOS 和 Windows 上运行。但是你也应该采取一些措施来避免出现问题:

  1. 使用 跨平台构建配置 包以自动设置您的项目引用,这使跨平台兼容性变得更容易,并使代码可以在任何平台上进行编译。(如果遵循上述指南,那么就没问题了)
  2. 使用 Path.Combine 构建文件路径,请不要对路径分隔符进行硬编码,因为它们不能在所有平台上都可使用
    // ✘ 不要这样做!这在 Linux 和 Mac 上不会起作用
    string path = this.Helper.DirectoryPath + "\assets\image.png";
    
    // ✓ 这样才是对的
    string path = Path.Combine(this.Helper.DirectoryPath, "assets", "image.png");
    
  3. 使用 this.Helper.DirectoryPath,请勿尝试自行确定模组路径
    // ✘ 不要这样做!如果 SMAPI 重写了程序集(例如对其进行了更新或跨平台),它将崩溃
    string modFolder = Assembly .GetCallingAssembly().Location;
    
    // ✓ 这样就没问题
    string modFolder = this.Helper.DirectoryPath;
    

如何反编译游戏代码?

观察游戏代码的工作方式通常对开发很有用。游戏的代码都编译在 StardewValley.exe 文件中,但是可以对其进行反编译,以获得原始代码的近似可读性。(由于反编译器的限制,此功能可能无法完全发挥作用,但是能够看到它在做什么。)

要反编译游戏代码...

在 Windows 上:
  1. 第一步:
    1. 安装最新版本的 ILSpy
    2. 打开 ILSpy
    3. 点击 视图 > 选项滑动至底部的 "其他" 选项, 并启用“始终限定成员引用”
  2. 在 ILSpy 打开 StardewValley.exe
  3. 右键 Stardew Valley 并选择 保存代码 创建反编译的项目,可以在 Visual Studio 中打开
On Linux/MacOS:
  1. Install Visual Studio Code.
  2. Get the ILSpy .NET Decompiler plugin for VSCode.
  3. Open the Visual Studio Code Command Palette (Command+Shift+P), then type ilspy to show the two commands.
  4. Choose Decompile IL Assembly (pick file), then choose the StardewValley.exe in your game folder.
  5. A tree view named ILSPY DECOMPILED MEMBERS should appear in the Explorer view. This lets you expand and select various nodes to see the decompiled C# code in the editor.

要解包 XNB 数据或图像文件,请参阅 模组:编辑 XNB 文件