Skip to content

API

这一页按 UI 贡献、注入对象、宿主数据和宿主能力来组织扩展 API。

注册入口

扩展入口脚本加载后,需要调用:

js
window.registerExtension(factory, token);

其中 token 来自:

js
const token = document.currentScript?.dataset?.extensionToken || "";

最小模板:

js
(function registerMyExtension(factory) {
  const token = document.currentScript?.dataset?.extensionToken || "";

  if (!token) {
    throw new Error("Missing extension activation token");
  }

  window.registerExtension(factory, token);
})(function (api) {
  return {};
});

UI 贡献

factory(api) 返回的对象可以声明以下 UI 贡献。

homeWidget

单个首页卡片。

字段类型必需说明
titlestring卡片标题
ComponentReact.ComponentType卡片组件
descriptionstring卡片描述
iconstring图标字段
keystring多卡片时的 key
defaultWidthnumber默认宽度
minWidthnumber最小宽度
maxWidthnumber最大宽度

homeWidgets

多个首页卡片,类型为 homeWidget[]

settingsPage

扩展设置页。

字段类型必需说明
ComponentReact.ComponentType设置页组件

对应路由:

text
/settings/extension/<identifier>

page

单个扩展页面。

字段类型必需说明
routePathstring扩展内部路由
ComponentReact.ComponentType页面组件
isStandAloneboolean是否为独立窗口页面

普通页面路由:

text
/extension/<identifier>/<routePath>

独立窗口路由:

text
/standalone/extension/<identifier>/<routePath>

pages

多个扩展页面,类型为 page[]

customModal

单个扩展自定义弹窗。宿主会用 Chakra UI 的 Modal 承载它,并把组件渲染在 ModalBody 中。

字段类型必需说明
keystring弹窗唯一键,仅在当前扩展内生效;不能为空,且不能包含 :
titlestring弹窗标题
ComponentReact.ComponentType<{ params?: any; close: () => void; }>弹窗内容组件
paramsany默认参数;调用 openCustomModal 时可覆盖
其他字段Omit<ModalProps, "children" | "isOpen">透传给 Chakra UI Modal 的属性,例如 sizecloseOnOverlayClickmotionPreset

组件会收到:

ts
{
  params?: any;
  close: () => void;
}

customModals

多个扩展自定义弹窗,类型为 customModal[]

slots

向宿主预留的 UI 插槽注册操作项。当前插槽全部用于实例详情页的条目菜单扩展。

基础结构:

ts
slots: {
  [slotKey]: {
    getItems: (context) => Array<{
      icon: string | IconType;
      label?: string;
      onClick?: MouseEventHandler<HTMLButtonElement>;
      danger?: boolean;
    }>;
  };
}

说明:

  • 仅已定义的插槽键会被宿主接收,未知键会被忽略。
  • getItems(context) 返回当前上下文下要追加的按钮项数组。
  • icon 可以是图标资源字符串,也可以是 react-iconsIconType
  • dangertrue 时,宿主会按危险操作样式渲染。

当前支持的插槽键与上下文如下:

插槽键context 额外字段
ui.instance.world.item_menu_operationssave: WorldInfo
ui.instance.server.item_menu_operationsserver: GameServerInfo
ui.instance.mod.item_menu_operationsmod: LocalModInfo
ui.instance.resourcepack.item_menu_operationspack: ResourcePackInfo
ui.instance.server_resourcepack.item_menu_operationspack: ResourcePackInfo
ui.instance.schematic.item_menu_operationsschematic: SchematicInfo
ui.instance.shaderpack.item_menu_operationspack: ShaderPackInfo

所有插槽上下文都包含这一组基础字段:

ts
{
  instanceId: string | undefined;
  summary: InstanceSummary | undefined;
}

dispose

扩展停用时调用的清理函数。

注入对象

factory 的参数为 apiapi 上包含以下注入对象。

api.React

宿主注入的 React 运行时。

扩展组件通过它使用 React 能力,例如:

js
const React = api.React;

api.ChakraUI

宿主注入的 Chakra UI 组件集合。

例如:

js
const { Box, Button, Text, VStack } = api.ChakraUI;

api.Components

宿主注入的业务组件。

字段说明
OptionItem选项卡片组件
OptionItemGroup选项组组件
Section页面分区容器
WrapCard卡片组件
WrapCardGroup卡片组组件

api.identifier

扩展标识符。

api.resolveAssetUrl(path)

将扩展内相对路径转换为资源 URL。

path 是相对于扩展根目录的路径,而不是相对于当前脚本文件的路径。比如扩展目录中存在 assets/video.mp4,那么这里传入的就是 "assets/video.mp4"

示例:

js
const videoUrl = api.resolveAssetUrl("assets/video.mp4");

Host

这一节介绍宿主注入给扩展的上下文入口。扩展通过这里拿到状态能力、动作能力,以及响应式的宿主数据。

api.getHostContext()

返回宿主上下文对象:

