multiplayer-game について
RivetKit でマルチプレイヤーゲームを開発する人向けの実装ガイドです。ゲーム種別ごとに、シミュレーション、同期、マッチメイキング、永続化、チート対策の設計パターンを整理しています。
主な機能
- 01ゲームループとティックレートのパターン
- 02物理演算と空間インデックスの指針
- 03状態同期とレプリケーション
- 04Actor 構成とマッチメイキングのパターン
- 05永続化とチート対策の実践
活用シーン
- 01ゲームのマッチメイキングとライフサイクル設計
- 02サーバーシミュレーションと状態同期方式の選定
- 03大規模ワールドをチャンク Actor に分割
- 04クライアントの移動やゲーム操作の検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ rivet-dev/ skills --skill multiplayer-gameインストール後、Claude Code で/multiplayer-gameを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
BASE_SKILL.mdindex.jsonopenapi.jsonreference/actors/access-control.mdactions.mdactor-runtime-socket.mdappearance.mdauthentication.mdcommunicating-between-actors.mdconnections.mddebugging.mddesign-patterns.mddestroy.mderrors.mdevents.mdfetch-and-websocket-handler.mdhelper-types.mdhttp-api.mdinput.mdinspector-tabs.mdkeys.mdkv.mdlifecycle.mdlimits.mdmetadata.mdqueues.mdreference/actors/quickstart/backend.mdcloudflare.mdeffect.mdnext-js.md詳細
マルチプレイヤーゲーム
重要:作業を始める前に、このスキルのディレクトリにある BASE_SKILL.md を必ず読んでください。デバッグ、エラー処理、状態管理、デプロイ、プロジェクトのセットアップに関する重要なガイダンスが記載されています。これらのルールとパターンは、すべての RivetKit の作業に適用されます。以下の内容は、すでに読み、理解していることを前提としています。
動作するサンプル
参考実装が必要な場合は、次のテンプレートにある動作するサンプルのコードを直接読んでください。
RivetKit でマルチプレイヤーゲームを構築するためのパターンです。ジャンルごとに応用できる実践的なチェックリストとして用意されています。
スターターコード
GitHub にある動作するサンプルのいずれかから始めて、ゲームに合わせて調整してください。マッチメイキングとライフサイクルのフローを一から作成しないでください。
| ゲームの分類 | スターターコード | よくある例 |
|---|---|---|
| バトルロイヤル | GitHub | Fortnite、Apex Legends、PUBG、Warzone |
| アリーナ | GitHub | Call of Duty の TDM/FFA、Halo Slayer、Counter-Strike のカジュアル、VALORANT のアンレート、Overwatch のクイックプレイ、Rocket League |
| IO スタイル | GitHub | Agar.io、Slither.io、surviv.io |
| オープンワールド | GitHub | Minecraft のサバイバルサーバー、Rust のようなワールド、MMO のゾーン/チャンクワールド |
| パーティー | GitHub | Fall Guys のプライベートロビー、カスタムゲームルーム、ソーシャルパーティーセッション |
| 2D 物理演算 | GitHub | 見下ろし型の物理演算バトル、2D アリーナゲーム、プラットフォーム格闘ゲーム |
| 3D 物理演算 | GitHub | 物理演算サンドボックスセッション、3D アリーナゲーム、移動の実験場 |
| ランク戦 | GitHub | チェスのランキング戦、対戦型カードゲーム、デュエルアリーナのランク戦キュー |
| ターン制 | GitHub | 通信チェス、Words With Friends、非同期ボードゲーム |
| 放置系 | GitHub | Cookie Clicker、Idle Miner Tycoon、Adventure Capitalist |
サーバーシミュレーション
ゲームループとティックレート
| パターン | 使用する場合 | 実装ガイダンス |
|---|---|---|
| 固定リアルタイムループ | バトルロイヤル、アリーナ、IO スタイル、オープンワールド、ランク戦 | run 内で sleep(tickMs) を実行し、c.aborted の場合は終了します。 |
| アクション駆動型の更新 | パーティー、ターン制 | スケジュールされたティックではなく、アクション/イベントに応じてのみ状態を変更し、ブロードキャストします。 |
| 粗いオフライン進行 | 放置型の進行を含むすべてのモード | c.schedule.after(...) を粗い間隔(例:5〜15 分)で使用し、経過した実時間に基づいて進行分を適用します。 |
物理演算
シンプルなゲームでは、まず独自のキネマティクスロジックから始めます。ジョイント、積み重なった剛体、高密度の衝突、複雑な形状(回転ポリゴン、カプセル、凸包、三角形メッシュ)が必要になったら、フル機能の物理エンジンに切り替えます。
シミュレーションごとにエンジンを1つ選びます。フロントエンド専用のライブラリをバックエンドのシミュレーション経路に含めず、サーバーの状態を信頼できる情報源として扱います。
| 次元 | 主なエンジン | 代替エンジン | コード例 |
|---|---|---|---|
| 2D | @dimforge/rapier2d | planck-js、matter-js | GitHub |
| 3D | @dimforge/rapier3d | cannon-es、ammo.js | GitHub |
空間インデックス
物理演算を伴わない空間クエリには、単純な O(n^2) のチェックではなく、専用のインデックスを使います。
| インデックスの種類 | 推奨事項 |
|---|---|
| AABB インデックス | AOI、可視性、コライダーを持たないエンティティには、動的な集合には rbush、静的に近い集合には flatbush を使います。 |
| ポイントインデックス | 最近傍または半径内のクエリには、d3-quadtree を使います。 |
ネットワーキングと状態同期
ネットコード
| モデル | 使用する場面 | 実装 |
|---|---|---|
| ハイブリッド(クライアントの移動、サーバーの戦闘) | シューティングゲーム、アクションスポーツ、ランク戦のデュエル | クライアントが移動を管理し、レートを制限した位置更新を送信します。サーバーはチート対策のために検証します。戦闘(飛翔体、命中、ダメージ)は完全にサーバーが権限を持ちます。 |
| 補間を使ったサーバー権威型 | IO スタイル、永続ワールド | クライアントは入力コマンドを送信します。サーバーは固定ティックでシミュレーションを実行し、権威あるスナップショットを配信します。クライアントはスナップショット間を補間します。 |
| サーバー権威型(基本ロジック) | ターン制、イベント駆動型 | サーバーが離散的なアクション(ターン、フェーズ遷移、投票)を検証して適用します。クライアントは確定済みの状態を表示します。 |
リアルタイムデータモデル
- スナップショットと差分:状態をイベントとして配信します。参加時や再同期時には完全なスナップショットを送信し、その後は通常の更新としてティックごとの差分を送信します。
- ティックごとにまとめる:イベントは小さく、型を明確にします。高頻度の更新はティックごとにまとめます。
- ゲームの更新に UI フレームワークの状態を使わない:シミュレーションには React の状態ではなく、
requestAnimationFrameまたは Canvas/Three.js のループを使います。UI フレームワークの状態はメニュー、HUD、フォーム用にします。 - ブロードキャストと接続ごとの送信:共有更新には
c.broadcast(...)を、プライベートデータやプレイヤーごとのデータにはconn.send(...)を使います。
シミュレーションロジックの共有
共有シミュレーションロジックは、クライアントとサーバーの両方で実行されます。たとえば、速度を積分してワールド境界内に収める applyInput(state, input, dt) 関数は、クライアントでは予測に、サーバーでは検証に使えます。
- ハイブリッドモード:クライアントは共有の移動ロジックを主な権限として実行し、サーバーはチート対策の検証に実行します。
- サーバー権威型モード:クライアントは共有ロジックを補間と予測にのみ使用します。
- 純粋性を保つ:移動の積分、入力変換、衝突ヘルパー、定数のみを含めます。
- 共有コードは
src/shared/に配置する:副作用のない決定的なヘルパーはsrc/shared/sim/*に配置します。
インタレスト管理
各クライアントが受信する内容を制御して、帯域幅を削減し、情報漏えいを防ぎます。
プレイヤーごとのレプリケーションフィルター
- 関連性でフィルタリングする:近接度、視線、チーム、ゲームフェーズに基づいて、各クライアントにはそのプレイヤーに関連する状態のみを送信します。
- シューティングゲームとアクションゲーム:近接度と、必要に応じて視野角チェックによってレプリケーションを制限します。
- サーバー側のみで処理する:クライアントには、見るべきでないデータを決して送信しないでください。
シャーディングされたワールド
- 大規模なワールドを分割する:
worldId:chunkX:chunkYをキーとするチャンクアクターを使います。 - 近くのチャンクを購読する:クライアントは近隣のパーティション(たとえば 3x3 のチャンク範囲)のみに接続します。
- 必要な場合のみ使う:小規模なマッチの標準構成としてではなく、ワールドが大規模で状態が多い場合(サンドボックス型建築ゲーム、MMO)にのみ使います。
バックエンドインフラストラクチャ
永続化
- インメモリ状態:毎ティック変化するリアルタイムのゲーム状態(プレイヤーの位置、入力、試合フェーズ、スコアなど)に最適です。
- SQLite(
rivetkit/db):クエリやインデックス、長期的な永続化が必要な、大規模またはテーブル形式の状態(タイル、インベントリ、マッチメイキングのプールなど)に適しています。複数のアクションが同じアクターに同時にアクセスする可能性があるため、DB の処理はキューを通じて直列化してください。
マッチメイキングのパターン
以下のアーキテクチャパターン全体で使用する、一般的な構成要素です。
アクターのトポロジー
| プリミティブ | 使用する場面 | 一般的な所有範囲 |
|---|---|---|
matchmaker["main"] + match[matchId] | セッションベースのマルチプレイヤー(バトルロイヤル、アリーナ、ランク戦、パーティー、ターン制) | マッチメイカーが検索と割り当てを担当します。マッチがライフサイクルとゲームプレイの状態を管理します。 |
chunk[worldId,chunkX,chunkY] | シャーディングが必要な広大な連続ワールド | 各チャンクがローカルプレイヤー、チャンクの状態、ローカルシミュレーションを管理します。 |
world[playerId] | プレイヤーごとの進行ループ(放置型/ソロのワールド状態) | プレイヤーごとのリソース、建物、タイマー、進行状況を管理します。 |
player[username] | マッチをまたいで再利用する標準プロフィール/レーティング | 永続的なプレイヤー統計(レーティングや勝敗など)を管理します。 |
leaderboard["main"] | 多数のマッチ/プレイヤー間で共有するランキング | 全体のスコア順一覧と上位リストを管理します。 |
キューイング戦略
- 複数のプレイヤーが同時にマッチメイカーへアクセスする可能性があるため、競合を防ぐには、検索/作成、キューへの追加/キューからの削除、終了などのアクションをアクターのキューを通じて直列化する必要があります。
- マッチ内のアクション(ゲームプレイ、スコア計算)は、マッチメイカーへ書き戻さない限り、キューイングは不要です。
セキュリティとチート対策
まずこの基本項目を実施し、競技性の高い環境や高リスクな環境では、さらにセキュリティを強化してください。
基本チェックリスト
- ID:信頼できる通信上の ID として
c.conn.idを使用します。パラメーター内のplayerId/usernameは信頼できない入力として扱い、サーバーが発行した割り当て/参加チケットを通じて紐付けます。 - 認可:呼び出し元が対象エンティティを変更する権限を持つこと(ルームへの参加、ターンの所有権、ホストのみが実行できるアクションなど)を検証します。
- 入力検証:サイズや長さを制限し、列挙値を検証し、ユーザー名(長さ、使用可能な文字、無制限の Unicode の回避)を検証します。
- レート制限:スパムにつながりやすいアクション(チャット、参加/退出、発砲、移動の更新)に対して、接続ごとにレート制限を設けます。
- 状態の整合性:派生状態(スコア、勝利条件、順位)はサーバー側で再計算します。インベントリ、通貨、リーダーボードの合計値をクライアント側で変更できるようにしてはいけません。
移動の検証
クライアント側で移動を決定するモード(ハイブリッド方式)では、滑らかな動作のために、クライアントから位置/回転の更新を送信できます。ただし、サーバーは次の項目を必ず実施する必要があります。
- 経過時間に基づいて、更新ごとの最大変化量(速度上限)を適用します。
- テレポートを拒否するか、補正します。
- ワールドの境界を適用します(該当する場合は基本的な衝突判定も行います)。
- 更新頻度を制限します(例:最大 20Hz)。
アーキテクチャパターン
以下の各ゲームタイプでは、最初に概要表を示し、その後にアクターとライフサイクルを詳しく説明します。
バトルロイヤル
| トピック | 概要 |
|---|---|
| マッチメイキング | 開始前のロビーのうち、最も人数が多いロビーへすぐに振り分けます(同数の場合は、最も古いロビーを優先します)。定員に達するまでプレイヤーはロビーで待機し、その後マッチが開始されます。 |
| ネットコード | ハイブリッド方式です。移動、カメラ、ローカルでの予測はクライアントが担います。ゾーンの状態、飛翔体、ヒット判定、脱落、戦利品、最終順位はサーバーが担います。 |
| ティックレート | 1 秒あたり 10 ティック(100ms)で、ゾーンの進行とライフサイクルの確認に固定ループを使用します。 |
| 物理演算 | クライアントが移動を担い、サーバーがアンチチート検証を行います。飛翔体、ヒット判定、ダメージはサーバー権限で処理されます。3D には @dimforge/rapier3d、トップダウン 2D には @dimforge/rapier2d を使用します。 |
アクター
-
キー:
matchmaker["main"] -
責任: ロビーの検索または作成、保留中の予約の追跡、収容人数の管理を行います。
-
アクション
findMatchpendingPlayerConnectedupdateMatchcloseMatch
-
キュー
findMatchpendingPlayerConnectedupdateMatchcloseMatch
-
状態
- SQLite
matchespending_playersplayer_countには、接続中と保留中のプレイヤーが含まれます
-
キー:
match[matchId] -
責任: ロビー/進行中/終了の各フェーズ、プレイヤーの状態、ゾーンの進行、脱落を管理します。
-
アクション
connect- 移動および戦闘アクション
-
キュー
- なし
-
状態
- JSON
phaseplayerszoneeliminationssnapshot data
ライフサイクル
sequenceDiagram
participant C as Client
participant MM as matchmaker
participant M as match
C->>MM: findMatch()
alt no open lobby
MM->>M: create(matchId)
end
MM-->>C: {matchId, playerId}
C->>M: connect(playerId)
M->>MM: pendingPlayerConnected(matchId, playerId)
MM-->>M: accepted
Note over M: lobby countdown -> live
M-->>C: snapshot + shoot events
M->>MM: closeMatch(matchId)
アリーナ
| トピック | 概要 |
|---|---|
| マッチメイキング | モード別の固定人数キュー(duo、squad、ffa)を使用し、定員に達した場合にのみマッチを作成して、(FFA を除き)チームを事前に割り当てます。 |
| ネットコード | ハイブリッド方式です。移動、予測、スムージングはクライアントが担います。チームまたは FFA の割り当て、飛翔体、ヒット判定、フェーズ遷移、スコアリングはサーバーが担います。 |
| ティックレート | 1 秒あたり 20 ティック(50ms)で、進行中のチーム戦および FFA のスナップショットには、より頻度の高いループを使用します。 |
| 物理演算 | 中程度から高強度です。移動はクライアントが担い、サーバーが検証を行います。戦闘およびエンティティはサーバー権限で処理されます。 |
アクター
-
キー:
matchmaker["main"] -
責任: モード別のキューを管理し、定員に達したマッチを作成して、チームを割り当て、割り当てを公開します。
-
アクション
queueForMatchunqueueForMatchmatchCompleted
-
キュー
queueForMatchunqueueForMatchmatchCompleted
-
状態
- SQLite
player_poolmatches- 接続およびプレイヤーごとにキー付けされた
assignments
-
キー:
match[matchId] -
責任: マッチの各フェーズと、スコアや勝利条件に関わるマッチ中のプレイヤー/チームの状態を管理します。
-
アクション
connect- ゲームプレイアクション
-
キュー
- なし
-
状態
- JSON
phaseplayersteam assignmentsscore and win state
ライフサイクル
sequenceDiagram
participant C as Client
participant MM as matchmaker
participant M as match
C->>MM: queueForMatch(mode)
Note over MM: enqueue in player_pool
Note over MM: fill when capacity reached
MM->>M: create(matchId, assignments)
Note over MM: persist assignments
MM-->>C: assignmentReady
C->>M: connect(playerId)
Note over M: waiting -> live when all players connect
M->>MM: matchCompleted(matchId)
IO スタイル
| トピック | 概要 |
|---|---|
| マッチメイキング | オープンロビーから、定員に達していない中で最も人数の多いルームにルーティングします。ルームの人数はハートビートで更新され、必要に応じて新しいロビーが自動作成されます。 |
| ネットコード | 補間を用いたサーバーオーソリテーティブ方式です。クライアントは入力インテントを送信し、補間を行います。移動、境界、ルームへの所属、正規スナップショットはサーバーが管理します。 |
| ティックレート | 10 ティック/秒(100ms)で、軽量なルームスナップショットを定期的に送信します。 |
| 物理演算 | 低~中程度の強度です。サーバーオーソリテーティブなキネマティック移動を採用し、衝突が複雑になった場合に限り、物理エンジンを段階的に導入します。 |
アクター
-
キー:
matchmaker["main"] -
責務:プレイヤーを最も人数の多いオープンロビーにルーティングし、予約と収容人数を追跡します。
-
アクション
findLobbypendingPlayerConnectedupdateMatchcloseMatch
-
キュー
findLobbypendingPlayerConnectedupdateMatchcloseMatch
-
状態
- SQLite
matchespending_players- 収容人数には保留中の予約が含まれます
-
キー:
match[matchId] -
責務:マッチごとの移動シミュレーションを実行し、スナップショットをブロードキャストします。
-
アクション
connectsetInput
-
キュー
- なし
-
状態
- JSON
playersinputsmovement statesnapshot cache
ライフサイクル
sequenceDiagram
participant C as Client
participant MM as matchmaker
participant M as match
C->>MM: findLobby()
alt no open lobby
MM->>M: create(matchId)
end
MM-->>C: {matchId, playerId}
C->>M: connect(playerId)
M->>MM: pendingPlayerConnected(matchId, playerId)
MM-->>M: accepted
Note over M: fixed tick simulation
M-->>C: snapshot events
M->>MM: closeMatch(matchId)
オープンワールド
| トピック | 概要 |
|---|---|
| マッチメイキング | ワールド座標を基にクライアント主導でチャンクにルーティングし、隣接チャンクとの接続を通じて近隣のチャンクウィンドウを事前ロードします。 |
| ネットコード | サンドボックスではハイブリッド方式(クライアント移動と検証)、MMO のようなフローではサーバーオーソリテーティブ方式です。チャンクへのルーティング、永続化、正規ワールド状態はサーバーが管理します。 |
| ティックレート | チャンクアクターごとに 10 ティック/秒(100ms)で、負荷はアクティブなチャンク数に応じて増加します。 |
| 物理演算 | 大規模運用では中~高程度です。チャンク内のシミュレーションは、サーバーオーソリテーティブ方式(MMO のような形式)にも、サーバー検証付きのクライアント移動(サンドボックスのような形式)にもできます。 |
アクター
- キー:
chunk[worldId,chunkX,chunkY] - 責務:チャンク内のプレイヤー、ブロック、移動ティック、チャンクへの所属を管理します。
- アクション
connectenterChunkaddPlayersetInputleaveChunkremovePlayer
- キュー
- なし
- 状態
- JSON
connectionsplayers- 1 つのチャンクキーにスコープされた
blocks
ライフサイクル
sequenceDiagram
participant C as Client
participant CH as chunk
Note over C: resolve chunk keys from world position
loop each visible chunk
C->>CH: connect(worldId, chunkX, chunkY, playerId)
Note over CH: store connection metadata
end
C->>CH: enterChunk/addPlayer
loop movement updates
C->>CH: setInput(...)
CH-->>C: snapshot
end
C->>CH: leaveChunk/removePlayer or disconnect
Note over CH: remove membership and metadata
パーティー
| トピック | 概要 |
|---|---|
| マッチメイキング | パーティーコードと明示的な参加操作を使う、ホスト作成のプライベートパーティーフローです。 |
| ネットコード | サーバーオーソリテーティブ方式(基本ロジック)です。メンバーシップ、ホスト権限、フェーズ遷移はサーバーが管理します。 |
| ティックレート | 継続的なティックはなく、更新はイベント駆動型です(join、start、finish)。 |
| 物理演算 | ロビーを中心とするフローでは低強度です。リアルタイムのミニゲームを追加しない限り、通常は専用の物理演算やインデックス作成は不要です。 |
アクター
-
キー:
matchmaker["main"] -
責務:パーティーの作成・参加フローを処理し、参加チケットを検証し、パーティーの人数を追跡します。
-
アクション
createPartyjoinPartyverifyJoinupdatePartySizecloseParty
-
キュー
createPartyjoinPartyverifyJoinupdatePartySizecloseParty
-
状態
- SQLite
parties- パーティーの検索と参加検証に使う
join_tickets
-
キー:
match[matchId] -
責務:パーティーメンバー、ホストの役割、準備完了フラグ、フェーズ遷移を管理します。
-
アクション
connectstartGamefinishGame
-
キュー
- なし
-
状態
- JSON
membershostready statephaseparty events
ライフサイクル
ホストのフロー
sequenceDiagram
participant H as Host Client
participant MM as matchmaker
participant M as match
H->>MM: createParty()
MM-->>H: {matchId, partyCode, playerId, joinToken}
H->>M: connect(playerId, joinToken)
M->>MM: verifyJoin(...)
MM-->>M: allowed
M->>MM: updatePartySize(playerCount)
H->>M: startGame() / finishGame()
M->>MM: closeParty(matchId)
参加者のフロー
sequenceDiagram
participant J as Joiner Client
participant MM as matchmaker
participant M as match
J->>MM: joinParty(partyCode)
MM-->>J: {matchId, playerId, joinToken}
J->>M: connect(playerId, joinToken)
M->>MM: verifyJoin(...)
MM-->>M: allowed / denied
M->>MM: updatePartySize(playerCount)
ランク戦
| トピック | 概要 |
|---|---|
| マッチメイキング | ELO ベースのキューでマッチングします。待ち時間が長くなるにつれて検索範囲が広がります。 |
| ネットコード | ハイブリッドです。クライアントがローカル予測と補間を使って移動を制御します。サーバーが投射物、命中判定、試合結果、レーティングの更新を制御します。 |
| ティックレート | 1 秒あたり 20 ティック(50ms)です。固定されたライブティックによって、決定論的なペースとブロードキャスト間隔を維持します。 |
| 物理演算 | 中程度から高強度です。クライアントが移動し、サーバーが検証と、サーバー主導の戦闘/命中判定を行います。 |
アクター
-
キー:
matchmaker["main"] -
責務:レーティングベースのキュー管理、マッチング、割り当ての永続化、完了通知の配信を行います。
-
アクション
queueForMatchunqueueForMatchmatchCompleted
-
キュー
queueForMatchunqueueForMatchmatchCompleted
-
状態
- SQLite
player_poolmatches- レーティング範囲と接続スコープを含む
assignments
-
キー:
match[matchId] -
責務:ランク戦のフェーズ、スコア、勝者の報告を管理します。
-
アクション
connect- ゲームプレイアクション
-
キュー
- なし
-
状態
- JSON
phaseplayersscorewinnercompletion payload
-
キー:
player[username] -
責務:正規のプレイヤー MMR と勝敗プロフィールを保存します。
-
アクション
initializegetRatingapplyMatchResult
-
キュー
- なし
-
状態
- JSON
ratingwinslossesmatch counters
-
キー:
leaderboard["main"] -
責務:上位プレイヤーを保存し、提供します。
-
アクション
updatePlayer
-
キュー
- なし
-
状態
- SQLite
- リーダーボードのスコア行
- 上位リストの順序
ライフサイクル
sequenceDiagram
participant C as Client
participant MM as matchmaker
participant P as player
participant M as match
participant LB as leaderboard
C->>MM: queueForMatch(username)
MM->>P: initialize/getRating
P-->>MM: rating
Note over MM: store queue row + retry pairing
MM->>M: create(matchId, assigned players)
MM-->>C: assignmentReady
C->>M: connect(username)
M->>MM: matchCompleted(...)
MM->>P: applyMatchResult(...)
MM->>LB: updatePlayer(...)
Note over MM: remove matches + assignments rows
ターン制
| トピック | 概要 |
|---|---|
| マッチメイキング | 非同期のプライベート招待とパブリックキューで、同じパターンのマッチングを行います。 |
| ネットコード | サーバー主導(基本ロジック)です。クライアントは送信前に手を作成できます。サーバーが手番の所有権、確定済みの手のログ、手番順、完了状態を管理します。 |
| ティックレート | 継続的なティックはありません。手の送信と手番の移行によって更新が行われます。 |
| 物理演算 | 非常に低強度です。リアルタイムの物理演算ループはなく、離散的なルール検証のみです。インデックス作成は任意で、主に規模が大きい場合の盤面やクエリの利便性を目的とします。 |
アクター
-
キー:
matchmaker["main"] -
責務:非同期マッチ向けのプライベート招待とパブリックキューのマッチングを処理します。
-
アクション
createGamejoinByCodequeueForMatchunqueueForMatchcloseMatch
-
キュー
createGamejoinByCodequeueForMatchunqueueForMatchcloseMatch
-
状態
- SQLite
matchesplayer_pool- 招待とキューのマッピング用の
assignments
-
キー:
match[matchId] -
責務:盤面の状態、手番順、手の検証、最終結果を管理します。
-
アクション
connectmakeMove
-
キュー
- なし
-
状態
- JSON
boardturnsplayersconnection presenceresult
ライフサイクル
パブリックキュー
sequenceDiagram
participant A as Client A
participant B as Client B
participant MM as matchmaker
participant M as match
A->>MM: queueForMatch()
B->>MM: queueForMatch()
Note over MM: pair first two queued players
MM->>M: create(matchId) + seed X/O players
MM-->>A: assignment/match info
MM-->>B: assignment/match info
A->>M: connect(playerId)
B->>M: connect(playerId)
A->>M: makeMove()
B->>M: makeMove()
opt all players disconnected for timeout
Note over M: destroy after idle timeout
end
M->>MM: closeMatch(matchId)
プライベート招待
sequenceDiagram
participant A as Client A
participant B as Client B
participant MM as matchmaker
participant M as match
A->>MM: createGame()
MM-->>A: {matchId, playerId, inviteCode}
B->>MM: joinByCode(inviteCode)
MM->>M: create(matchId) + seed X/O players
MM-->>A: assignment/match info
MM-->>B: assignment/match info
A->>M: connect(playerId)
B->>M: connect(playerId)
A->>M: makeMove()
B->>M: makeMove()
M->>MM: closeMatch(matchId)
アイドルゲーム
| トピック | 概要 |
|---|---|
| マッチメイキング | マッチメーカーはありません。各プレイヤーは、プレイヤーごとの直接アクターと、共有のリーダーボードアクターを使用します。 |
| ネットコード | サーバー権威型(基本ロジック)です。クライアントはUIと建設の意図を管理します。サーバーはリソース、生産率、建設の検証、リーダーボードの合計値を管理します。 |
| ティックレート | 継続的なティックはありません。大まかな間隔にはc.schedule.after(...)を使い、経過した実時間からオフライン中の進行を計算します。 |
| 物理演算 | 標準的なアイドルゲームのループでは使用しません。遷移(build、collect、upgrade)は離散的であり、空間インデックスは必要ありません。 |
アクター
-
キー:
world[playerId] -
責務:1人のプレイヤーの進行状況、建物、生産スケジュール、状態の更新を管理します。
-
アクション
initializebuildcollectProduction
-
キュー
- なし
-
状態
- JSON
- プレイヤーごとの建物
resourcestimersprogression state
-
キー:
leaderboard["main"] -
責務:全体のスコアを保存し、リーダーボードの更新を提供します。
-
アクション
updateScore
-
キュー
updateScore
-
状態
- SQLite
- プレイヤーをキーとする
scoresテーブル - 現在のリーダーボード合計値
ライフサイクル
sequenceDiagram
participant C as Client
participant W as world
participant LB as leaderboard
C->>W: getOrCreate(playerId) + initialize()
Note over W: seed state + schedule collection
W-->>C: stateUpdate
loop gameplay loop
C->>W: build() / collectProduction()
W->>LB: updateScore(...)
Note over LB: upsert scores
LB-->>C: leaderboardUpdate
W-->>C: stateUpdate
end
リファレンスマップ
アクター
- アクセス制御
- アクション
- アクターキー
- アクターランタイムソケット
- アクターのステータス
- 認証
- Cloudflare Workers クイックスタート
- アクター間の通信
- 接続
- カスタムインスペクタータブ
- デバッグ
- 設計パターン
- アクターの破棄
- Effect.ts クイックスタート(ベータ)
- エラー
- Fetch と WebSocket ハンドラー
- ヘルパー型
- アイコンと名前
- メモリ内状態
- 入力パラメーター
- ライフサイクル
- 制限
- 低レベル HTTP リクエストハンドラー
- 低レベル KV ストレージ
- 低レベル WebSocket ハンドラー
- メタデータ
- Next.js クイックスタート
- Node.js と Bun のクイックスタート
- キューと実行ループ
- React クイックスタート
- リアルタイム
- Rust クイックスタート(ベータ)
- スケーリングと並行処理
- スケジュールと Cron
- 状態の共有と参加
- SQLite
- SQLite + Drizzle
- Supabase Functions クイックスタート
- テスト
- トラブルシューティング
- 型
- 標準 HTTP API
- バージョンとアップグレード
- ワークフロー
CLI
クライアント
クックブック
- AI エージェント
- チャットルーム
- 共同テキストエディター
- Cron ジョブとスケジュールタスク
- テナントごとのデータベース
- VPC またはエアギャップネットワークへの Rivet のデプロイ
- ライブカーソルとプレゼンス
- マルチプレイヤーゲーム
デプロイ
- コンテナランナー
- Amazon Web Services Lambda へのデプロイ
- AWS ECS へのデプロイ
- Cloudflare Workers へのデプロイ
- Freestyle へのデプロイ
- Google Cloud Run へのデプロイ
- Hetzner へのデプロイ
- Kubernetes へのデプロイ
- Railway へのデプロイ
- Rivet Compute へのデプロイ
- Supabase Functions へのデプロイ
- Vercel へのデプロイ
- VM とベアメタルへのデプロイ
一般
- アクターの設定
- クロスオリジンリソース共有
- LLM と AI 向けドキュメント
- エッジネットワーキング
- エンドポイント
- 環境変数
- HTTP サーバー
- ロギング
- プールの設定
- 本番環境チェックリスト
- レジストリの設定
- ランタイムモード
- WASM とネイティブ SDK の比較