Caputchin
Pengembangan game kustom

Bangun game swahosting

Di akhir tutorial ini kamu akan punya game Caputchin sungguhan: sebuah bundel JavaScript yang berjalan di iframe ber-sandbox widget, berbicara ke host lewat game SDK, dan melaporkan sebuah trace yang bisa dijalankan-ulang server. Tak seperti mode manual, sebuah game swahosting bisa menggerbang sebuah kunci situs, karena rondenya bisa-diputar-ulang. Tutorial ini mencakup membangun dan menghosting game; putar-ulang dan penggerbangan mencakup artefak yang sebenarnya menyalakan gerbang.

Baca jalankan game-mu sendiri untuk di mana ini cocok. Kamu butuh tempat untuk menghosting berkas JavaScript statis (CDN atau host statis mana pun) dan widget di halamanmu.

Bentuk sebuah game swahosting

Sebuah game swahosting adalah satu bundel JavaScript mandiri yang:

  1. Mengimpor fungsi register @caputchin/game-sdk dan mendaftarkan satu game factory.
  2. Merender ke kontainer yang diberikan widget ke factory, memakai bahasa, skin, dan konfigurasi terselesaikan yang dilewatkan bersamanya.
  3. Bermain secara deterministik di bawah seed per-ronde, merekam permainan sebagai trace.
  4. Saat menang, memanggil bridge.pass({ trace }) dengan catatan itu.

Widget memuat bundel-mu ke iframe-nya dan memanggil factory-mu; factory yang dipanggil adalah sinyal mulai (tak ada event mulai terpisah untuk ditunggu).

1. Daftarkan sebuah game factory

Pasang SDK dan panggil register sekali dengan factory-mu. Kamu tak melewatkan manifest; server menyelesaikan preset dan menyerahkannya ke factory.

import { register } from "@caputchin/game-sdk";

register((container, bridge, ctx) => {
  // container — a DOM element inside the sandboxed iframe; render into it.
  // bridge    — push-only channel to the host (pass / error / setSize).
  // ctx       — the per-round context (seed + resolved locale/skin/config).

  const cleanup = startGame(container, bridge, ctx);

  // Return an optional cleanup function; the widget calls it on unmount.
  return cleanup;
});
npm install @caputchin/game-sdk

2. Baca konteks per-ronde

Argumen ketiga factory, ctx, membawa semua yang dibutuhkan game-mu untuk pengunjung ini:

  • ctx.seed — seed putar-ulang per-ronde. Turunkan semua keacakan dari ini. Null saat game berjalan di luar sesi terverifikasi.
  • ctx.locale — objek bahasa terselesaikan: ctx.locale._lang plus kunci string terjemahanmu.
  • ctx.skin — objek skin terselesaikan: ctx.skin._theme (selalu light atau dark) plus kunci warna dan asetmu.
  • ctx.config — konfigurasi gameplay terselesaikan (atau null).

Ini adalah preset terselesaikan untuk pengunjung ini, dihasilkan Caputchin dari skema dan preset yang kamu definisikan di dasbor. Kamu membaca kunci-mu sendiri darinya; kamu tak menyelesaikan apa pun sendiri.

Jika tata letakmu butuh ukuran eksplisit, beri tahu host sekali setelah cat pertamamu:

bridge.setSize(360, 480);

3. Buat permainan deterministik

Inilah aturan yang membuat sebuah game bisa-digerbang: game harus deterministik diberi seed dan input pemain. Jangan panggil Math.random() atau membaca jam dinding untuk apa pun yang memengaruhi hasil; turunkan setiap pilihan acak dari ctx.seed. Server menjalankan-ulang logikamu di bawah seed yang sama dan trace terekam yang sama dan harus mencapai vonis yang sama.

// A tiny seeded PRNG; feed it ctx.seed so the server reproduces the run.
function makeRng(seed) {
  let s = hashToInt(seed);
  return () => (s = (s * 1103515245 + 12345) & 0x7fffffff) / 0x7fffffff;
}

Rekam input yang mengemudikan hasil (target mana yang dikenai pemain, dalam urutan, dengan waktu jika penting) selagi kamu bermain. Serialisasikan catatan itu ke sebuah string: string itu adalah trace-mu.

4. Pass dengan trace

Saat pengunjung menang, serahkan trace ke host. pass menerima sebuah objek dengan satu string trace:

function onWin(traceString) {
  bridge.pass({ trace: traceString });
}

Trace opaque bagi platform: ia adalah string apa pun yang hanya game-mu definisikan, sedemikian sehingga logikamu, digabung dengan seed, mereproduksi hasil. Game tak melaporkan skor di sini; penilaian, jika ada, adalah urusan dalam-iframe-mu sendiri.

Dua fakta jembatan lagi:

  • pass pertama menebus ronde; ronde yang gagal atau ditinggalkan ditandakan dengan sekadar tak memanggil pass (tak ada metode fail di jembatan ini).
  • bridge.error({ code, message }) untuk kegagalan internal-game (sebuah aset gagal memuat, sebuah eksepsi), bukan kekalahan pemain. Ia memunculkan event error ke host.

Setelah host menebus pass, ia melepaskan token widget, dan backend-mu memverifikasi token itu seperti biasa.

5. Bundel untuk sandbox

Widget memuat persis satu URL skrip, jadi semua harus ada di satu berkas itu. Konfigurasi bundler-mu (esbuild, rollup, vite, webpack; salah satu) untuk satu keluaran mandiri:

  • inline aset sebagai data URL (sprite, suara, font);
  • nonaktifkan pemisahan kode;
  • jika kamu memakai WASM, sematkan ia sebagai base64 dan instansiasi dari byte.

Pola yang tidak berfungsi di dalam sandbox, karena iframe ber-origin-opaque dengan CSP ketat:

  • fetch('./sprite.png') relatif-path — tak ada path untuk diambil;
  • import('./chunk.js') dinamis — URL kedua diblokir;
  • new Worker('./worker.js') — munculkan worker dari URL Blob inline sebagai gantinya;
  • pengambilan CDN eksternal saat runtime — connect-src memblokirnya.

6. Hosting bundel dan arahkan widget ke ia

Sajikan berkas terbangun dari host statis-mu sendiri lewat https (loopback http diizinkan untuk dev lokal), lalu arahkan widget ke ia:

<caputchin-game
  sitekey="cpt_pub_..."
  game-src="https://cdn.example.com/my-game/game.js"
></caputchin-game>

Widget memuat bundel-mu ke iframe ber-sandbox-nya, memanggil factory-mu dengan konteks, dan menunggu pass-mu. Pada titik ini game berjalan dan memverifikasi, tapi ia belum diizinkan menggerbang sebuah key.

7. Buat ia bisa-digerbang

Untuk memakai game swahosting-mu sebagai gerbang verifikasi, dua hal lagi dibutuhkan, keduanya dibahas berikutnya:

  1. Daftarkan ia sebagai game kustom di dasbor (sebuah id yang kamu pilih) dan definisikan skema dan preset bidangnya agar konteks membawa locale/skin/config nyata.
  2. Unggah sebuah artefak putar-ulang: sebuah build headless dari logika game-mu yang dijalankan server untuk menurunkan-ulang vonis dari seed dan trace. Lihat putar-ulang dan penggerbangan.

Sampai artefak putar-ulang diunggah dan lolos pemeriksaan-dirinya, game kustom menunjukkan Tidak bisa diputar ulang dan tak bisa menggerbang.

Lihat juga

Di halaman ini