İçeriğe atla

Oda tarifleri

Her maçı kaydet

Oda kapandığında devam etmekte olan maç dahil, her maçı bir tekrar dosyası olarak kaydedin.

Bu oda, başlama vuruşundan maçın bitiş düdüğüne kadar her maçı kaydeder ve her kaydı, yanına küçük bir JSON özetiyle birlikte diske yazar.

host.mjs
import { mkdir, writeFile } from 'node:fs/promises';
import { createRoom, readReplay } from 'ball2d/node';

const directory = 'recordings';
await mkdir(directory, { recursive: true });

const room = await createRoom({
  apiKey: process.env.BALL2D_API_KEY,
  roomName: 'Recorded matches',
  noPlayer: true,
  public: true,
});

async function save(blob, reason) {
  const stamp = new Date().toISOString().replace(/[:.]/g, '-');
  const name = `${directory}/${stamp}`;
  await writeFile(
    `${name}.ball2drep`,
    Buffer.from(await blob.arrayBuffer()),
  );
  const replay = await readReplay(blob);
  const summary = {
    reason,
    seconds: (replay.end - replay.initial.tick) / 60,
    players: [
      ...new Set(
        replay.roster
          .map((entry) => entry.name)
          .filter(Boolean),
      ),
    ],
  };
  await writeFile(
    `${name}.json`,
    `${JSON.stringify(summary, null, 2)}\n`,
  );
  console.log('Saved', name);
}

room.onGameStart = () => room.startRecording();

room.onGameStop = () => {
  const blob = room.stopRecording();
  if (blob)
    void save(blob, 'Match ended').catch((error) =>
      console.error(error),
    );
};

// The room finishes recordings on its own at a limit,
// on a stadium change and on close.
room.onRecordingComplete = (blob, reason) => {
  void save(blob, reason).catch((error) =>
    console.error(error),
  );
};

room.onError = (message) => console.error(message);
console.log(room.roomLink);

for (const signal of ['SIGINT', 'SIGTERM']) {
  process.once(signal, async () => {
    // Delivers the running recording to onRecordingComplete.
    room.close();
    await room.closed;
    // Let the last write finish.
    setTimeout(() => process.exit(0), 1000);
  });
}

Nasıl çalışır

  • Başlama vuruşunda başlayın, düdükte durdurun. onGameStop, hem bir maç durdurulduğunda hem de tamamlanmış bir maç lobiye döndüğünde tetiklenir; böylece her maç save() içinde sonuçlanır.
  • Hiçbir şey kaybolmaz. Odanın kendisinin sonlandırdığı kayıtlar -bir saatlik sınır, bir stadyum değişikliği veya close() nedeniyle- onRecordingComplete içine gelir. Sizin kendiniz durdurduğunuz kayıtlar buraya gelmez; böylece her dosya tam olarak bir kez kaydedilir.
  • Özetler dosyadan gelir. readReplay(), kaydedilirken her kaydı doğrular; bozuk bir dosya burada başarısız olur, aylar sonra değil.
  • Yazma işlemleri tick'in dışında kalır. Kaydetme işlemi asenkrondur ve simülasyonu asla bloklamaz.

Kayıtlar, yalnızca onları oluşturan motor derlemesi tarafından okunabilir. Yükseltme sonrasında okumayı planlıyorsanız SDK sürümünü kayıtlarınızla birlikte saklayın.