跳转到正文

搭建多人协同怪物讨伐

构建一个多名成员攻击同一只怪物、并在其生命值降到 0 之前持续共享结果的实时讨伐玩法。Webspace 的通用 shared-resource 处理器会在服务器端统一处理攻击、生命值变化和按行动发放的奖励。

开始之前

  • 需要部署架构和 API 的权限。
  • 必须向要使用实时功能的成员授予 send 和 receive 权限。
  • 将讨伐目标的创建 API 配置为仅管理员可用。

从完成的架构开始

下载共享资源游戏架构(.sfn)中包含本文使用的三张表的列与权限,以及 shared-resource 处理器设置。 所有语言版本的文档共用此文件,文件中的表和列说明均为英文。

  1. 下载文件,上传到团队文件夹或个人文件夹,然后用架构编辑器打开。
  2. 在 API 构建 的部署设置中确认 数据库标识符。为避免默认值 resource_game 与现有数据库重复,请改为 monster_raid_team_a 这样的新标识符。
  3. 检查权限和处理器设置后,部署架构。

此文件是共享资源后端结构示例。由于 includeClient 为 false,不会自动生成游戏界面,也不包含初始怪物数据。需要另外制作使用下方 API 和 WebSocket 事件的界面,并创建讨伐目标。

将数据拆分为三张表

共享资源结构将以下三类数据分开存放。

表存储内容
game_resources怪物代码、状态、当前与最大生命值、版本和奖励物品
game_actions行动 ID、发起攻击的成员、实际伤害、结果生命值和奖励数量
game_inventory各成员的物品和累计数量

game_actions 的行动 ID 用于区分重试。即使再次发送同一个行动 ID,生命值和奖励也不会被重复计算。

设置实时处理器

开启实时功能,并将事件处理器选为 shared-resource。如果使用默认表名,处理器设置的结构如下。

{
  "resourcesTable": "game_resources",
  "actionsTable": "game_actions",
  "inventoryTable": "game_inventory",
  "actionPower": 1,
  "rewardPerAction": 1,
  "maxClientAmount": 1,
  "broadcast": "namespace"
}

broadcast 为 namespace 时,连接到同一个 Webspace 实时命名空间的客户端会一起收到结果事件。为 actor 时,只向发起行动的成员发送结果。

创建讨伐目标

以管理员权限调用 game_resources/create 创建怪物。

{
  "code": "RAID-1",
  "kind": "monster",
  "status": "active",
  "current_value": 10000,
  "max_value": 10000,
  "version": 0,
  "reward_item_code": "monster-core"
}

打开界面时,从 game_resources 的查询 API 读取当前生命值和版本。新建连接或连接恢复后,再次查询 REST API,即可以当前服务器状态为准校正界面。

通过 WebSocket 发送攻击

已登录的成员订阅实时连接后,发送 resource-game.act 事件。

{
  "type": "webspace:send",
  "data": {
    "dbName": "monster_raid_team_a",
    "event": "resource-game.act",
    "payload": {
      "actionId": "attack-00000001",
      "resourceCode": "RAID-1",
      "amount": 1
    }
  }
}

dbName 使用部署时指定的 数据库标识符。

actionId 由英文字母、数字、_ 和 - 组合而成,长度为 8~80 个字符。省略 amount 时为 1;发送值时,请使用处理器 maxClientAmount 范围内的整数。

服务器处理完成后会发送 resource-game.action-applied。

{
  "actionId": "attack-00000001",
  "resourceId": 1,
  "currentValue": 9999,
  "version": 1,
  "rewardQuantity": 1,
  "duplicate": false
}

界面只有在收到此结果后才更改生命值。客户端直接发送 resource-game.action-applied 的请求会被拒绝。

显示生命值和奖励

  1. 确认 resourceId 是当前正在查看的怪物。
  2. 确认 version 大于上一次的结果。
  3. 用 currentValue 更新生命值显示。
  4. currentValue 为 0 时,显示共同击败完成状态。
  5. 个人物品从 game_inventory/list 重新查询。

对 game_inventory 应用只能读取成员本人数据的所有者权限。不要仅凭结果事件中的 rewardQuantity 推测其他成员的持有量。

注意事项

  • 攻击力和奖励由服务器的处理器设置决定,而不是客户端的值。
  • 资源变更、行动记录和奖励累计在同一个事务中处理。
  • 当前的通用结构按行动提供奖励。击败排名或击败者专属奖励需要另行设计。
  • 响应延迟也不视为成功。使用同一个 actionId 重新确认,可以防止重复应用。

相关文档