Skip to content

Latest commit

 

History

History
216 lines (170 loc) · 5.97 KB

cheatsheet.mdx

File metadata and controls

216 lines (170 loc) · 5.97 KB

import { Tab, Tabs } from "@rspress/core/theme";

API 速查手册 (Cheatsheet)

本文整理了开发 SFMC 业务模块时常用的 SAPI 核心接口与代码片段。

1. 模块入口与注册 (ModuleRegistry)

每个模块在 sapi/src/index.ts 中通过 ModuleRegistry.register 注册:

import { ModuleRegistry } from "@sfmc-bds/sdk/module-loader";
import { Command, Msg, Permission } from "@sfmc-bds/sdk/sapi/runtime";

// 注册玩家命令 /c:tp;需在模块顶层注册以参与启动期命令收集
Command.register(
  "tp",
  "tp.use",
  (player) => {
    if (player) Msg.info("正在传送至主城...", player);
  },
  "传送至主城",
  "feature-teleport"
);

// 需要名称或数量时声明 parameters。可选参数必须放在最后,回调按声明顺序接收。
Command.register(
  "pay",
  "pay.use",
  (player, target, amount) => {
    if (player) Msg.info(`准备向 ${String(target)} 支付 ${String(amount)}`, player);
  },
  "向玩家付款",
  "feature-pay",
  undefined,
  {
    parameters: [
      { name: "target", type: "string" },
      { name: "amount", type: "integer" },
    ],
  }
);

ModuleRegistry.register({
  id: "feature-teleport",
  afterWorldLoad: false, // 是否需要等待世界完全加载后再执行 init
  lifecycle: {
    // 1. 注册权限节点
    registerPermissions() {
      Permission.register("tp.use", 0); // Any=0, Member=1, OP=2, Admin=3
      Permission.register("tp.admin", 2);
    },

    // 2. 注册 Minecraft 原生或自定义事件
    registerEvents() {
      // 在此处订阅 world.afterEvents
    },

    // 3. 异步初始化(读写配置、建表等)
    async init() {
      console.log("[feature-teleport] 初始化完成");
    },

    // 4. 卸载与资源释放
    cleanup() {
      // 清理定时器与缓存
    },
  },
});

2. 消息输出 (Msg)

业务代码中请避免直接调用 player.sendMessage(),统一使用 SDK 提供的 Msg 助手以保持前缀与色彩风格统一:

import { Msg } from "@sfmc-bds/sdk/sapi/runtime";
import { world } from "@minecraft/server";

// 发送给指定玩家(参数顺序:消息文本在前,玩家对象在后)
Msg.info("这是一条常规提示", player);
Msg.success("操作成功完成", player);
Msg.warning("注意:此区域禁止 PvP", player);
Msg.error("余额不足,操作失败", player);
Msg.tips("输入 /c:menu 可打开快捷菜单", player);

// 全服广播原生消息
world.sendMessage("§f[*] 全服公告:服务器将在 10 分钟后例行维护");

3. 表单排版 (ListFormInfo)

使用 ActionFormData 构建菜单面板时,可通过 ListFormInfo 格式化正文行:

import { ActionFormData } from "@minecraft/server-ui";
import { ListFormInfo } from "@sfmc-bds/sdk/sapi/runtime";

const form = new ActionFormData()
  .title("领地管理面板")
  .body(ListFormInfo([
    "当前领地:[主城保护区]",
    "领地主人:ServerAdmin",
    "当前权限:允许移动 / 禁止破坏",
  ]))
  .button("购买领地")
  .button("权限设置")
  .button("§c返回上一页"); // 仅返回/关闭按钮建议带红字

form.show(player).then((response) => {
  if (response.canceled) return;
  // 处理点击选项
});

4. 数据库读写与事务 (@sfmc-bds/sdk/sapi/db)

使用 @sfmc-bds/sdk/sapi/db 进行 SQLite 数据操作:

import { db, sql } from "@sfmc-bds/sdk/sapi/db";

// 1. 初始化建表
await db.execute(sql`
  CREATE TABLE IF NOT EXISTS player_stats (
    player_id TEXT PRIMARY KEY,
    points INTEGER NOT NULL DEFAULT 0,
    last_login INTEGER NOT NULL
  )
`);

// 2. 插入或更新记录
await db.execute(sql`
  INSERT INTO player_stats (player_id, points, last_login)
  VALUES (${player.id}, 100, ${Date.now()})
  ON CONFLICT(player_id) DO UPDATE SET
    points = points + 100,
    last_login = excluded.last_login
`);

// 3. 查询单条数据
const result = await db.queryOne<{ points: number }>(sql`
  SELECT points FROM player_stats WHERE player_id = ${player.id}
`);
console.log(`玩家当前点数: ${result?.points ?? 0}`);
import { db, sql } from "@sfmc-bds/sdk/sapi/db";

// 在事务中执行原子扣款与加款
await db.transaction(async (tx) => {
  // 1. 扣除发起者点数
  const sender = await tx.queryOne<{ points: number }>(sql`
    SELECT points FROM player_stats WHERE player_id = ${senderId}
  `);

  if (!sender || sender.points < amount) {
    throw new Error("余额不足");
  }

  await tx.execute(sql`
    UPDATE player_stats SET points = points - ${amount} WHERE player_id = ${senderId}
  `);

  // 2. 增加接收者点数
  await tx.execute(sql`
    UPDATE player_stats SET points = points + ${amount} WHERE player_id = ${targetId}
  `);

  // 3. 写入交易日志
  await tx.execute(sql`
    INSERT INTO transfer_logs (sender, target, amount, created_at)
    VALUES (${senderId}, ${targetId}, ${amount}, ${Date.now()})
  `);
});

5. 模块配置读写 (@sfmc-bds/sdk/sapi/config)

每个模块在 <SFMC_ROOT>/configs/<configKey>.json 拥有独立配置文件。模块可在 configs-default/<configKey>.json 声明默认值,平台在安装与更新时会自动补齐缺失项且不覆盖已有值:

import { config } from "@sfmc-bds/sdk/sapi/config";

// 读取配置(第二个参数为默认回退值)
const spawnPoint = await config.get("spawn_point", { x: 0, y: 64, z: 0 });
const enableWelcome = await config.get("enable_welcome", true);

// 运行时修改配置并保存
await config.set("spawn_point", { x: 100, y: 70, z: 200 });

6. 跨模块服务调用 (@sfmc-bds/sdk/sapi/service)

调用其他模块在 manifest.json 中声明的 RPC 服务:

import { service } from "@sfmc-bds/sdk/sapi/service";

// 调用 feature-economy 提供的 balance 查询服务
const res = await service.call<{ balance: number }>("economy.balance", {
  playerId: player.id,
});

console.log(`用户余额: ${res.balance}`);