Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Oyuncu verisi (bulut kaydı)

Bu sayfa oyuncunun ilerlemesini (seviye, ayarlar, oyun kaydı) Open Play’de saklayıp başka cihazdan kaldığı yerden sürdürmeyi anlatır. Oyununuz kendi kayıt biçimini taşıyorsa ve onu oyuncu hesabına bağlamak istiyorsanız okuyun.

Ne işe yarar

Oyuncu verisi, oyuncu başına anahtar-değer deposudur. Değer, sunucuda yorumlanmayan opak bir JSON nesnesidir: Open Play onu saklar, boyutunu ölçer ve aynen geri verir; alanlarını sorgulamaz, hesap yapmaz. Kayıt biçimini ve sürümünü oyununuz belirler.

Bu özellik çekirdektedir: bir ürün modülüne bağlı değildir ve Oyun ayarları › Modüller sayfasından kapatılamaz.

Panelde nerede

Ne yapacaksınızPanel sayfası
Bir oyuncunun anahtarlarını, boyutlarını ve değerini görmek; gerektiğinde silmekOyuncular › oyuncu profili › “Oyun verisi” bölümü

Panelden değer yazılamaz; yalnız salt okunur biçimli JSON olarak görünür. Operatör silmesi gerekçe (8–500 karakter) ister ve denetim kaydına yazılır.

Sınırlar

SınırDeğer
Anahtar^[a-z0-9][a-z0-9._-]{0,63}$ (küçük harf, rakam, ., _, -; en çok 64 karakter)
DeğerÜst düzey JSON nesnesi; serileşmiş (kompakt) boyutu en çok 65 536 bayt
Anahtar sayısıOyuncu başına en çok 16
Yazım hızıOyuncu başına dakikada en çok 60 yazım (PUT ve DELETE; okumalar sayılmaz)

Değerde kayan noktalı sayılar serbesttir: değer opak veridir, sunucu onunla hesap yapmaz. İki sınır vardır: nesne anahtarlarının sırası korunmaz ve 2^64’ten büyük tam sayılar ile çift duyarlığı aşan ondalıklar yuvarlanabilir; büyük sayıları dize olarak saklayın.

Sürümlü yazım (CAS)

Her anahtarın bir sürümü vardır: ilk yazımda 1, her başarılı yazımda 1 artar. Sürüm bir i64’tür ve JSON’da ondalık dize olarak taşınır ("3"); HTTP başlığında ETag: "3" biçimindedir.

Önkoşulsuz yazım yoktur. Her PUT tam olarak birini taşır:

  • If-None-Match: * — yalnız anahtar yoksa oluştur.
  • If-Match: "<sürüm>" — yalnız güncel sürüm buysa güncelle.

İki başlığı birden göndermek, hiçbirini göndermemek ya da biçimsiz değer göndermek 428 precondition_required döner. Sürüm tutmazsa (başka cihaz aynı sırada yazdı) 409 version_conflict ve güncel sürüm döner; uzak kaydı okuyun, kendi kuralınızla birleştirin ve yeniden deneyin. Kaynak: crx-domain::player_data.

Oyunun yaptığı çağrılar

Oyuncu uçları oyuncu oturumuyla çalışır: __Secure-crx.session çerezi ya da opak oturum belirteci (Authorization: Bearer) ve x-crx-env: <ortam uuid>. Yazımlar (PUT, DELETE) mağaza satın alma ucuyla aynı tarayıcı korumasını taşır: Origin denetimi ve çerez oturumunda x-csrf-token (bkz. Oturumlar ve CSRF). Geliştirici anahtarı oyuncu uçlarında kabul edilmez (401).

Yöntem ve yolKimlikNe yapar
GET /v1/player/dataoyuncu oturumuKendi anahtarlarının özetini listeler
GET /v1/player/data/{key}oyuncu oturumuBir anahtarı okur (ETag: "<sürüm>")
PUT /v1/player/data/{key}oyuncu oturumuÖnkoşullu oluşturur ya da günceller
DELETE /v1/player/data/{key}oyuncu oturumuIf-Match ile siler (204)
GET /v1/players/{player_id}/datasunucu anahtarıBir oyuncunun anahtar özetleri (yalnız okuma)
GET /v1/players/{player_id}/data/{key}sunucu anahtarıBir oyuncunun bir anahtarı (yalnız okuma)

Sunucu uçları Authorization: Bearer crx_live_<önek>_<gizli> ister; istemci anahtarı 403, oyuncu oturumu 401 alır. Yanıtlar Cache-Control: private, no-store taşır.

Listele

GET /v1/player/data
x-crx-env: 0192f000-0000-7000-8000-00000000e001
{ "items": [ { "key": "my-game.save", "version": "3", "size": 214, "updatedAt": "2026-11-03T10:15:30.120Z" } ] }

Oluştur

PUT /v1/player/data/my-game.save
x-crx-env: 0192f000-0000-7000-8000-00000000e001
x-csrf-token: <csrf belirteci>
If-None-Match: *
Content-Type: application/json

{ "value": { "level": 4, "stars": 17, "playTimeSeconds": 913.5 } }
{ "key": "my-game.save", "version": "1", "updatedAt": "2026-11-03T10:15:30.120Z" }

Yanıt ETag: "1" başlığını da taşır. Gövde tam olarak { "value": <nesne> } olmalıdır; başka alan 422 invalid_value döner.

Güncelle ve sil

