Skip to content

uzu_code システム全体像 ​

内部ドキュメント

このドキュメントは内部実装の詳細です。ゲーム開発者向けの情報は docs.code.uzu-app.com を参照してください。

概要 ​

uzu_code は、WebView ベースの UGC ゲームプラットフォームである。 TypeScript で実装された Web ゲームを Flutter の WebView 内で実行し、ホスト (Flutter) とゲーム (JS) の間で双方向通信を行う。

ゲームは Scenario Content Server (Cloudflare Workers + R2) 経由で配信され、 マルチプレイは Cloudflare Workers + Durable Objects による play-server が担い、シナリオの reducer をサーバー側で実行して state を同期する。

アーキテクチャ全体図 ​

┌──────────────────────────────────────────────────────────────┐
│        Emulator アプリ (dart/apps/uzu_code/emulator)    │
│                                                              │
│  ┌──────────────────┐   ┌─────────────────────────────────┐  │
│  │ParameterBuilder  │ → │ EmulatorScreen (1P〜4P 選択)     │  │
│  │ Screen           │   │  ┌──────────┐  ┌──────────┐     │  │
│  │(設定入力画面)      │   │  │ Player 1 │  │ Player 2 │     │  │
│  └──────────────────┘   │  │(WebView) │  │(WebView) │     │  │
│          ↑              │  └──────────┘  └──────────┘     │  │
│   endpoint / serverUrl  │  ┌──────────┐  ┌──────────┐     │  │
│                         │  │ Player 3 │  │ Player 4 │     │  │
│                         │  │(WebView) │  │(WebView) │     │  │
│                         │  └──────────┘  └──────────┘     │  │
│                         └─────────────────────────────────┘  │
│                                                              │
│  Desktop: DesktopEmulatorLoader (ZIP DL → gameDir 解決)       │
└──────────────────────────────────────────────────────────────┘
           │                        │
           │ GameService            │ GamePlayScreen (uzu_code)
           │ (HTTP ZIP DL           │  ├ LocalServerService (localhost HTTP, dir mode)
           │  + 展開・キャッシュ)     │  ├ BridgeService (双方向通信)
           │                        │  └ PlayScreenController (Host ↔ Game)
           │                        │
           ↓                        │
┌───────────────────────────────────┴──────────────────────────┐
│         Scenario Content Server (uzu-code content-server) │
│                                                              │
│  Cloudflare Workers + R2                                     │
│  HMAC 署名付きサブドメイン URL でゲーム ZIP/ファイルを配信          │
└──────────────────────────────────────────────────────────────┘
           ↑
           │ uzu publish
┌──────────┴───────────────────────────────────────────────────┐
│              UGC ゲーム (TypeScript + Vite)                   │
│                                                              │
│  ┌───────────┐  ┌──────────────────────────────────────┐     │
│  │  Reversi  │  │  今後追加されるゲーム ...               │      │
│  │ (example) │  │                                      │     │
│  └───────────┘  └──────────────────────────────────────┘     │
│                                                              │
│  共通: @uzuhq/code-sdk    (javascript/uzu_code/sdk)    │
│  CLI:  @uzuhq/code-cli   (javascript/uzu_code/cli)   │
└──────────────────────────────────────────────────────────────┘
           │ WebSocket
┌──────────┴────────────────────────────────────────────────────┐
│       Play Server (javascript/uzu_code/play-server/) │
│                                                               │
│  Cloudflare Workers + Durable Objects                         │
│  └ GameHost: シナリオ logic を facet 実行 (/ws/games/{rev}/{room}) │
└──────────────────────────────────────────────────────────────┘

ディレクトリ構成 ​

