マガジン

アップロードしたZIPはどこへ行くか:検証から配信まで

遊びを見つける

執筆にClaudeを使用しています。

地形や橋のある小さなゲーム世界を箱に整理し、ブラウザ形のアーチへ運ぶ模型
記事のテーマをもとに制作したAI生成イラスト。

ブラウザゲームをZIPにまとめ、アソバースの投稿画面に置く場面を考えてみます。ファイルを選んだ瞬間から、公開されて誰かが遊ぶまでの間に、そのZIPは何度か姿を変えます。受け付けられ、中身を調べられ、保管され、別の場所から配信され、囲いのついた枠の中で動きます。この記事では、その流れのどこまでが案内で確かめられていて、どこから先が確かめられていないのかを仕分けします。 先に断っておくと、「非公開の保管場所に置かれ、そこから配信される」という構成そのものは、確認済みの案内には書かれていません。保管場所が非公開かどうか、ファイルがどんな名前で並ぶかといった内部の構成は、この記事では推測で埋めません。書けるのは、投稿の3段階、受け付けの上限、配信元の分離、実行時の囲い、という外から読み取れる部分です。 仕分けができれば、書かれていない部分を「現在の案内で確認する」ものとして扱えます。さらに、読者が自分の手で確かめられる範囲も見えてきます。後半では、小さなHTMLを使った確認手順を設計書の形で示します。

この記事の目次
  1. 流れを一枚にすると:入力、表示の確認、公開
  2. 受け付けの段階で見られること
  3. 保管から配信へ:確かめられることと、確かめられないこと
  4. 配信されたあとの実行の場:囲いとSDK
  5. 自分の手で確かめる設計書
  6. 次の行動

流れを一枚にすると:入力、表示の確認、公開

投稿は「入力→表示の確認→公開」の3段階で進みます。HTMLまたはZIPの直接アップロードのほか、公開済みURLを指定する方法もあります。下書き保存、公開内容の更新、非公開化、削除もできます。公開にはメールアドレスの確認が必要です。

流れを、確認できる事柄と確認できない事柄に分けると次のようになります。

  • 入力、確認済みの事柄:HTML・ZIPのアップロード、または公開済みURL。サイズや数の上限、案内で確認する事柄:検証の細かな内部手順
  • 表示の確認、確認済みの事柄:公開前に表示を見る段階がある、案内で確認する事柄:保管場所や配信経路の内部構成
  • 公開、確認済みの事柄:メール確認が必要。アップロード作品は別オリジンから配信、案内で確認する事柄:配信の仕組みの詳細
  • 公開後、確認済みの事柄:更新、非公開化、削除ができる、案内で確認する事柄:削除後に実体が消えるまでの細かな時間

退会については、アップロードファイル、履歴・セーブを含む個人データ、認証アカウントを削除すると案内されています。ファイルが個人データと並んで削除の対象に挙がっているので、アップロードされた実体はアカウントに紐づいて管理されていると読めます。ただし、これは設計から読み取れる範囲の話で、内部の保管方式を示すものではありません。

受け付けの段階で見られること

ZIPが最初にぶつかるのは、数字の上限です。確認済みの条件は次のとおりです。

  • アップロードは20MiB以内です。
  • ZIPを展開した後は、合計100MiB以内、1,000ファイル以内です。
  • 1ファイルは30MiB以内です。
  • 入口は直下の index.html です。
  • 画像や音などの素材は相対パスで参照します。
  • サーバー用コード、サービスワーカー、SharedArrayBufferを使うマルチスレッドは対象外です。
  • 1人につきUTC(協定世界時)で1日10回まで、アカウントごとに100アップロード・1GiBまでです。

上限が「アップロード時」と「展開後」の二段で決められている点に注目できます。圧縮されたZIPは20MiBに収まっていても、展開すると100MiBを超えることがあります。逆に、展開後の合計が小さくても、1ファイルが30MiBを超えれば条件に合いません。容量で止まったときは、ZIP全体のサイズだけでなく、展開後の合計と最大のファイルを見比べる必要があります。

もう一つ、起こりやすい失敗があります。入口が「直下の index.html」と指定されているので、フォルダごと圧縮した場合は注意が必要です。ZIPを開いた最上位に my-game/ というフォルダが1つだけあり、index.html がその中にある形では、直下に入口がない状態になるかもしれません。この点が実際にどう扱われるかは確認済みの案内にないので、手元のZIPを開いて、最上位に index.html が見えるかを自分の目で確かめるのが確実です。

素材を相対パスで参照するという条件も、同じ発想です。ZIPの中だけで完結し、外の絶対的な場所に頼らない作りにしておけば、どこから配信されても入口からたどれます。

保管から配信へ:確かめられることと、確かめられないこと

配信について確認できる事実は、アップロードしたコードがメインサイトとは別のオリジンから配信される、という一点です。オリジンとは、アドレスのうち「通信方式・ドメイン・ポート」の組を指します。ブラウザはオリジンが違うページ同士を原則として隔てます。そのため、別オリジンで動くゲームのスクリプトは、メインサイト側の保存領域などに直接触れにくくなります。これはブラウザの一般的な仕組みで、アソバース固有の説明ではありません。