ts
{
  actions: ExtensionAbilityActions;
  state: {
    useExtensionState: <T>(key: string, initialValue: T) => [T, SetState<T>];
  };
}

常见写法:

js
const host = api.getHostContext();

api.useHostData()

这是一个 React Hook,用于读取宿主数据。它返回的值由宿主维护,当账号、实例、配置或路由参数变化时,组件会收到新的数据快照。

js
const hostData = api.useHostData();

具体介绍如下。

Host Data

api.useHostData() 返回的是启动器提供给扩展的只读数据快照。它适合用来驱动界面展示、条件判断和与宿主状态相关的交互逻辑。

api.useHostData() 包含以下字段:

字段类型说明
configLauncherConfig启动器配置
selectedPlayerPlayer | undefined选中的账号
selectedInstanceInstanceSummary | undefined选中的实例
playerListPlayer[]账号列表
instanceListInstanceSummary[]实例列表
routeQueryRecord<string, string | string[] | undefined>路由查询参数

Host State

useExtensionState(key, initialValue)

扩展私有状态 Hook,类似于 React 开发中的 useState

js
const host = api.getHostContext();
const [count, setCount] = host.state.useExtensionState("count", 0);

状态以扩展作用域保存在启动器宿主侧。

Host Actions

host.actions 提供扩展可调用的宿主能力。每个动作都由宿主实现,扩展通过这些方法完成配置更新、页面跳转、文件访问、网络请求和扩展重载等操作。

getPlayerList

获取账号列表。

ts
const players = host.actions.getPlayerList(sync?: boolean);

getInstanceList

获取实例列表。

ts
const instances = host.actions.getInstanceList(sync?: boolean);

updateConfig

更新配置路径对应的值。

ts
host.actions.updateConfig(path: string, value: any);

在扩展允许的路由范围内跳转页面。

ts
await host.actions.navigate(route: string);

请求宿主执行一次历史返回。

ts
host.actions.navBack();

openWindow

打开独立窗口并加载指定路由。

ts
host.actions.openWindow(route: string, title: string);

请求宿主打开外部链接。

ts
await host.actions.openExternalLink(url: string);

openSharedModal

打开宿主共享弹窗。

ts
host.actions.openSharedModal(key: string, params?: any);

openCustomModal

打开当前扩展注册的自定义弹窗。

ts
host.actions.openCustomModal(key: string, params?: any);

这里的 key 对应 customModalcustomModals 中声明的键,只能打开当前扩展自己的弹窗。

setHomeWidgetTitle 1.1.0

更新首页卡片的标题。

ts
host.actions.setHomeWidgetTitle(title: string, key?: string);

若同一扩展声明了多个首页卡片,可通过 key 指定目标卡片;省略 key 则更新该扩展唯一的首页卡片。

readFile

读取扩展 data/ 目录中的文件。

ts
const content = await host.actions.readFile(
  path: string,
  mode?: "string" | "base64"
);

默认以 "string" 读取;当需要处理二进制内容时,可以使用 "base64"

writeFile

将内容写入扩展 data/ 目录中的文件。

ts
await host.actions.writeFile(
  path: string,
  content: string,
  mode?: "string" | "base64"
);

默认以 "string" 写入;写入二进制内容时可配合 "base64" 模式使用。

deleteFile

删除扩展 data/ 目录中的文件。

ts
await host.actions.deleteFile(path: string);

deleteDirectory

删除扩展 data/ 目录中的目录。

ts
await host.actions.deleteDirectory(path: string);

request

发起 HTTP 请求并返回响应对象。

ts
const response = await host.actions.request(
  input: URL | Request | string,
  init?: RequestInit
);

requestText

请求文本内容,并按指定编码读取响应。

ts
const text = await host.actions.requestText(
  url: string,
  init?: RequestInit,
  encoding?: string
);

invoke

调用宿主的 Tauri 命令并返回结果,部分命令无法被直接调用。

ts
const result = await host.actions.invoke<T = unknown>(
  command: string,
  payload?: Record<string, unknown>
);

示例

获取当前选中实例的 ID,并读取该实例根目录下的 options.txt

js
const host = api.getHostContext();
const hostData = api.useHostData();

async function readSelectedInstanceOptions() {
  const instanceId = hostData.selectedInstance?.id;
  if (!instanceId) {
    throw new Error("No selected instance");
  }

  const optionsText = await host.actions.invoke("read_instance_file", {
    instanceId,
    dirType: "Root",
    path: "options.txt",
    mode: "string",
  });

  return optionsText;
}

这里的 dirType: "Root" 对应实例根目录;如果要读取 modsresourcepacks 等目录,需要传入对应的 InstanceSubdirType 值。

logger

访问宿主日志模块。

ts
host.actions.logger.info("extension log");

reloadSelf

重新加载扩展。

ts
host.actions.reloadSelf();

updateSelf

请求宿主下载指定版本的扩展包,并弹出安装更新确认。

ts
await host.actions.updateSelf(src: string, newVersion: string);