维护提醒

BWIKI 全站将于 9 月 3 日(全天)进行维护,期间无法编辑任何页面或发布新的评论。

全站通知:

模组:制作指南/APIs/Integrations

来自星露谷物语维基
跳到导航 跳到搜索

模组:目录

模组整合(mod integration)是指两个模组以某种方式通信或合作。SMAPI 提供了一些支持模组整合的功能。

依赖

您可以在 manifest.json 文件中定义依赖,也就是您的模组需要哪些前置模组。如果需要的依赖缺失,SMAPI 会向玩家显示一个友好的错误。参见[[../Manifest|清单文件]]以获取更多信息。

模组注册项

您的模组可以获取已加载模组的信息,或检查某个模组是否已加载(当调用您模组的 Entry(…) 方法时,所有模组都已加载完毕)。

// check if a mod is loaded
bool isLoaded = this.Helper.ModRegistry.IsLoaded("UniqueModID");

// get info for a mod
IModInfo mod = this.Helper.ModRegistry.Get("UniqueModID");
bool isContentPack = mod.IsContentPack;
IManifest manifest = mod.Manifest; // name, description, version, etc

// get info for all loaded mods
foreach(IModInfo mod in this.Helper.ModRegistry.GetAll()) {  }

模组API

模组可以将自身的 API 提供给其他模组,甚至不需要依赖或程序集引用。这可以用于整合模组、提供自定义信息或提供新的框架接口,以作为 SMAPI 接口的补充。

提供接口

按如下步骤来提供可供其他模组使用的 API:

  1. 向您的模组添加一个正常的类,其中包含您希望公开的方法和属性。
    public class YourModApi
    {
        public string ExampleProperty { get; set; } = "Example value";
    
        public bool GetThing(string example)
        {
           return true;
        }
    }
    
    (如需要,您可以使用构造函数以初始化此 API)
  2. 重写您模组入口类的 GetApi 并返回您的 API 的一个实例。您可以选择该方法的两种版本之一:
    • 重写 GetApi() 以向所有模组提供 API 的同一个实例。此方法只会被调用一次,随后 SMAPI 会缓存其创建的实例。
         public override object GetApi()
         {
            return new YourModApi();
         }
      
    • 重写 GetApi(IModInfo mod) 以为每个模组提供单独的实例。每个请求此 API 的模组都会导致此方法被调用一次。 注意此 IModInfo mod 参数仅用于获取信息(例如用于记录错误)。请不要使用此参数来阻止特定模组调用 API,否则可能被视作滥用行为。
         public override object GetApi(IModInfo mod)
         {
            return new YourModApi(mod.Manifest);
         }
      

大功告成!SMAPI 会获取您的 API 的一个实例并缓存它。

说明:

  • GetApi 总是在 Entry 之后被调用,因此可以放心将其传入您的模组的初始化字段。
  • 谨慎修改您的接口!如果您做了较大修改,其他模组可能需要随之更新。
  • 您可以酌情向您的 API 添加一个接口类。如果其他模组直接引用您的模组 DLL,这样他们就能够使用您的接口类而无需再自行创建。

使用API

您如果需要使用某个模组提供的 API,您可以将其映射到一个接口类

  1. 创建一个接口类,其中仅有您希望访问的属性和方法。此接口类必须为公共类,且不能为内部接口。(如果您直接引用模组 DLL,且后者提供了公共的 API 接口类,则您可以直接使用它。)
    public interface ISomeModApi
    {
       bool GetThing(string example);
    }
    
  2. 在您的模组代码中(Entry 之后),您可以通过指定您在第一步创建的接口类以及[[../Manifest#基本字段|模组唯一ID]]来获取 API:
    ISomeModApi api = helper.ModRegistry.GetApi<ISomeModApi>("other-mod-ID");
    if (api != null)
       bool result = api.GetThing("boop");
    

您也可以使用反射而非接口类来实现快速整合:

object api = helper.ModRegistry.GetApi("other-mod-id");
if (api != null)
   bool result = helper.Reflection.GetMethod(api, "GetThing").Invoke<bool>("boop");

注意:

  • 在所有模组都初始化完毕且其 Entry 方法被调用之前,您不能调用 GetApi。如果您需要在较早时调用模组 API,则 GameLoop.GameLaunched [[../Events|事件]];该事件一定会在所有模组初始化完毕后触发。
  • 您总是应当检查您调用的 API 是否为空。如果无法调用,则 GetApi 会返回空(无法调用的情形例如模组未安装或不提供对应 API)。若 GetAPi</smap> 不能映射某个 API,则会抛出异常。
  • 请留心模组可能会在未来改变其 API 接口;因此,在试图映射接口之前,可以先检查模组版本。

已知的限制

  • 当您提供 API 时,接口类和实现类必须都是公共的。

发送消息

您可以使用多人接口来发送消息。消息的接收方可以很精确(例如,某台联机计算机上的某一个具体的模组),也可以很宽泛(所有计算机上的所有模组)。消息也可以发送到本地计算机上,例如用于两个模组之间的通讯。该特性可以用于各种模组整合。

例如:

  • 从主模组处请求某些东西。(拖拉机模组 Tactor Mod 在多人游戏中使用此特性来给当前玩家生成一个拖拉机,即使拖拉机所在地点并未同步到该玩家。)
  • 告知其他模组某些信息。(随时随地查看箱子 Chest Anywhere 模组使用此特性来告知自动化 Automate 模组,当箱子的自动化选项被编辑)。

共享程序集引用

注意:这并不是 SMAPI 的功能,但是我们仍将其列入文档,因为这是模组整合的常用手段。

您可以在您的 csproj 中添加对某个模组程序集的引用,然后直接向您的模组代码中导入其命名空间及函数。注意,这仅用于如下情形:您希望的功能无法藉由模组的公共 API 实现,或这是目标模组希望被公开使用的方法。这会使您的模组必须依赖于目标模组。

例如,下面的片段向您的模组引用了一个 Content Patcher 程序集,就在 ContentPatcher 命名空间下,从而无需在构建模组时嵌入 ContentPatcher.dll

<ItemGroup>
    <Reference Include="ContentPatcher" HintPath="$(GamePath)\Mods\ContentPatcher\ContentPatcher.dll" Private="false" />
</ItemGroup>

请确保 ContentPatcher.dll 的路径符合您的实际安装情况。