uzu_code/
├── dart/
│   ├── packages/uzu_code/  # Flutter ライブラリ (ゲーム表示フレームワーク)
│   │   └── lib/
│   │       ├── uzu_code.dart        # バレルエクスポート
│   │       ├── play_screen_controller.dart # Host ↔ Game 双方向通信コントローラ
│   │       ├── helpers/                   # QueryParamsBuilder 等
│   │       ├── screens/                   # GamePlayScreen (WebView, dir/url mode)
│   │       └── services/                  # BridgeService, LocalServerService
│   └── apps/uzu_code/emulator/ # Emulator アプリ (マルチプレイヤーテスト用)
│       └── lib/
│           ├── main.dart                         # エントリーポイント
│           ├── config.dart                       # EmulatorConfig (起動パラメータ)
│           ├── player.dart                       # EmulatorPlayer データクラス
│           ├── screens/
│           │   ├── parameter_builder_screen.dart  # 設定入力画面
│           │   ├── desktop_emulator_loader.dart   # Desktop ZIP DL + 展開ローダー
│           │   └── emulator_screen.dart           # マルチプレイヤー画面
│           ├── services/
│           │   └── game_service.dart              # HTTP ZIP DL + キャッシュ管理
│           └── utils/                            # open_url 等
├── javascript/uzu_code/
│   ├── sdk/                          # @uzuhq/code-sdk (ゲーム⇔Flutter 通信 SDK)
│   │   └── src/
│   │       ├── index.ts              # メインエントリ (init, run, on, send 等)
│   │       ├── types.ts              # 型定義 (GameConfig, SendAction 等)
│   │       ├── reconnectable-ws.ts   # ReconnectableWebSocket (自動再接続)
│   │       ├── dev-hooks.ts          # window.__uzu_dev (外部 automation)
│   │       └── run/                  # run() API 実装 (local, online)
│   ├── engine-core/                  # 3 ランタイム共有のエンジン定義 (GameLogic 型 / ゲーム内時計 / json-patch / random)
│   │                                 # publish せず、SDK / cli / play-server が各自のビルドで取り込む
│   ├── room-core/                    # サーバー専用のゲームルーム本体 (GameRoomCore)
│   │                                 # publish せず、cli の dev-server と play-server の facet が共有する
│   ├── cli/                          # @uzuhq/code-cli (ビルド・パブリッシュ CLI / uzu dev)
│   │   └── src/dev-server/           # dev harness の in-memory GameRoom (本番と同一プロトコル)
│   ├── play-server/                  # ゲームサーバー (CF Workers + DO)
│   │   └── src/
│   │       ├── index.ts              # Worker エントリ (ルーティング)
│   │       ├── game-host.ts          # GameHost Durable Object (supervisor)
│   │       └── game-worker-template/ # GameFacet エンジン (engine-core を焼き込んで配布)
│   ├── scenario-content-server/      # ゲームコンテンツ配信 (CF Workers + R2)
│   │   └── src/
│   │       └── index.ts              # HMAC 認証 + R2 ZIP 展開配信
│   └── example_scenarios/
│       ├── quick_draw/               # サンプルゲーム (tickRate 0 + deadlines / 乱数)
│       ├── reversi/                  # サンプルゲーム (run() API 使用)
│       └── shogi/                    # サンプルゲーム (tick / 持ち時間あり)
├── Taskfile.yml             # タスクランナー設定
├── docs/                    # ドキュメント
└── plans/                   # 設計ドキュメント

コンポーネント一覧 ​

コンポーネントディレクトリ技術スタック詳細ドキュメント
Flutter ライブラリdart/packages/uzu_code/Flutter (Dart 3.11+), webview_flutterflutter-host.md
Emulator アプリdart/apps/uzu_code/emulator/Flutter, uzu_code, audioplayersemulator.md
Web ゲーム外部リポジトリに移行済み (サンプル: example_scenarios/)TypeScript (strict), ViteUZU Code docs
Flutter ↔ JS ブリッジ横断的WebView JavaScriptChannel, postMessagebridge.md
PlayScreen SDKjavascript/uzu_code/sdk/TypeScript, @uzuhq/code-sdkplay-screen-sdk.md
Play Serverjavascript/uzu_code/play-server/Cloudflare Workers, Durable Objectsplay-server
PR プレビューjavascript/uzu_code/cli/uzu-cli, R2 ライフサイクルpreview.md
Scenario Content Serverjavascript/uzu_code/scenario-content-server/Cloudflare Workers, R2, HMAC 認証—

データフロー ​

1. ゲーム開発
   外部リポジトリで開発 → npm run build → dist/ にビルド出力

2. パブリッシュ
   uzu publish → ビルド → ZIP 作成 → R2 アップロード → gRPC でリビジョン登録
   uzu preview → ビルド → ZIP 作成 → R2 アップロード (リビジョン登録なし、14 日で自動削除)

3. Emulator 起動
   ParameterBuilderScreen で endpoint / serverUrl を入力
   → Web: EmulatorScreen (gameUrl モード)
   → Desktop: DesktopEmulatorLoader (ZIP DL → gameDir モード)

4. ゲーム表示
   GamePlayScreen が WebView でゲームをロード
   → dir モード: LocalServerService でローカル HTTP 配信
   → url モード: Scenario Content Server から直接配信 (iframe)

5. ゲームプレイ中の通信
   Flutter → JS: 自分の通話の状態・アプリからサーバーへの伝言 (BridgeService → runJavaScript)
   JS → Flutter: 音声再生・マイク操作・観測席が聴く部屋・WebSocket の状態・サーバーからの伝言 (FlutterHost.postMessage)

6. マルチプレイ通信
   GamePlayScreen が URL に ?roomId=xxx&server=xxx&seatId=xxx&players=[...] を付与 (players = roster)
   → SDK が パラメータ検出 → uzu-code play-server に WebSocket 接続
   → クライアントは action を送り、サーバーが reducer で実行 → 結果を全員へ broadcast (onState)
   → サーバーは接続と通話の状態・部屋割り (presence) も全員へ配り、アプリが部屋とマイクを合わせる

ゲームコンテンツ配信 ​

ゲームコンテンツは uzu-code content-server (Cloudflare Workers + R2) 経由で配信される。

  • HMAC 署名付きサブドメイン URL で認証 (Firebase Auth 不要)
  • R2 バケットから ZIP を取得し、個別ファイルとして配信
  • Cache API によるキャッシュ (max-age 86400)
  • /__zip__ エンドポイントで生 ZIP ダウンロード (モバイル向け)

開発コマンド ​

サーバー起動 ​

bash
task uzu_code:play-server                   # play-server 起動 (wrangler dev)

Emulator 起動 ​

bash
task dev                                    # Emulator 起動 (macOS)
cd dart/apps/uzu_code/emulator && flutter run -d macos    # 直接起動

検証・解析 ​

bash
cd dart/packages/uzu_code && dart analyze    # Flutter 静的解析
cd dart/apps/uzu_code/emulator && dart analyze