この分離から、設計として次のことが読み取れます。投稿されたコードは、どんな内容でもメインサイトと同じ場所では動かない前提で扱われています。ログイン情報を持つメインサイトと、第三者が書いたコードを動かす場所を分けているわけです。

一方で、次の点は確認済みの案内にないため、断定できません。

  • ZIPが展開された状態で置かれるのか、ZIPのまま置かれるのか
  • 保管場所が公開か非公開か
  • 検証がどの順序で、何を対象に行われるのか
  • 公開前の「表示の確認」と公開後の配信が、同じ経路かどうか

「非公開の保管場所から配信まで」という流れは、これらが分かって初めて言い切れる話です。現時点で言えるのは、「受け付けの上限があり、確認の段階があり、メールで確認された人だけが公開でき、配信は別オリジンで行われる」という外形までです。内部の構成が気になる場合は、現在の案内やヘルプで確認してください。

配信されたあとの実行の場:囲いとSDK

別オリジンで配信されたゲームは、sandbox付きのiframeの中で実行されます。sandboxは、埋め込んだページに許可する動作をあらかじめ絞る、ブラウザの機能です。許可の細目は確認済みの案内にないため、どの動作が許されるかを決めつけず、作品を開いて確かめる前提で考えるのが安全です。

アップロードしたゲームには、SDKが自動で追加されます。SDKは、ゲームとアソバースをつなぐ小さな部品です。これを通じて、作品専用のプレイヤーIDと、クラウドセーブ(作品ごとにJSONで128KiBまで)が使えます。URL投稿のゲームでは、作者がSDKを自分で読み込んだときに同じ機能が使えます。具体的な呼び出し方は、現在の案内で確認してください。

ここで守るべき約束があります。ゲームには、FirebaseのUID、認証トークン、メールアドレスを渡しません。作品に渡るのは「作品専用のプレイヤーID」だけで、ログインの実体はゲームの外にとどまります。作る側から見れば、ゲーム側で本人確認の情報を扱わなくてよいということです。

アップロード作品の中のlocalStorageとsessionStorageは「一時メモリーの互換処理」と説明されています。ブラウザに長く残る保存場所として当てにせず、残したい進行はクラウドセーブに預ける設計です。ゲストの進行は端末内に保存され、ログイン後のアカウントへ自動では混ざりません。また、未同期の端末セーブは、クラウドの古いデータより優先して再送されます。

自分の手で確かめる設計書

ここまでの「別オリジンで動く」「囲いの中にいる」「保存は一時メモリー」は、小さなHTMLを置けば、自分のブラウザで見られる部分があります。問いは「自作のゲームは、メインサイトと違う場所で、枠の中にいる状態で動いているか」です。

準備するもの

次のHTMLを index.html という名前で保存し、他のファイルを入れずにZIPにします。ZIPを開いたときの最上位に index.html が見える形にしてください。

html
<!doctype html>
<meta charset="utf-8">
<title>置き場所チェック</title>
<pre id="out"></pre>
<script>
const lines = [];
lines.push("origin: " + location.origin);
lines.push("href: " + location.href);
lines.push("iframe内: " + (window.self !== window.top));
try {
  localStorage.setItem("t", "1");
  lines.push("localStorage: 書き込みできた");
} catch (e) {
  lines.push("localStorage: エラー " + e.name);
}
document.getElementById("out").textContent = lines.join("\n");
</script>

手順

  1. 投稿画面でZIPをアップロードし、下書きの状態で「表示の確認」まで進めます。公開は不要です。
  2. 表示された4行を、そのまま書き写します。
  3. 同じ画面を再読み込みして、もう一度書き写します。
  4. メインサイトのアドレス欄の表示と、1行目のoriginを見比べます。

アップロードには1日の回数制限(UTC1日10回)があります。試す回数は最小限にとどめ、再読み込みで済む確認は再アップロードしないでください。

結果の読み方

  • originが、メインサイトのアドレスと一致しているかを見ます。一致しなければ、「配信元が分かれている」という案内と矛盾しません。一致する場合は、表示の確認画面と公開後の配信で経路が違う可能性も含めて、案内を確認してください。
  • iframe内の行は、枠の中で動いているかどうかの目安です。
  • localStorageの行は、書き込めたかどうかだけを示します。「書き込めた」ことと「長く残る」ことは別の話です。進行を残す手段は、クラウドセーブを基本に考えてください。
  • 値が想定と違っても、それだけで不具合とは言えません。案内にない部分は、案内で確認するのが先です。

起こりやすい誤り

  • フォルダごと圧縮して、最上位に index.html が見えない状態になっています。
  • 素材を絶対パスで書いて、ZIPの中のファイルを参照できていません。
  • 1回の再読み込みの結果だけで判断しています。2回書き写して一致を確かめておくと、見間違いを減らせます。
  • 表示された href をそのままSNSに載せています。下書き中のアドレスは、公開するつもりのないものとして扱ってください。

次の行動

手元のゲームをZIPにして、展開後の合計サイズ、最大のファイル、最上位の index.html の3点を確かめてください。そのうえで、上の確認用HTMLを下書きの「表示の確認」で動かし、書き写した4行を見比べます。保管場所や検証の内部については、現在の案内で確認してください。