Build a shared monster raid

This example builds a real-time raid in which several members attack the same monster until its health reaches zero. Webspace's shared-resource processor applies attacks, health changes, and per-action rewards together on the server.

Before you begin

  • You need permission to deploy schemas and APIs.
  • Members must have the real-time send and receive permissions.
  • Restrict the raid-target creation API to administrators.

Start with the complete schema

Download the shared-resource game schema (.sfn). It includes the columns and permissions for all three tables used in this guide, together with the shared-resource processor configuration.

  1. Download the file, upload it to a team or personal folder, and open it in the schema editor.
  2. In the API Build deployment settings, review the Database identifier. Change the default resource_game to a new identifier such as monster_raid_team_a so it does not conflict with an existing database.
  3. Review the permissions and processor settings, then deploy the schema.

This file is a backend structure example for a shared resource. Its includeClient setting is false, so it does not generate a game interface or include an initial monster record. Build the interface separately with the APIs and WebSocket events below, and create the raid target before playing.

Separate the data into three tables

The shared-resource structure separates three types of data.

TableStored data
game_resourcesMonster code, status, current and maximum health, version, and reward item
game_actionsAction ID, acting member, applied damage, resulting health, and reward quantity
game_inventoryEach member's items and accumulated quantities

The action ID in game_actions identifies retries. Sending the same action ID again does not apply health changes or rewards twice.

Configure the real-time processor

Enable the real-time feature and select shared-resource as its event processor. With the default table names, the processor configuration has this shape:

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

With broadcast set to namespace, clients connected to the same Webspace real-time namespace receive the result event. Set it to actor to return results only to the member who acted.

Create a raid target

Call game_resources/create as an administrator to create the monster.

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

When the page opens, read the current health and version from the game_resources API. Read it again after a new connection or reconnection so the interface uses the current server state.

Send an attack over WebSocket

After an authenticated member subscribes to the real-time connection, send a resource-game.act event.

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

Use the Database identifier selected during deployment as dbName.

Create an actionId of 8–80 ASCII letters, numbers, underscores, or hyphens. amount defaults to 1 when omitted. When included, it must be an integer within the processor's maxClientAmount limit.

The server returns resource-game.action-applied after processing the action.

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

Update the health display only after receiving this result. A client request that sends resource-game.action-applied directly is rejected.

Display health and rewards

  1. Confirm that resourceId belongs to the monster currently displayed.
  2. Confirm that version is newer than the previous result.
  3. Update the health display from currentValue.
  4. Show the shared completion state when currentValue reaches zero.
  5. Reload personal items from game_inventory/list.

Apply owner-only read access to game_inventory, so members can read only their own data. Do not infer another member's inventory from rewardQuantity in a shared event.

Notes

  • Attack strength and rewards come from the server's processor configuration, not client values.
  • The resource change, action record, and reward update run in one transaction.
  • The shared structure provides per-action rewards. Kill rankings and kill-only rewards require a separate design.
  • Do not treat a delayed response as success. Retry with the same actionId to avoid applying the action twice.