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 的属性,例如 size、closeOnOverlayClick、motionPreset

组件会收到:

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-icons 的 IconType。
  • danger 为 true 时,宿主会按危险操作样式渲染。

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

插槽键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 的参数为 api。api 上包含以下注入对象。

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 对应 customModal 或 customModals 中声明的键,只能打开当前扩展自己的弹窗。

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" 对应实例根目录;如果要读取 mods、resourcepacks 等目录,需要传入对应的 InstanceSubdirType 值。

logger ​

访问宿主日志模块。

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

reloadSelf ​

重新加载扩展。

ts
host.actions.reloadSelf();

updateSelf ​

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

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