PUT /v1/player/data/my-game.save
If-Match: "1"
{ "value": { "level": 5, "stars": 21 } }
DELETE /v1/player/data/my-game.save
If-Match: "2"

Silme 204 döner. Oyuncu silmesi de önkoşulludur; operatör silmesi panelden yapılır.

Okumak

GET /v1/player/data/my-game.save
{ "key": "my-game.save", "value": { "level": 5, "stars": 21 }, "version": "2", "updatedAt": "2026-11-03T10:16:02.004Z" }

Anahtar yoksa 404 ve {"code":"not_found"} döner.

Hata kodları

Bu uçların hataları, çekirdeğin geri kalanından farklı olarak JSON’dur: { "code": "…", "message": "…" }.

DurumcodeNe zaman
404not_foundAnahtar yok (sunucu uçlarında oyuncu bu ortamda yoksa da)
409version_conflictSürüm tutmadı ya da var olan anahtara If-None-Match: *; currentVersion güncel sürümü (anahtar yoksa null) taşır
413value_too_largeDeğer 64 KiB’ı aştı; limit alanı sınırı verir
422invalid_keyAnahtar kalıba uymuyor
422invalid_valueDeğer nesne değil, gövde { "value": … } değil ya da JSON değil
422too_many_keysOyuncu 16 anahtarda; limit alanı sınırı verir
428precondition_requiredIf-Match / If-None-Match: * yok, çift ya da biçimsiz
429rate_limitedDakikada 60 yazım aşıldı; Retry-After saniye cinsinden bekleme verir
401—Oturum yok, geçersiz ya da yasaklı oyuncu (kimlik katmanı ban ayrımını sızdırmaz)
403—Origin, Fetch Metadata ya da CSRF reddi; sunucu uçlarında istemci anahtarı

Yasaklı bir oyuncunun yazımı kimlik katmanında 401 ile biter; depo da savunma olarak yazımı 403 ve {"code":"account_banned"} ile reddeder.

TypeScript SDK

PlayerClient.data bu uçların tipli karşılığıdır: list(), get(key), create(key, value), update(key, value, version), delete(key, version). Sürümler bigint’tir; değer normal JS nesnesidir (güvenli tam sayılar number, aralık dışı tam sayılar bigint, ondalıklar number). CSRF belirtecini ve çerezi SDK yönetir. 409 çatışması PlayerDataConflict (+ currentVersion: bigint | null) olarak fırlar; diğer retler CrxError’dır ve playerDataErrorCode(error) ile ayrışır. Bkz. TypeScript SDK.

Çalışan örnek: kaydet, çatışmada birleştir

/** Oyuncu verisi (bulut kaydı): kaydı oku, değiştir, sürümlü yaz; çatışmada uzak kayıtla birleştirip yeniden dene. */
import { PlayerDataConflict, type PlayerClient, type PlayerDataValue } from "@ferdiunal/open-play-ts";

const KEY = "my-game.save";

/** İki kaydı oyunun kendi kuralıyla birleştirir: burada her bölümde en iyi yıldız sayısı kalır. */
function merge(remote: PlayerDataValue, local: PlayerDataValue): PlayerDataValue {
  const best = (a: unknown, b: unknown): number => Math.max(typeof a === "number" ? a : 0, typeof b === "number" ? b : 0);
  return { ...remote, ...local, stars: best(remote.stars, local.stars) };
}

/** Kaydı buluta yazar; sürüm çatışırsa (başka cihaz yazmıştır) uzak kaydı okur, birleştirir ve en çok 3 kez dener. */
export async function saveToCloud(player: PlayerClient, local: PlayerDataValue): Promise<void> {
  let value = local;
  let current = await player.data.get(KEY).catch((error: unknown) => {
    if (error instanceof Error && "status" in error && error.status === 404) return null;
    throw error;
  });
  for (let attempt = 0; attempt < 3; attempt += 1) {
    try {
      if (current === null) await player.data.create(KEY, value);
      else await player.data.update(KEY, value, current.version);
      return;
    } catch (error: unknown) {
      if (!(error instanceof PlayerDataConflict)) throw error;
      current = error.currentVersion === null ? null : await player.data.get(KEY);
      if (current !== null) value = merge(current.value, value);
    }
  }
  throw new Error("Kayıt üç denemede birleştirilemedi");
}

Saklama ve silme

  • Oyuncu satırı hiç silinmez; terk edilmiş misafir hesapları kapatılırken (anonimleştirme) o hesabın oyuncu verisi aynı işlemde silinir.
  • Operatör, panelden bir anahtarı gerekçeyle silebilir; oyuncu kendi anahtarını If-Match ile siler.
  • Veri, oyuncu ve ortam başına yalıtılmıştır: bir ortamın oyuncusu başka ortamdan okunamaz.

Sık karşılaşılan durumlar

  • Sürekli 409 alıyorum. Başka bir cihaz yazıyor ya da update’e eski sürüm veriyorsunuz. Her yazımdan sonra dönen version değerini saklayın; çatışmada uzak kaydı okuyup birleştirin, ham sürümü artırıp tekrar göndermeyin.
  • 429 alıyorum. Dakikada 60 yazım sınırı oyuncu başınadır. Her tuş vuruşunda değil, gecikmeli (debounce) ve anlamlı noktalarda yazın; Retry-After kadar bekleyin.
  • 16 anahtar sınırı. Birden çok küçük anahtar yerine kayıt türü başına bir anahtar kullanın (ör. my-game.save, my-game.settings).

İlgili sayfalar