Arcade Docs & SDK v4.3.8 & Atölye UGC
Konsol Paneli Oyunlarım PlayZone & R2 Yeni Oyun Ekle PlayZone Arcade Mağaza
FELEROUS PLAYZONE ECOSYSTEM

Felerous Arcade SDK v4.3.8 & Atölye UGC Rehberi

HTML5 Canvas ve WebGL oyunlarınızı PlayZone platformuna bağlayarak oyunculara sıfır indirmeyle ulaştırın. Gerçek zamanlı skor telemetrisi, 18 kademeli profil başarımları, Steam-tarzı Topluluk Atölyesi (Workshop UGC) ve otomatik CDN optimizasyonu.

AI SDK Asistanı ("Kendi AI'ına Sor") & Anında Kod Sihirbazı

Canlı SDK v4.3 Bağlam Köprüsü /llms.txt Standardı Aktif ↗

Geleneksel kod yazmayı bilmenize veya saatlerce dokümantasyon okumanıza gerek yok! Konu türünü seçip ChatGPT'ye otomatik gönderebilir, panoya kopyalayıp kendi AI aracınıza (Gemini, Cursor, Antigravity) yapıştırabilir ya da sağdaki Anında Kod Sihirbazı ile 0 milisaniyede hazır entegrasyon kodunuzu üretebilirsiniz. (Ayrıca sağ alttaki AI SDK Rehberi baloncuğundan her an erişebilirsiniz!)

1. Akıllı SDK Paketleyici (Konu Seç & İlet) v4.3 Bağlam Gömmeli

Mesaj yazmanıza gerek yok! İhtiyacınız olan entegrasyon türünü aşağıdan seçin; tüm FELEROUS SDK v4.3 fonksiyonları seçtiğiniz konuya göre otomatik paketlensin:

2. Anında Kod Sihirbazı (0ms Şablon Üretici) 0ms Saf JS
İstenen SDK Özelliklerini Seçin:
Hazır Entegrasyon Kodu (index.html)

Sıfırdan Yayına: 6 Adımlı Geliştirici Yol Haritası

FELEROUS PlayZone Arcade ekosisteminde oyun yayınlama akışı lineer ve pürüzsüzdür:

1. Kayıt & Dev Handle Al
Geliştirici Başvurusu yapın. Onaylandığında DEV-FEL-XXXX kimliğiniz tanımlanır.
2. Oyunu Oluştur & Kimlik Al
Konsoldan " Yeni Oyun Ekle" deyin. Oyununuza tahsis edilen gameSlug ve App ID kimliğini kopyalayın.
3. 3 Zorunlu Görseli Ekle
1600×900 Kapak (cover), 1920×1080 Afiş (banner) ve 512×512 İkon (icon) hazırlayın. Otomatik WebP'ye küçültülür.
4. SDK & Şemaları Bağla
Resmi CDN köprüsünü ekleyin, manifest.json ve achievements.json şemalarınızı oluşturun.
5. Yerel Test & Doğrulama
Oyunu tarayıcınızda açın. Felerous SDK yerel test panelinde skor ve başarımların simülasyonunu izleyin.
6. ZIP Paketle & Gönder
Klasörü ZIP yapıp konsoldan incelemeye gönderin. Onay sonrası Cloudflare R2 üzerinden 0 TL maliyetle anında yayına girin.

1. 5 Dakikada Hızlı Başlangıç

Felerous Arcade ekosisteminin felsefesi: "Oyun akıcı çalışır (Dumb Engine), Platform skorları ve başarımları akıllıca yönetir (Smart Platform)."

2 Satırda Tak-Çalıştır (Plug & Play) Entegrasyon
Zero-Config Ready

İster kendi oyununuzu geliştirin, ister Yapay Zekaya (Gemini, Claude, Cursor) oyun yazdırın; Felerous ekosistemine küresel liderlik tablosu, oyuncu kimliği ve skor kaydı eklemek artık sadece 2 satır kod! Karmaşık biletler, süre hesaplamaları ve UI tabloları SDK tarafından otomatik yönetilir.

Sadece 2 Satır: index.html
<!-- 1. Köprüyü ekleyin -->
<script src="https://store.felerous.com/js/felerous-bridge_html5.js"></script>

<script>
  // 2. Oyun bittiğinde skoru gönderin & yerleşik şık liderlik tablosunu ekrana açın:
  felerousBridge.submitScore(score);      // Süre, bilet ve güvenlik arka planda otomatik!
  felerousBridge.showLeaderboard();       // Sıfır CSS hamallığı; neon cam modal anında açılır!
</script>
Rozet Ekle: felerousBridge.mountBadge()
Oyuncu Adı: felerousBridge.player.name
⭐ Oylama Aç: felerousBridge.openReviews()
Çift Motor Mimarisi (Dual-Engine SDK): Oyun motorunuza uygun optimize edilmiş köprüyü seçin. Saf HTML5 / Canvas projeleri için ultra hafif felerous-bridge_html5.js (~13KB), Phaser 3 projeleri için sahne yaşam döngüsü ve ses yönetimi entegreli felerous-bridge_phaser.js kullanın. Küp Avatar ve Canlı NPC kullanmak isterseniz bağımsız felerous-cuberig-sdk.js eklentisini dahil edebilirsiniz.
Seçenek A: HTML5 / Canvas 2D / Vanilla JS (felerous-bridge_html5.js)
<!-- 1. HTML5 Arcade Köprüsünü Dahil Edin (Ultra Hafif ~13KB, Sıfır Bağımlılık) -->
<script src="https://store.felerous.com/js/felerous-bridge_html5.js"></script>
<!-- İsteğe Bağlı: Oyununuzda Küp Avatar / Canlı Drivatar kullanacaksanız ekleyin -->
<script src="https://store.felerous.com/js/felerous-cuberig-sdk.js"></script>

<script>
  // 2. Konsoldan aldığınız kimliklerle el sıkışmayı başlatın:
  felerousBridge.init({
    gameSlug: 'dusen-sicimler',            // Oyununuzun benzersiz slug kodu
    appId: 1000002,                        // Geliştirici Konsolundaki App ID
    onReady: (player) => {
      console.log(' Oyuncu oturumu doğrulandı:', player.name, player.felerousId);
    },
    onAchievementConfirmed: (achId) => {
      console.log(' Başarım Supabase bulutuna mühürlendi:', achId);
    }
  });

  // 3. Başarım açma:
  felerousBridge.unlockAchievement('first_clear');

  // 4. Skor bildirimi:
  felerousBridge.submitScore({
    score: 18450,
    difficultyTier: 'lvl2',
    difficultyLabel: 'Klasik',
    durationSeconds: 120,
    achievements: ['first_clear'],
    stats: { lines_cleared: 15, apm: 90 }
  });
</script>
Seçenek B: Phaser 3 WebGL / Canvas Edition (felerous-bridge_phaser.js)
<!-- 1. Phaser 3 & Phaser Köprüsünü Dahil Edin -->
<script src="https://cdn.jsdelivr.net/npm/phaser@3.80.1/dist/phaser.min.js"></script>
<script src="https://store.felerous.com/js/felerous-bridge_phaser.js"></script>
<!-- İsteğe Bağlı Küp Avatar SDK -->
<script src="https://store.felerous.com/js/felerous-cuberig-sdk.js"></script>

<script>
class ArcadeScene extends Phaser.Scene {
    constructor() { super('ArcadeScene'); }

    create() {
        // Sahneyi ve Oyunu Köprüye Bağla (Otomatik pause/resume, mute ve delta süre sayacı aktif olur)
        felerousBridge.attachScene(this);

        felerousBridge.init({
            gameSlug: 'dusen-sicimler',
            appId: 1000002,
            bridgeToken: 'fel_sec_ORNEK_UYGULAMA_ANAHTARI',
            onReady: async (player) => {
                console.log(' Phaser Sahnesinde Oyuncu Eşleşti:', player.name);

                // Küp Avatar yüklüyse oyuncunun renk paletini WebGL sprite'a giydir
                if (window.FelerousCubeRig) {
                    const avatar = await FelerousCubeRig.getAvatar(player.felerousId);
                    if (avatar && avatar.palette && this.playerSprite) {
                        felerousBridge.applyTint(this.playerSprite, avatar.palette.primary);
                    }
                }
            }
        });
    }

    gameOver(finalScore) {
        // Otomatik hesaplanan net süre ve engine_type: 'Phaser3_WebGL' telemetrisiyle skoru gönder
        felerousBridge.submitScore({
            score: finalScore,
            difficultyTier: 'lvl2',
            difficultyLabel: 'Klasik'
        });
        felerousBridge.showLeaderboard();
    }
}

const config = { type: Phaser.AUTO, width: 1600, height: 900, scene: ArcadeScene };
const game = new Phaser.Game(config);
</script>

Yerel Test & Konsol Simülasyon Modu (Local Dev Mock)

Oyununuzu kendi bilgisayarınızda (localhost veya doğrudan index.html dosyasını açarak) test ettiğinizde köprü otomatik yerel test moduna geçer:

  • Tarayıcı DevTools konsolunda renkli [FelerousBridge: Yerel Test Modu (v4.3)] rozeti açılır.
  • Sanal bir test oyuncusu profili (DEV-TEST-001) tahsis edilir ve onReady callback'i otomatik tetiklenir.
  • submitScore() çağırdığınızda gönderilen tüm skor yükü (payload), süre ve başarımlar konsola detaylı tablo halinde basılır. "Köprü çalışıyor mu?" şüphesine yer kalmaz!

2. Evrensel Klasör Standardı

Cloudflare R2 kovanına yüklenecek olan oyun paketinizin kök dizini standart ve temiz olmalıdır:

Dosya ve Dizin Hiyerarşisi
[oyun-slug-kodu]/                      (Örn: dusen-sicimler/)
├── index.html                         # Oyunun giriş noktası (HTML5 Canvas)
├── manifest.json                      # [ÖNERİLEN] FDB dosya ağacı & paket kimliği
├── achievements.json                  # [ÖNERİLEN] Oyunun tüm başarımları (v1.0.1)
├── changelog.json                     # [OPSİYONEL] Sürüm geçmişi (FDB Depo sekmesinde gösterilir)
├── icon.png                           # 512x512 kare vitrin ikonu (1:1)
├── cover.png                          # Yatay vitrin kapağı (16:9 - 1600x900 veya 1920x1080)
├── banner.png                         # Geniş sinematik afiş görseli (16:9 - 1920x1080 Full HD)
├── shortcut.png                       # [4. GÖRSEL STANDARDI] 512x512 mobil ana ekran (PWA) & masaüstü kısayol simgesi (yoksa icon.png kullanılır)
├── css/
│   └── style.css                      # Oyun stilleri (100dvh ve koyu mod korumalı)
└── js/
    ├── felerous-bridge.js             # Felerous Store resmi köprü SDK'sı
    ├── sound.js                       # 8-bit prosedürel Web Audio motoru
    └── game.js                        # Oyun mantığı ve döngüsü
R2 Temizlik Kuralı: Dağıtım klasörünüzde kesinlikle server.js, node_modules/, .git/ veya geçici geliştirici notları bulunmamalıdır. Sadece tarayıcının doğrudan çalıştıracağı saf dosyalar yer almalıdır.

2.1 FelerousStore Arcade — 4 Görsel Standardı (Vitrin + Mobil/Masaüstü Kısayol)

Oyun paketinizin Cloudflare R2 kovan kök dizininde, PlayZone vitrininde, Haber Merkezinde ve oyuncuların telefon ana ekranı / PC masaüstü kısayollarında en yüksek kalitede sunulması için aşağıdaki 4 görsel standardı tanımlanmıştır:

Dosya Adı En-Boy Oranı Standart Çözünürlük Format Mağaza & Cihazdaki Kullanım Alanı
icon.png 1:1 (Kare) 512×512 px PNG Mağaza vitrin listesi simgesi, Haber Merkezi oyun rozeti, FDB logosu ve tarayıcı favicon'u.
cover.png 16:9 (Yatay Vitrin) 1600×900 px (veya 1920×1080) PNG FelerousStore oyun kartı kapağı, Haber Merkezi küçük görseli ve oyun açılış splash ekranı.
banner.png 16:9 (Geniş Afiş) 1920×1080 px (Full HD) PNG PlayZone oyun detay sayfasının ve FDB veri takibinin en üstündeki sinematik hero/afiş arka planı.
shortcut.png 1:1 (Maskable Kısayol) 512×512 px PNG 4. Görsel Standardı: Oyuncuların PlayZone üzerinden telefon ana ekranına (iOS/Android PWA) veya PC masaüstüne (Tauri / .url) eklediği uygulama kısayol simgesi. (Pakette yoksa sistem otomatik olarak icon.png dosyasını kullanır.)
Optimizasyon Tavsiyesi: Görsellerinizi PNG formatında hazırladıktan sonra TinyPNG veya benzeri kayıpsız sıkıştırma araçlarından geçirmeniz sayfa yüklenme hızını artırır. Felerous altyapısı bu görselleri gerektiğinde modern WebP formatına dönüştürerek istemcilere sunar.

3. MANIFEST.JSON Spesifikasyonu & FDB Dosya Ağacı

Oyun paketinin sürümünü mühürlemek, FDB (FELEROUS Database) sisteminde dosya ağacını listelemek ve Geliştirici Panelindeki formu tek tıkla otomatik doldurmak için kök dizinde manifest.json yer alır.

ℹ
Vitrin Otoritesi Geliştirici Panelindedir: Oyunun PlayZone vitrinindeki adı, filtre kategorisi (örn: Retro / Piksel, Bulmaca, Aksiyon), kapak görseli ve kontrolleri doğrudan Geliştirici Paneli üzerinden yönetilir. manifest.json vitrin filtrelerini ezmez; FDB dosya ağacını oluşturmak ve geliştiriciye form doldurma kolaylığı sağlamak için teknik bir kimlik belgesidir.
manifest.json (Düşen Sicimler v1.0.5 Referansı)
{
  "id": "dusen-sicimler",
  "slug": "dusen-sicimler",
  "name": "Düşen Sicimler",
  "version": "1.0.5",
  "developer": "Subushaki",
  "publisher": "FELEROUS",
  "category": "Retro / Piksel",
  "game_type": "web",
  "entry": "index.html",
  "icon": "icon.png",
  "cover": "cover.png",
  "banner": "banner.png",
  "shortcut": "shortcut.png",
  "orientation": "portrait_or_landscape",
  "resolution": {
    "width": 1080,
    "height": 1920,
    "responsive": true
  },
  "features": {
    "achievements": true,
    "leaderboards": true,
    "anti_cheat": true,
    "telemetry": true
  },
  "files": [
    { "name": "index.html", "type": "Oyun Giriş Dosyası" },
    { "name": "banner.png", "type": "Afiş Görseli" },
    { "name": "cover.png", "type": "Kapak Görseli" },
    { "name": "icon.png", "type": "Oyun İkonu" },
    { "name": "manifest.json", "type": "Oyun Yapılandırması" },
    { "name": "achievements.json", "type": "Başarım Veritabanı" },
    { "name": "changelog.json", "type": "Sürüm Notları" },
    { "name": "js/game.js", "type": "Oyun Motoru & Mantığı" },
    { "name": "js/felerous-bridge_html5.js", "type": "Platform SDK Köprüsü" },
    { "name": "js/sound.js", "type": "8-bit Ses Motoru" },
    { "name": "css/style.css", "type": "Stil Dosyası" }
  ]
}
Alan Tür Açıklama
id String Veritabanı ve API ile eşleşen benzersiz kimlik (snake_case). Örn: dusen_sicimler.
slug String URL ve R2 klasör adı (kebab-case). Örn: dusen-sicimler.
version String Anlık oyun sürümü (SemVer formatı: "1.0.3"). FDB Depo başlığında gösterilir.
orientation String Mobil yön tercihi: "portrait", "landscape" veya "portrait_or_landscape".
features Object Oyunun desteklediği platform yetenekleri (başarımlar, liderlik tabloları, hile koruması, telemetri).
files Array FDB "Depolar" (Depots) sekmesinde taranan dosya listesi. Her dosyanın adı ve insan-okunabilir işlevi belirtilir.

4. ACHIEVEMENTS.JSON Spesifikasyonu (18 Başarım Tam Referansı)

Felerous Store ekosisteminde başarımların tek doğru kaynağı (Single Source of Truth) oyun kökündeki achievements.json dosyasıdır. FDB Başarımlar sekmesi, oyun içi HUD bildirimleri ve oyuncunun Steam-standardı Profil Vitrini bu dosyayı okur.

achievements.json (Düşen Sicimler Resmi 18 Başarımı — 1000 XP)
{
  "game_id": "dusen-sicimler",
  "version": "1.0.5",
  "total": 18,
  "achievements": [
    {
      "id": "first_clear",
      "title": "İlk Adım",
      "description": "İlk satırını başarıyla temizle.",
      "icon": "",
      "category": "progression",
      "rarity": "common",
      "points": 10
    },
    {
      "id": "tetris_master",
      "title": "Düşen Sicim",
      "description": "Tek hamlede 4 satır birden sil.",
      "icon": "",
      "category": "skill",
      "rarity": "rare",
      "points": 25
    },
    {
      "id": "combo_king",
      "title": "Kombo Ustası",
      "description": "En az 4x ardışık satır kombosu yap.",
      "icon": "",
      "category": "skill",
      "rarity": "epic",
      "points": 50
    },
    {
      "id": "hard_dropper",
      "title": "Işık Hızı",
      "description": "Tek oyunda 25 kez sert düşüş (smash) yap.",
      "icon": "",
      "category": "speed",
      "rarity": "uncommon",
      "points": 15
    },
    {
      "id": "survivor",
      "title": "Kabus Gazisi",
      "description": "Kabus modunda en az 60 saniye hayatta kal.",
      "icon": "",
      "category": "survival",
      "rarity": "legendary",
      "points": 100
    },
    {
      "id": "architect",
      "title": "Büyük Mimar",
      "description": "Tek bir oyunda 50+ satır sil.",
      "icon": "",
      "category": "endurance",
      "rarity": "epic",
      "points": 50
    },
    {
      "id": "high_scorer",
      "title": "Puan Avcısı",
      "description": "Tek bir oyunda 20.000 puanı aş.",
      "icon": "",
      "category": "score",
      "rarity": "rare",
      "points": 30
    },
    {
      "id": "tactician",
      "title": "Usta Taktisyen",
      "description": "Hold (saklama) özelliğini en az 10 kez kullan.",
      "icon": "",
      "category": "strategy",
      "rarity": "uncommon",
      "points": 15
    },
    {
      "id": "double_trouble",
      "title": "Çifte Vuruş",
      "description": "Toplam 50 İkili Satır (2 satır birden) temizle.",
      "icon": "2⃣",
      "category": "skill",
      "rarity": "uncommon",
      "points": 20
    },
    {
      "id": "triple_threat",
      "title": "Üçlü Tehdit",
      "description": "Toplam 25 Üçlü Satır (3 satır birden) temizle.",
      "icon": "3⃣",
      "category": "skill",
      "rarity": "rare",
      "points": 35
    },
    {
      "id": "back_to_back",
      "title": "Ardarda Tetris",
      "description": "Arka arkaya 2 Tetris (4 satır) yap.",
      "icon": "",
      "category": "skill",
      "rarity": "epic",
      "points": 60
    },
    {
      "id": "perfect_clear",
      "title": "Mükemmel Temizlik",
      "description": "Tahtayı tamamen boşalt (Perfect Clear).",
      "icon": "",
      "category": "skill",
      "rarity": "legendary",
      "points": 120
    },
    {
      "id": "speed_demon",
      "title": "Hız Canavarı",
      "description": "1 dakika içinde 40 satır temizle.",
      "icon": "⏱",
      "category": "speed",
      "rarity": "rare",
      "points": 40
    },
    {
      "id": "marathon_runner",
      "title": "Maratoncu",
      "description": "Toplam 1000 satır temizle.",
      "icon": "",
      "category": "endurance",
      "rarity": "epic",
      "points": 75
    },
    {
      "id": "piece_master",
      "title": "Parça Ustası",
      "description": "Toplam 1000 parça indir.",
      "icon": "",
      "category": "progression",
      "rarity": "rare",
      "points": 30
    },
    {
      "id": "apm_champion",
      "title": "Hızlı Parmaklar",
      "description": "Bir oyunda 300 APM (Aksiyon/Dk) üzerine çık.",
      "icon": "",
      "category": "speed",
      "rarity": "epic",
      "points": 55
    },
    {
      "id": "nightmare_warrior",
      "title": "Kabus Savaşçısı",
      "description": "Kabus modunda 120 saniye hayatta kal.",
      "icon": "",
      "category": "survival",
      "rarity": "legendary",
      "points": 170
    },
    {
      "id": "millionaire",
      "title": "Milyoner",
      "description": "Toplam 1.000.000 kariyer puanı topla.",
      "icon": "",
      "category": "score",
      "rarity": "legendary",
      "points": 100
    }
  ]
}
Steam Tarzı Profil Entegrasyonu: Bir oyuncu başarım kazandığında profiline işlenir. Profil sayfasında (profile.html) oyuncunun açtığı başarımlar, toplam başarıma oranlanarak dinamik renkli Steam ilerleme çubuğunda (BAŞARIMLAR: N/18 (%X)) ve akordeon detay çekmecesinde sergilenir.

5. CHANGELOG.JSON Spesifikasyonu (FDB Sürüm Günlüğü & Depolar)

Oyununuz güncellendikçe FDB (FELEROUS Database) "Depolar" sekmesinde sürüm geçmişinin otomatik taranıp SteamDB tarzında değişiklik günlüğü (patch notes) olarak sunulması için kök dizinde changelog.json tutulur.

changelog.json (Düşen Sicimler Gerçek Sürüm Günlüğü)
[
  {
    "version": "v1.0.3",
    "date": "2026-09-27T18:35:00Z",
    "description": "Başarım açılışı ve ses motoru stabilite güncellemesi.",
    "changes": [
      "Başarım kilidi açıldığında oluşan ses motoru uyumsuzluğu giderildi",
      "Kesintisiz oyun için başarım akışları tam korumalı (fail-safe) hale getirildi",
      "Özel prosedürel zafer arpeji (playAchievement) ses motoruna eklendi"
    ]
  },
  {
    "version": "v1.0.2",
    "date": "2026-09-27T00:00:00Z",
    "description": "Canvas doğrudan dokunmatik kaydırma ve jest kontrolleri güncellemesi.",
    "changes": [
      "Tahta üzerinde doğrudan parmakla sola/sağa hassas blok kaydırma eklendi",
      "Yatay kaydırma sırasında kazara düşüşleri önleyen eksen kilidi (axis lock) geliştirildi",
      "Aşağı hızlı kaydırmada (flick down) doğrudan zemine yapışma (Hard Drop) eklendi",
      "Tek dokunuşla (tap) 90 derece döndürme ve yukarı kaydırmayla saklama (Hold) entegre edildi"
    ]
  },
  {
    "version": "v1.0.1",
    "date": "2026-09-26T21:30:00Z",
    "description": "18 Başarım Paketi ve Kariyer Takibi güncellemesi.",
    "changes": [
      "10 yeni beceri ve kariyer başarımı eklendi (toplam 18 başarım)",
      "Kümülatif kariyer istatistikleri ve SafeStorage kalıcılığı sağlandı",
      "Perfect Clear (Mükemmel Temizlik) ve Back-to-Back Tetris tespiti eklendi"
    ]
  },
  {
    "version": "v1.0.0",
    "date": "2026-09-26T21:00:00Z",
    "description": "Düşen Sicimler resmi PlayZone ve FDB lansman sürümü.",
    "changes": [
      "8 adet Arcade başarımı entegre edildi",
      "Gerçek zamanlı Supabase telemetrisi bağlandı",
      "FDB Depo tarama desteği eklendi",
      "Mobil, Samsung Internet ve Safari tam uyumluluk optimizasyonları yapıldı"
    ]
  }
]

6. Resmi Köprü SDK: felerous-bridge_html5.js & felerous-bridge_phaser.js (v4.3.8 — 6 Katmanlı Skor Doğrulama, Origin Kontrolü & Atölye UGC)

Oyununuz ile PlayZone çerçevesi arasındaki tüm iletişimi yöneten köprü sınıfı. Sahte skor ve manipülasyonları engellemek için App ID, Çift Yönlü Origin Doğrulaması, Steam-Tarzı Topluluk Atölyesi (Workshop UGC) ve tek kullanımlık Oturum Bileti (Session Ticket) mekanizmasını içerir. Ayrıca iframe dışındayken otomatik Yerel Test & Simülasyon Modu sağlar:

6 Katmanlı Skor & Anti-Cheat Doğrulaması Nasıl Çalışır?
  • Çift Yönlü Köken (Origin) Doğrulaması: Köprü, gelen postMessage olaylarını yalnızca yetkili Felerous platform alan adlarından (https://store.felerous.com, https://arcade.felerous.com, https://developer.felerous.com) ve yerel test kökenlerinden (localhost, 127.0.0.1) kabul eder. Üçüncü taraf veya sahte iframe'lerden gelen mesajlar sessizce elenir.
  • Korumalı Anahtar Saklama (game_secrets): Sunucu/webhook anahtarları asla umumi games tablosunda veya istemci JS kodunda tutulmaz; Row Level Security (RLS) politikalarıyla korunan public.game_secrets tablosunda saklanır.
  • Liderlik Tablosunda Kimlik Sabitlemesi (Anti-Spoofing): Supabase veritabanındaki enforce_arcade_score_identity() tetikleyicisi sayesinde oyuncu skor gönderirken başka birinin felerous_id veya player_name kimliğini taklit edemez; oturum açtığı gerçek profiles kaydı zorunlu olarak mühürlenir.
  • Tek Kullanımlık Oturum Bileti (Session Ticket) & Erken Skor Kuyruğu: Oyun açıldığında ve her yeni elde (startSession()) tek kullanımlık süreli bilet üretilir. Oyuncu el sıkışma tamamlanmadan skor gönderirse, v4.3.8 kuyruğu (_pendingScores) bileti bekleyip skoru kayıpsız iletir.
  • Hız & Mantık Analizi (Velocity Check): Oyun süresiyle uyuşmayan imkansız puanlar (örneğin 3 saniyede 1 milyon puan) otomatik elenir ve güvenlik günlüğüne kaydedilir.
  • Geliştirici 2FA Güvencesi: Konsolda anahtar yenileme, paket yükleme ve silme gibi tüm kritik işlemler TOTP tabanlı 2FA oturum bileti ile korunur.

Geliştirici Entegrasyon Rehberi (3 Kolay Adım)

1. Adım: Geliştirici Konsolundan Oyun Kimliğinizi (gameSlug & App ID) Alın

Kimlik bilgilerinize Konsol'da 3 kolay yerden ulaşabilirsiniz: 1) Güvenlik Masası (4. Katman), 2) PlayZone Oyunlarım ekranı, veya 3) Oyun Düzenle (#edit) sayfası (Bölüm 4). İstemci (tarayıcı) kodunda yalnızca herkese açık gameSlug ve sayısal App ID (örn: 1000010) kullanılır; gizli tokenler istemci koduna gömülmez.

Korumalı Anahtar & Yenileme: Sunucu/webhook anahtarınızı yenilemek isterseniz " Tokeni Sıfırla / Yenile" butonuna basabilirsiniz (2FA doğrulamalı). Önceki anahtar game_secrets tablosundan anında silinir ve yenisi üretilir.
2. Adım: Motorunuza Uygun SDK Köprüsünü Ekleyin

Oyununuzun altyapısına göre optimize edilmiş resmi CDN betiğini index.html dosyanıza ekleyin:

Saf HTML5 / Canvas 2D / DOM (Ultra Hafif ~53KB ham / ~11.3KB gzip):
<script src="https://store.felerous.com/js/felerous-bridge_html5.js"></script>
Phaser 3 WebGL & Canvas Edition (~56KB ham / ~11.9KB gzip):
<script src="https://store.felerous.com/js/felerous-bridge_phaser.js"></script>
İsteğe Bağlı: Küp Avatar & Canlı NPC Havuzu Eklentisi (~14KB ham / ~4.3KB gzip):
<script src="https://store.felerous.com/js/felerous-cuberig-sdk.js"></script>
3. Adım: Başlatın & Oyun Bittiğinde Skoru Gönderin

Oyun başladığında konsoldan aldığınız kimliklerle el sıkışmayı başlatın. HTML5 için doğrudan çağırabilir, Phaser 3 için felerousBridge.attachScene(this) ile sahneyi bağlayabilirsiniz:

HTML5 / Canvas 2D Entegrasyonu:
<script>
  felerousBridge.init({
    gameSlug: 'neon-volt',
    appId: 1000010,
    mountBadge: 'top-right',
    onReady: (player) => {
      console.log(' Oyuncu hazır:', player.name, player.felerousId);
    }
  });

  // Oyun bittiğinde (tek satır veya detaylı obje):
  felerousBridge.submitScore(14500, 'lvl2');
  felerousBridge.showLeaderboard();
</script>
Phaser 3 Scene Entegrasyonu:
<script>
class MyGameScene extends Phaser.Scene {
    create() {
        felerousBridge.attachScene(this); // Otomatik duraklatma, sessize alma ve oynanış süresi
        felerousBridge.init({
            gameSlug: 'neon-volt',
            appId: 1000010,
            onReady: (player) => {
                console.log(' Phaser Sahnesinde Oyuncu Eşleşti:', player.name);
            }
        });
    }

    onGameOver(finalScore) {
        felerousBridge.submitScore({
            score: finalScore,
            difficultyTier: 'lvl2',
            difficultyLabel: 'Uzman'
        });
        felerousBridge.showLeaderboard();
    }
}
</script>
Yerel Geliştirici Simülasyon Modu (Local Dev & Offline Mock)

Oyununuzu PlayZone'a yüklemeden önce kendi bilgisayarınızda (localhost, 127.0.0.1 veya doğrudan dosya olarak) çalıştırdığınızda SDK durumu otomatik algılar (isEmbedded = false):

  • Sanal Test Oturumu: DEV-TEST-001 kodlu test profili simüle edilir, onReady ve on('ready') dinleyicileri 50ms içinde otomatik ateşlenir.
  • Görsel Konsol Logları: Tarayıcının F12 konsolunda stilize edilmiş [Yerel Test & Simülasyon Modu Aktif (v4.3)] bildirim kartı gösterilir.
  • Polimorfik Skor & Başarım Doğrulaması: submitScore(14500) veya submitScore({ score: 14500, difficultyTier: 'lvl2' }) çağrıldığında yük verileri konsolda doğrulanır.
  • Sahte Liderlik Tablosu & Neon Cam Modal: showLeaderboard() veya requestLeaderboard() çağrıldığında anında mock ilk 3 sıralama verisi ve yerleşik Neon Cam arayüzü açılır.
js/felerous-bridge_html5.js (SDK v4.3.8 Birleşik Çekirdek Referansı)
/**
 *  FELEROUS ARCADE BRIDGE SDK — HTML5 / CANVAS / WEBGL EDITION (v4.3.8)
 * Resmi CDN: https://store.felerous.com/js/felerous-bridge_html5.js
 * Phaser 3 CDN: https://store.felerous.com/js/felerous-bridge_phaser.js
 *
 * Özellikler:
 * - Polimorfik submitScore(score, tier) & submitScore({ score, difficultyTier, ... })
 * - Yerleşik Neon Cam Liderlik Tablosu (showLeaderboard / closeLeaderboard) & Köşe Rozeti (mountBadge)
 * - Erken skor gönderimlerini koruyan _pendingScores kuyruğu (FELEROUS_PLAYER_INFO el sıkışmasını bekler)
 * - Çift yönlü Origin doğrulaması, Pause / Resume / Mute sinyalleri, Cloud Save & Workshop UGC
 * - Hem kanonik (name, felerousId, avatar) hem alias (username, displayName, felId, avatarUrl) oyuncu alanları
 */
class FelerousBridgeHTML5 {
    constructor(config = {}) {
        if (typeof config === 'string') config = { gameSlug: config };
        this.version = '4.3.8-html5';
        this.engine = 'html5';
        this.gameSlug = config.gameSlug || config.gameId || 'felerous-game';
        this.appId = config.appId || null;
        this.bridgeToken = config.bridgeToken || null;
        this.targetOrigin = config.targetOrigin || 'https://store.felerous.com';

        this.player = this._buildPlayerObject({
            name: 'Oyuncu',
            felerousId: null,
            avatar: 'https://store.felerous.com/image/felerous/FELEROUS.png',
            isGuest: true,
            userId: null
        });
        this.sessionTicket = null;
        this.leaderboard = [];
        this.friends = [];
        this._pendingScores = [];
        this._memoryStorage = {};
        this._verifiedParentOrigin = null;
        this.isEmbedded = typeof window !== 'undefined' && window.self !== window.top;
        this.sessionStartTime = Date.now();
        this.isReady = false;
        this._resolveReady = null;
        this.ready = new Promise((resolve) => {
            this._resolveReady = resolve;
        });

        this._listeners = { ready: [], pause: [], resume: [], mute: [], leaderboard: [], achievement: [], friends: [] };
        this.workshop = new FelerousWorkshopClient(this);

        if (config.onReady) this.on('ready', config.onReady);
        if (config.onLeaderboard) this.on('leaderboard', config.onLeaderboard);
        if (config.onAchievementConfirmed) this.on('achievement', config.onAchievementConfirmed);

        this._setupListeners();
    }

    _isLocalDevEnvironment() {
        if (typeof window === 'undefined' || !window.location) return false;
        const protocol = window.location.protocol;
        const host = (window.location.hostname || '').toLowerCase();
        return (
            protocol === 'file:' ||
            host === 'localhost' ||
            host === '127.0.0.1' ||
            host === '::1' ||
            host === '[::1]' ||
            host.endsWith('.local')
        );
    }

    _isTrustedOrigin(origin) {
        if (!origin || typeof origin !== 'string') return false;
        const trustedOrigins = [
            'https://store.felerous.com',
            'https://arcade.felerous.com',
            'https://developer.felerous.com',
            'https://felerous-store.vercel.app'
        ];
        if (this.targetOrigin && this.targetOrigin !== '*' && !trustedOrigins.includes(this.targetOrigin)) {
            trustedOrigins.push(this.targetOrigin);
        }
        if (trustedOrigins.includes(origin)) return true;
        if (this._isLocalDevEnvironment()) {
            return /^http:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/i.test(origin);
        }
        return false;
    }

    _resolveTargetOrigin() {
        if (this._verifiedParentOrigin && this._isTrustedOrigin(this._verifiedParentOrigin)) {
            return this._verifiedParentOrigin;
        }
        if (typeof document !== 'undefined' && document.referrer) {
            try {
                const refOrigin = new URL(document.referrer).origin;
                if (this._isTrustedOrigin(refOrigin)) return refOrigin;
            } catch (_) {}
        }
        if (this.targetOrigin && this.targetOrigin !== '*' && this._isTrustedOrigin(this.targetOrigin)) {
            return this.targetOrigin;
        }
        return 'https://store.felerous.com';
    }

    _buildPlayerObject(raw = {}) {
        const name = raw.name || raw.player_name || raw.username || raw.displayName || 'Oyuncu';
        const felerousId = raw.felerousId || raw.felerous_id || raw.felId || null;
        const avatar = raw.avatar || raw.avatar_url || raw.avatarUrl || 'https://store.felerous.com/image/felerous/FELEROUS.png';
        const isGuest = raw.isGuest !== undefined ? Boolean(raw.isGuest) : Boolean(raw.is_guest);
        const userId = raw.userId || raw.user_id || raw.id || felerousId || null;
        return {
            name, felerousId, avatar, isGuest, userId,
            username: name, displayName: name, felId: felerousId, avatarUrl: avatar, id: userId || felerousId || 'guest'
        };
    }

    on(event, callback) {
        if (typeof callback !== 'function') return this;
        if (!this._listeners[event]) this._listeners[event] = [];
        this._listeners[event].push(callback);
        if (event === 'ready' && this.isReady) callback(this.player);
        return this;
    }

    onReady(cb) { return this.on('ready', cb); }
    onLeaderboard(cb) { return this.on('leaderboard', cb); }
    onAchievementConfirmed(cb) { return this.on('achievement', cb); }
    onFriends(cb) { return this.on('friends', cb); }

    _emit(event, data, extra) {
        (this._listeners[event] || []).forEach(fn => {
            try { fn(data, extra); } catch (e) { console.warn('[FelerousBridge]', e); }
        });
    }

    init(options = {}) {
        if (typeof options === 'string') options = { gameSlug: options };
        if (options.gameSlug || options.gameId) this.gameSlug = options.gameSlug || options.gameId;
        if (options.appId) this.appId = options.appId;
        if (options.bridgeToken) this.bridgeToken = options.bridgeToken;
        if (options.targetOrigin) this.targetOrigin = options.targetOrigin;
        if (options.onReady) this.on('ready', options.onReady);
        if (options.onLeaderboard) this.on('leaderboard', options.onLeaderboard);
        if (options.onAchievementConfirmed) this.on('achievement', options.onAchievementConfirmed);
        if (options.mountBadge) {
            this.mountBadge(typeof options.mountBadge === 'object' ? options.mountBadge : { position: options.mountBadge });
        }

        this.sessionStartTime = Date.now();

        return new Promise((resolve) => {
            const handleReady = (p) => {
                if (this._resolveReady) this._resolveReady(p);
                resolve(p);
            };

            if (this.isReady && this.player) {
                handleReady(this.player);
                return;
            }

            this.on('ready', handleReady);

            if (this.isEmbedded) {
                this._postToParent({
                    type: 'FELEROUS_INIT_PLAYER',
                    game_id: this.gameSlug,
                    app_id: this.appId,
                    bridge_token: this.bridgeToken,
                    timestamp: Date.now()
                });
            } else if (this._isLocalDevEnvironment()) {
                //  Yerel Geliştirici Simülasyon Modu (Yalnızca localhost / 127.0.0.1 / file://)
                setTimeout(() => {
                    if (!this.isReady) {
                        this.player = this._buildPlayerObject({
                            name: 'Geliştirici (Yerel Test)',
                            felerousId: 'DEV-TEST-001',
                            avatar: 'https://store.felerous.com/image/felerous/FELEROUS.png',
                            isGuest: false,
                            userId: 'mock-dev-id'
                        });
                        this.sessionTicket = 'mock_tkt_' + Date.now();
                        this.isReady = true;
                        this._emit('ready', this.player);
                    }
                }, 50);
            } else {
                //  Üretim Ortamında Doğrudan Açılış — Standalone Misafir Modu
                setTimeout(() => {
                    if (!this.isReady) {
                        this.player = this._buildPlayerObject({
                            name: 'Misafir Oyuncu',
                            felerousId: null,
                            avatar: 'https://store.felerous.com/image/felerous/FELEROUS.png',
                            isGuest: true,
                            userId: null
                        });
                        this.sessionTicket = null;
                        this.isReady = true;
                        this._emit('ready', this.player);
                    }
                }, 50);
            }
        });
    }

    _setupListeners() {
        if (typeof window === 'undefined' || typeof window.addEventListener !== 'function') return;

        window.addEventListener('message', (event) => {
            if (this.isEmbedded) {
                if (event.source !== window.parent) return;
                if (!this._isTrustedOrigin(event.origin)) return;
                this._verifiedParentOrigin = event.origin;
            } else if (!this._isLocalDevEnvironment()) {
                return;
            }

            const data = event.data;
            if (!data || typeof data !== 'object') return;

            switch (data.type) {
                case 'FELEROUS_PLAYER_INFO':
                case 'FELEROUS_AUTH_SUCCESS':
                    this.player = this._buildPlayerObject(data);
                    if (data.session_ticket) this.sessionTicket = data.session_ticket;
                    this.isReady = true;
                    if (this._resolveReady) this._resolveReady(this.player);
                    this._flushPendingScores();
                    this._emit('ready', this.player);
                    break;
                case 'FELEROUS_LEADERBOARD_UPDATE':
                    this.leaderboard = data.leaderboard || [];
                    this._emit('leaderboard', this.leaderboard);
                    break;
                case 'FELEROUS_ACHIEVEMENT_CONFIRMED':
                    this._emit('achievement', data);
                    break;
                case 'FELEROUS_FRIENDS_DATA':
                    this._emit('friends', data.friends || []);
                    break;
            }
        });
    }

    _flushPendingScores() {
        if (!this.sessionTicket || !this._pendingScores || this._pendingScores.length === 0) return;
        const queue = this._pendingScores.splice(0, this._pendingScores.length);
        queue.forEach(payload => {
            payload.session_ticket = this.sessionTicket;
            this._postToParent(payload);
        });
    }

    submitScore(input = 0, maybeTier = 'lvl1') {
        let cfg = {};
        if (typeof input === 'number') {
            cfg = (typeof maybeTier === 'object' && maybeTier !== null)
                ? { ...maybeTier, score: input }
                : { score: input, difficultyTier: typeof maybeTier === 'string' ? maybeTier : 'lvl1' };
        } else if (typeof input === 'object' && input !== null) {
            cfg = input;
        }

        const rawDuration = cfg.durationSeconds !== undefined && cfg.durationSeconds !== null
            ? Number(cfg.durationSeconds)
            : Math.floor((Date.now() - this.sessionStartTime) / 1000);
        const duration = Math.max(1, Math.floor(Number.isFinite(rawDuration) ? rawDuration : 1));

        const payload = {
            type: 'FELEROUS_SUBMIT_SCORE',
            game_id: this.gameSlug,
            app_id: this.appId,
            bridge_token: this.bridgeToken,
            session_ticket: this.sessionTicket,
            score: Math.max(0, Math.floor(Number(cfg.score) || 0)),
            level_reached: cfg.levelReached || 1,
            lines_cleared: cfg.linesCleared || 0,
            difficulty_tier: cfg.difficultyTier || 'lvl1',
            difficulty_label: cfg.difficultyLabel || 'Standart',
            duration_seconds: duration,
            achievements: cfg.achievements || [],
            stats: cfg.stats || {},
            timestamp: Date.now()
        };

        if (this.isEmbedded) {
            if (!this.sessionTicket) {
                if (this._pendingScores.length < 20) this._pendingScores.push(payload);
                this._postToParent({
                    type: 'FELEROUS_INIT_PLAYER',
                    game_id: this.gameSlug,
                    app_id: this.appId,
                    bridge_token: this.bridgeToken,
                    timestamp: Date.now()
                });
            } else {
                this._postToParent(payload);
            }
        }
        return Promise.resolve(payload);
    }

    unlockAchievement(achievementId) {
        if (!achievementId) return;
        this._postToParent({
            type: 'FELEROUS_UNLOCK_ACHIEVEMENT',
            game_id: this.gameSlug,
            app_id: this.appId,
            session_ticket: this.sessionTicket,
            achievement_id: achievementId,
            timestamp: Date.now()
        });
    }

    requestLeaderboard(difficultyTier = null) {
        if (this.isEmbedded) {
            this._postToParent({
                type: 'FELEROUS_GET_LEADERBOARD',
                game_id: this.gameSlug,
                difficulty_tier: difficultyTier
            });
        }
    }

    getLeaderboard(difficultyTier = null) { return this.requestLeaderboard(difficultyTier); }

    saveCloudData(slotOrData = 'default', maybeData = undefined) {
        const slotKey = (maybeData === undefined && typeof slotOrData === 'object') ? 'default' : String(slotOrData || 'default');
        const data = (maybeData === undefined && typeof slotOrData === 'object') ? slotOrData : maybeData;
        try { localStorage.setItem(`felerous_cloud_${this.gameSlug}_${slotKey}`, JSON.stringify(data)); } catch (e) {}
        if (this.isEmbedded) {
            this._postToParent({ type: 'FELEROUS_CLOUD_SAVE', game_id: this.gameSlug, app_id: this.appId, session_ticket: this.sessionTicket, slot: slotKey, data, timestamp: Date.now() });
        }
        return Promise.resolve({ success: true, slot: slotKey });
    }

    loadCloudData(slotKey = 'default') {
        try {
            const raw = localStorage.getItem(`felerous_cloud_${this.gameSlug}_${slotKey}`);
            return Promise.resolve(raw ? JSON.parse(raw) : null);
        } catch (e) { return Promise.resolve(null); }
    }

    openReviews() {
        if (this.isEmbedded) {
            this._postToParent({
                type: 'FELEROUS_OPEN_REVIEWS',
                game_id: this.gameSlug,
                app_id: this.appId,
                timestamp: Date.now()
            });
        }
    }

    exitToPlayzone() {
        const targetUrl = 'https://store.felerous.com/playzone';
        if (this.isEmbedded) {
            this._postToParent({ type: 'FELEROUS_EXIT_GAME', game_id: this.gameSlug, redirect_url: targetUrl });
        }
        setTimeout(() => {
            try {
                if (window.top && window.top !== window.self) window.top.location.href = targetUrl;
                else window.location.href = targetUrl;
            } catch (e) {
                window.location.href = targetUrl;
            }
        }, 150);
    }

    _postToParent(payload) {
        if (!this.isEmbedded || typeof window === 'undefined' || !window.parent || window.parent === window.self) return;
        try {
            const targetOrigin = this._resolveTargetOrigin();
            if (!targetOrigin || targetOrigin === '*') return;
            window.parent.postMessage(payload, targetOrigin);
        } catch (e) {
            console.warn('[FelerousBridge] postMessage hatası:', e);
        }
    }
}

felerousBridge API Referans Kataloğu (v4.3)

Aşağıdaki metotlar hem felerous-bridge_html5.js hem felerous-bridge_phaser.js motorlarında (ve geriye dönük uyumluluk kalkanında) evrensel olarak desteklenir:

Metot / Özellik Motor Dönüş Tipi Açıklama & Kullanım Örneği
submitScore(score, tier) Tüm Motorlar void 2 Satırda Tak-Çalıştır: Skoru platforma iletir. Tek bir sayı (submitScore(14500)) veya detaylı obje kabul eder. Süre ve anti-cheat telemetrisi otomatiktir.
showLeaderboard(options) Tüm Motorlar void Yerleşik Neon Cam Modal: Oyunun üzerine sıfır CSS ile küresel skor tablosunu açar. Phaser'da sahneyi otomatik dondurur (pause).
closeLeaderboard() Tüm Motorlar void Açık olan liderlik tablosu modalını kapatır; Phaser sahnesini devam ettirir (resume).
mountBadge(options) Tüm Motorlar void Oyunun köşesine (top-right, top-left vb.) minik tıklanabilir [ Liderlik | Oyuncu] rozeti koyar.
init(options) Tüm Motorlar Promise<Object> Başlangıç el sıkışması: { gameSlug, appId, mountBadge, onReady }.
unlockAchievement(id) Tüm Motorlar void Belirtilen başarımı anında Supabase bulutuna mühürler ve HUD bildirimini tetikler.
getLeaderboard(tier) Tüm Motorlar void Platformdan ham Top 10 sıralama verisini talep eder (felerous:leaderboard_update olayını ateşler).
getFriends() Tüm Motorlar Promise<Array> Oyuncunun onaylı arkadaşlarının sanitize edilmiş profil listesini döner.
getFriendBotNames(options) Tüm Motorlar Promise<string[]> Arkadaş listesindeki isimleri çeker; yetersizse yedek isimlerle doldurup botlara atanmaya hazır dizi döner.
exitToPlayzone() Tüm Motorlar void Oyundan güvenle çıkıp PlayZone ana mağaza vitrinine yönlendirir.
openReviews() Tüm Motorlar void Oyuncunun oyuna puan vermesi ve yorum yazması için PlayZone İnceleme Modalını açar.
player (Özellik) Tüm Motorlar Object Aktif oyuncu kimliği: { name, felerousId, avatar, isGuest }. Asla null dönmez.
attachScene(scene) Phaser 3 Özel this Aktif Phaser sahnesini bağlar. Otomatik scene.pause(), sound.mute ve delta süre sayacını devreye sokar.
applyTint(sprite, color) Phaser 3 Özel void Hex renk kodunu (örn: '#38bdf8') WebGL tint sayısına çevirip Phaser Sprite nesnesine uygular.
Yapay Zekaya (Gemini, Claude, Cursor) Oyun Kodlatırken Kullanılacak Sistem İstemi

Kendi oyununuzu bir yapay zekaya sıfırdan yazdırırken veya var olan bir Canvas/Phaser oyununu PlayZone'a uyarlatırken aşağıdaki tek paragraflık kuralı AI'ya yapıştırmanız yeterlidir:

Bu oyunu FELEROUS PlayZone Arcade SDK v4.3 standardına uyumlu hale getir:
1. HTML'e <script src="https://store.felerous.com/js/felerous-bridge_html5.js"></script> köprüsünü dahil et (Phaser kullanıyorsan felerous-bridge_phaser.js).
2. Oyun bittiğinde skoru tek satırda ilet: felerousBridge.submitScore(score);
3. Oyun sonu ekranında küresel skor tablosunu aç: felerousBridge.showLeaderboard();
4. Oyuncu kimliğini felerousBridge.player.name üzerinden oku. Ekstra CSS veya modal tablosu tasarlama; yerleşik Felerous HUD overlay'ini kullan.

7. İki Yönlü Olay Sözleşmeleri (PostMessage Kataloğu)

Oyun (iFrame) ile ev sahibi PlayZone oynatıcı çerçevesi arasındaki tam çift yönlü olay haberleşme tablosu:

Olay Adı (Type) Yön Açıklama Yük (Payload)
FELEROUS_INIT_PLAYER Oyun Platform Oyun açıldığında kimlik doğrulama, dinamik oturum bileti (session ticket) ve liderlik tablosunu talep eder. { type, game_id, app_id, bridge_token, timestamp }
FELEROUS_PLAYER_INFO Platform Oyun Giriş yapmış kullanıcının profilini, oturum biletini ve doğrulama durumunu oyuna aktarır. { type, player_name, avatar_url, felerous_id, is_guest, user_id, session_ticket, app_id, verified }
FELEROUS_UNLOCK_ACHIEVEMENT Oyun Platform Başarım kazanıldığında anında Supabase user_achievements tablosuna yazar ve PlayZone HUD bildirimini tetikler. { type, game_id, app_id, bridge_token, session_ticket, achievement_id, timestamp }
FELEROUS_ACHIEVEMENT_CONFIRMED Platform Oyun Başarım Supabase bulutuna başarıyla mühürlendiğinde köprüye geri teyit sinyali döner. { type, game_id, achievement_id, synced: true }
FELEROUS_SUBMIT_SCORE Oyun Platform Oyun bittiğinde skoru arcade_scores tablosuna kaydeder, oyuncu kütüphanesine oyunu otomatik ekler ve skor sıralamasını günceller. { type, game_id, app_id, bridge_token, session_ticket, score, level_reached, lines_cleared, difficulty_tier, difficulty_label, duration_seconds, achievements, stats, timestamp }
FELEROUS_GET_LEADERBOARD Oyun Platform İlgili oyunun Top 10 skor tablosunu talep eder. { type, game_id, difficulty_tier }
FELEROUS_LEADERBOARD_UPDATE Platform Oyun Güncel ilk 10 skor sıralamasını dizi formatında oyuna gönderir. { type, game_id, difficulty_tier, leaderboard: [...] }
FELEROUS_SET_MUTE Platform Oyun PlayZone üst HUD ses butonundan gelen ses aç/kapa komutu. { type, muted: true/false }
FELEROUS_PAUSE Platform Oyun PlayZone üst HUD duraklat butonuna basıldığında oyunu durdurur. { type }
FELEROUS_RESUME Platform Oyun PlayZone üst HUD devam butonuna basıldığında oyunu sürdürür. { type }
FELEROUS_EXIT_GAME Oyun Platform Oyuncunun güvenli şekilde PlayZone vitrinine dönmesini sağlar. { type, game_id, redirect_url }
FELEROUS_WORKSHOP_PUBLISH Oyun Platform Oyun içinden doğrudan Atölye'ye yeni bir tasarım, blueprint veya mod yayınlar (DB seviyesinde maks 512KB payload ve saatte 10 adet hız sınırı korumalı). { type, req_id, game_id, payload: { title, category, description, footprint, blueprintData, tags } }
FELEROUS_WORKSHOP_GET_ITEMS Oyun Platform Oyuna ait onaylı Atölye eserlerini, popüler blueprintleri ve modları listeler. { type, req_id, game_id, filters: { category, search, limit, offset, sort } }
FELEROUS_WORKSHOP_SUBSCRIBE Oyun Platform Oyuncunun bir Atölye eserine abone olmasını veya abonelikten çıkmasını sağlar. { type, req_id, item_id, subscribe: true/false }
FELEROUS_WORKSHOP_VOTE Oyun Platform Bir Atölye eserine olumlu veya olumsuz oy verilmesini sağlar (Sayaçlar veritabanı tetikleyicisiyle güvene alınmıştır). { type, req_id, item_id, vote_type: 'up'/'down' }
FELEROUS_GET_FRIENDS Oyun Platform Oyuncunun onaylı arkadaş listesini talep eder (Bot isimleri ve sosyal özellikler için). { type, req_id, game_id }
FELEROUS_FRIENDS_DATA Platform Oyun Güvenlik filtresinden geçmiş arkadaş listesini oyuna iletir (Yalnızca sanitize edilmiş id, name, username, avatar). { type, req_id, friends: [...] }
FELEROUS_AVATAR_GET_MY_SPEC Oyun Platform Oyuncunun profile.html üzerinde tasarladığı 2.5D Küp Avatar (CubeRig v1) spec verisini talep eder. { type, req_id, rig_family: 'cube_v1' }
FELEROUS_AVATAR_MY_SPEC_RESULT Platform Oyun Kullanıcının aktif gardırop ve kıyafet spec JSON verisini döner. { type, req_id, spec: { gender, skinTone, hairStyle, outfit, accessory, ... } }
FELEROUS_AVATAR_GET_NPC_POOL Oyun Platform Canlı oyuncu avatarlarından oluşan dinamik NPC havuzunu talep eder (şehir simülasyonu sakinleri, uzay filosu pilotları, arena rakipleri vb.). { type, req_id, count, category, min_wealth, max_wealth, vip_only }
FELEROUS_AVATAR_NPC_POOL_RESULT Platform Oyun Kategoriye göre filtrelenmiş gerçek oyuncu avatarları dizisini döner. { type, req_id, npcs: [...] }
Kritik Geliştirici İpucu (Siyah Ekran & Yarış Durumu Koruması):
Oyununuz iframe veya hızlı CDN önbelleği üzerinden açıldığında window.addEventListener('DOMContentLoaded', ...) olayı betikleriniz yüklenmeden çoktan tetiklenmiş olabilir. Oyununuzun siyah ekranda kalmaması için başlatıcınızı mutlaka document.readyState kontrollü tasarlayın:
if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', launchGame);
} else {
    launchGame();
}

8. Zorluk Kademeleri & Liderlik Tablosu Entegrasyonu

PlayZone skor tablosunda adil rekabet sağlamak için skorlar zorluk kademelerine (Difficulty Tiers) göre filtrelenir.

ℹ
Standart Kademe Kodları: Oyununuzun türüne göre kademeler belirleyebilirsiniz. Düşen Sicimler örneğinde 4 kademe kullanılmıştır:
  • lvl1 / Acemi: Yavaş düşüş hızı, yeni başlayanlar için.
  • lvl2 / Klasik: Standart arcade dengesi (varsayılan kademe).
  • lvl3 / Usta: Yüksek hız ve daha agresif tempo.
  • lvl4 / Kabus: Zirve refleks gerektiren aşırı hız kademesi.

Skor gönderirken difficulty_tier: 'lvl2' ve difficulty_label: 'Klasik' parametrelerini sağladığınızda PlayZone ve FDB liderlik tablolarında bu sekmeler otomatik ayrışır.

Oyununuzda Zorluk Kademesi Yoksa (Tek Liderlik Tablosu):
Oyununuz tek bir oyun döngüsüne sahipse (örn: sonsuz koşu, flappy tarzı veya tek modlu rekabet); skor gönderirken parametreleri şu şekilde vermeniz yeterlidir: difficulty_tier: 'standard', difficulty_label: 'Genel Sıralama'
PlayZone sistemi gereksiz sekmeler üretmez ve oyununuz için şık, tek bir ana liderlik tablosu açar.
Platform Sınır Değerleri & Kotalar (Limits)

Cloudflare R2 kovanlarında 0 TL egress maliyetiyle ışık hızında sunulabilmesi için aşağıdaki platform limitlerine uyulması rica olunur:

Maksimum ZIP Paketi:
50 MB (Daha büyük projeler için Harici WebSocket / CDN modeli kullanılmalıdır).
Toplam Başarım Puanı:
Oyun başına en fazla 1000 XP (Steam / Konsol endüstri standardı).
Zorluk Kademesi Sınırı:
En fazla 6 aktif kademe sekmesi (lvl1 ... lvl6).
Görsel Optimizasyonu:
Konsol yükleyicisi görselleri otomatik olarak ~150-250 KB WebP'ye indirir.

9. Steam-Tarzı Topluluk Atölyesi (Workshop & UGC) Mimarisi (v4.3.8)

Oyununuzda oyuncuların kendi tasarımlarını (taretler, binalar, fabrikalar, haritalar veya genel blueprintler) oluşturup harici bir geliştirici portalına girmeden doğrudan oyun içinden tek tıkla FELEROUS Atölyesi'ne yüklemelerini ve diğer oyuncuların paylaştığı eserleri oyun içine aktarmalarını sağlayan çift yönlü UGC (User-Generated Content) motoru.

1. Sıfır-İçerik Koruması (Zero-Content Protection):
FELEROUS Store ve Topluluk kuralları gereği, Atölye desteği olan ancak henüz en az 1 onaylı eseri yayınlanmamış oyunların Atölye sekmeleri veya filtre menüleri vitrinde asla boş/anlamsız olarak görünmez. İlk eser yayınlandığında games.workshop_items_count veritabanı tetikleyicisiyle otomatik artar ve Atölye sekmeleri canlıya geçer.
Atölye Veri Güvenliği ve Şişirme Önleme (Anti-Flooding) Standartları
  • Maksimum 512 KB Payload Tavanı: Kanvas blueprintleri PostgreSQL veritabanında CHECK (octet_length(blueprint_data::text) <= 524288) kısıtlamasıyla korunur. Ağır model veya DoS amaçlı şişirilmiş veriler sunucuya giremez.
  • Anti-Spam & Rate-Limiting: Kullanıcı başına 15 saniye cooldown ve saatte maksimum 10 Atölye eseri paylaşma sınırı veritabanı seviyesinde (BEFORE INSERT TRIGGER) kilitlenmiştir.
  • Kimlik Taklidi Engeli: Eserin yazarı (author_id) istemciden manipüle edilemez; Supabase RLS ve veritabanı kontrolüyle zorunlu olarak oturum açan kullanıcının gerçek auth.uid() kimliğine bağlanır.
  • Mühürlü Sayaçlar (Tamper-Proof Counters): upvotes_count ve subscribers_count gibi vitrin sayaçları doğrudan güncellenemez. Yalnızca workshop_votes ve workshop_subscriptions ilişkisel tablolarındaki gerçek eylemler üzerinden otomatik hesaplanır.

JavaScript Entegrasyon Örnekleri (felerousBridge.workshop)

1. Tasarım / Blueprint Yayınlama (Oyun İçinden)
// Oyuncu editörde veya stüdyoda "Atölyede Paylaş" butonuna bastığında:
const result = await felerousBridge.workshop.publish({
  gameSlug: 'void-factory',
  title: 'Ağır Plazma Kulesi Mk-IV',
  category: 'turret',               // 'turret', 'factory', 'defense', 'conveyor', 'blueprint', 'mod', 'map'
  description: 'Gelişmiş soğutma ünitesi ve çift manyetik hızlandırıcıya sahip savunma kulesi.',
  footprint: '2x2',                 // Ayak izi (1x1, 2x2, 3x3 vb.)
  previewImage: canvas.toDataURL('image/png'), // Küçük resim (thumbnail)
  blueprintData: myTurretModelData, // JSON formatında model/çizim verisi (Maks 512KB)
  tags: ['plasma', 'heavy', 'defense', '2x2']
});

if (result.success) {
  alert(' Tasarımınız FELEROUS Topluluk Atölyesi\'nde yayınlandı! Eser ID: ' + result.item_id);
} else {
  alert('Yayınlama hatası: ' + result.error);
}
2. Topluluk Eserlerini Listeleme & Oyuna İçe Aktarma
// Oyun içi Varlık Mağazasında (Roblox Toolbox tarzı) topluluk modellerini getirin:
const res = await felerousBridge.workshop.getItems({
  gameSlug: 'void-factory',
  category: 'turret',               // Opsiyonel filtre
  search: 'plazma',                 // Opsiyonel arama kelimesi
  sort: 'popular',                  // 'popular', 'newest', 'subscribers'
  limit: 20
});

if (res.success && res.items.length > 0) {
  res.items.forEach(item => {
    console.log(`[Atölye] ${item.title} — Yazar: ${item.author_name} —  ${item.upvotes_count}`);
    // Modeli oyuna yüklemek için:
    // myGameEngine.loadBlueprint(item.blueprint_data);
  });
}
3. Beğeni (Oy Verme) ve Abone Olma
// Eseri beğenme (+1 Upvote):
await felerousBridge.workshop.vote(item.id, 'up');

// Esere abone olma (Kullanıcı kütüphanesine kaydetme):
await felerousBridge.workshop.subscribe(item.id, true);
ℹ
Geleceğe Hazır Tauri Masaüstü Mimarisi: Web PWA istemcisinde postMessage köprüsü çalışırken, gelecekte Tauri masaüstü istemcisine geçildiğinde window.__TAURI__.invoke çağrısıyla yerel dosya sistemine bağlanacaktır. Geliştirici kodunda tek bir satır dahi değişiklik gerektirmez!

10. Arkadaş İsimli Botlar & Sosyal Köprü (Social Friends Bridge - v4.2)

Felerous Arcade SDK v4.2 ile geliştiriciler, standart rastgele bot isimlerinin yerine oyuncunun FELEROUS Store'daki gerçek arkadaşlarının kullanıcı adlarını veya platformdaki rastgele gerçek oyuncuların isimlerini oyun içi botlara, düşmanlara veya refakatçilere atayabilir.

Metot Dönüş Tipi Açıklama
felerousBridge.getFriends() Promise<Array> Oyuncunun onaylı arkadaşlarının sanitize edilmiş listesini döner: [{ id, name, username, avatar_url }].
felerousBridge.getFriendBotNames(options) Promise<string[]> Botlar için doğrudan kullanıma hazır isim dizisi döner ({ count: 10, fallbackNames: [...], shuffle: true }).
felerousBridge.getRandomCommunityPlayers(options) Promise<Array> Platformdaki gerçek oyunculardan (veya oyuncunun arkadaşlarından) canlı NPC / rakip havuzu döner.

11. Küp Avatar (CubeRig v1) & Canlı NPC Havuzu Mimarisi (FelerousCubeRig SDK)

Oyuncular Felerous Store profilinde (profile.html) veya Avatar Studio'da kendi 2.5D Küp Avatarlarını tasarlar; bu avatar hem PlayZone arcade dünyalarında canlı bir rakip olarak yerini alır, hem de bağımsız oyunlarda canlı bir müttefik veya şehir sakini olarak taşınır.

Modüler Tasarım: Yalnızca Avatar Kullanan Oyunlar Yükler

Tetris, Tuğla Kırma veya Uzay Savaşları gibi karakter gerektirmeyen oyunların boşuna kod yüklemesini engellemek için Küp Avatar motoru çekirdek köprüden ayrılmıştır. Oyununuzda avatar veya Canlı Drivatar kullanacaksanız felerous-cuberig-sdk.js dosyasını eklemeniz yeterlidir:

<script src="https://store.felerous.com/js/felerous-cuberig-sdk.js"></script>
Metot Dönüş Tipi Açıklama
FelerousCubeRig.getAvatar(felIdOrUser) Promise<Object> Belirtilen FEL-ID (örn: 'FEL-1001'), kullanıcı adı veya aktif oturumdaki oyuncunun CubeRig JSON spec verisini döner.
FelerousCubeRig.getNPCPool(count) Promise<Array> Canlı oyuncu avatarlarından oluşan hazır NPC / Drivatar havuzunu çeker (Varsayılan count = 20).
FelerousCubeRig.getDefaultSpec(gender) Object Varsayılan kadın ('female') veya erkek ('male') CubeRig şablonunu anında üretir.
felerousBridge.avatars.getMyAvatar() Promise<Object> Köprü geriye dönük uyumluluğu: SDK yüklendiğinde köprü üzerinden aktif oyuncu avatarını döner.
Kullanım Örneği: Oyuncu Avatarını ve NPC Havuzunu Çekme
<script>
  // 1. Aktif oyuncunun veya arkadaşının avatarını FEL-ID ile çek:
  const avatar = await FelerousCubeRig.getAvatar(player.felerousId);
  console.log('Avatar Renk Paleti:', avatar.palette);
  console.log('Kıyafet & Aksesuarlar:', avatar.slots);

  // 2. Canlı 10 adet Drivatar NPC'si çek (Arka plan kalabalığı, yarış rakipleri vb.):
  const npcs = await FelerousCubeRig.getNPCPool(10);
  npcs.forEach(npc => {
    console.log(`NPC Adı: ${npc.name}, FEL-ID: ${npc.felerousId}`);
  });
</script>

12. Tauri v2 Masaüstü İstemcisi & Çift Yönlü IPC Köprüsü

FELEROUS Ekosistemi hem modern web tarayıcılarında (PlayZone Web PWA) hem de Tauri v2 tabanlı Masaüstü Başlatıcıda (FELEROUS Launcher) sıfır konfigürasyonla çalışacak çift motorlu mimariye sahiptir. felerous-bridge.js çalışma anında ortamı otomatik tespit eder; tarayıcıdaysa window.postMessage, masaüstündeyse yerel Rust çekirdeğine window.__TAURI__.core.invoke ile doğrudan bağlanır.

13. Mobil & Çapraz Tarayıcı "Altın Kuralları"

Mobil tarayıcılarda (Safari, Samsung Internet, Chrome Mobil) kusursuz deneyim sağlamak için şu 5 altın kural uygulanmalıdır:

1. Dynamic Viewport (100dvh)

Mobil gezinti çubuğu hareket ettiğinde sayfanın taşmasını engeller:

css/style.css
html, body, #game-container {
  height: 100vh;
  height: -webkit-fill-available;
  height: 100dvh;
  overflow: hidden;
  position: fixed;
  width: 100%;
}

2. SafeStorage (Safari Gizli Mod & Iframe Koruması)

Safari Gizli Modunda localStorage çökmelerini engeller:

SafeStorage Koruması
window.SafeStorage = {
  _mem: {},
  getItem(k) {
    try { return localStorage.getItem(k); }
    catch (e) { return this._mem[k] || null; }
  },
  setItem(k, v) {
    try { localStorage.setItem(k, v); }
    catch (e) { this._mem[k] = String(v); }
  }
};

3. Web Audio API Otomatik Oynatma Uyandırıcısı (unlockAudio)

Kullanıcının ilk dokunuşunda ses motorunu uyandırır:

unlockAudio Snippet
function unlockAudio() {
  if (window.audioCtx && window.audioCtx.state === 'suspended') {
    window.audioCtx.resume();
  }
  document.removeEventListener('pointerdown', unlockAudio);
}
document.addEventListener('pointerdown', unlockAudio, { passive: true });

4. Samsung Internet Renk Bozulması Koruması

Gece modunda canvas renklerinin tersine çevrilmesini engeller:

Zorunlu Gece Modu Koruması
:root { color-scheme: dark; }
canvas { color-scheme: dark; forced-color-adjust: none; touch-action: none; }

5. Dokunmatik Jestler ve Eksen Kilidi (Axis Lock)

Düşen Sicimler v1.0.2 ile geliştirilen sezgisel doğrudan Canvas jest kontrol modeli:

Hassas Eksen Kilidi Mantığı
// Yatay sürüklemede kazara düşüşleri engelleyen eksen kilidi
let touchStartX = 0, touchStartY = 0, isDragging = false;

canvas.addEventListener('touchstart', (e) => {
  const t = e.touches[0];
  touchStartX = t.clientX;
  touchStartY = t.clientY;
  isDragging = true;
}, { passive: true });

canvas.addEventListener('touchmove', (e) => {
  if (!isDragging) return;
  const dx = e.touches[0].clientX - touchStartX;
  const dy = e.touches[0].clientY - touchStartY;

  // Eksen kilidi: Yatay hareket dikey hareketten fazlaysa sola/sağa kaydır
  if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 28) {
    if (dx > 0) game.moveRight(); else game.moveLeft();
    touchStartX = e.touches[0].clientX;
  }
}, { passive: true });

canvas.addEventListener('touchend', (e) => {
  isDragging = false;
});

14. Dağıtım Modelleri: Felerous R2 Bulut vs Harici Sunucu

Felerous PlayZone ekosisteminde oyununuzu iki farklı mimariyle milyonlarca oyuncuya ulaştırabilirsiniz:

Model A: Felerous R2 Bulut Barındırma

Oyununuzun tüm dosyaları (HTML, JS, CSS, ses ve görseller) tek bir ZIP arşivi olarak sunulur. Felerous Güvenlik Masası'nın onayının ardından oyun arcade.felerous.com/[oyun-slug]/index.html adresiyle küresel Cloudflare Edge CDN üzerinden sıfır sunucu maliyetiyle yayınlanır.

Tek kişilik oyunlar ve statik WebGL projeleri için tavsiye edilir.
Model B: Harici Geliştirici Sunucusu (Self-Hosted)

Oyununuzu kendi bulut altyapınızda (Cloudflare Pages, Vercel, Render, Node.js VPS, AWS veya özel alan adınızda) barındırırsınız. PlayZone oyununuzu güvenli bir sandbox iframe içerisinde vitrine bağlar.

Canlı çok oyunculu (NeonVolt vb.), dinamik backendli oyunlar için zorunludur.

Harici Sunucuda Barındırma İçin 3 Demir Güvenlik Kuralı:

1. HTTPS / SSL Zorunluluğu: Felerous Store güvenli HTTPS protokolü üzerinden çalıştığı için tarayıcılar HTTP üzerindeki karma içerikleri (Mixed Content) tamamen engeller. Oyun web adresiniz ve varsa WebSocket bağlantılarınız mutlaka https:// ve wss:// olmalıdır.
2. CSP ve iFrame İzinleri (Frame Ancestors): Sunucunuzun HTTP yanıt başlıklarında Felerous PlayZone'un oyunu gömebilmesi için izin verilmelidir:
Content-Security-Policy: frame-ancestors 'self' https://store.felerous.com https://*.felerous.com;
3. SDK Köprüsü Uyumu (felerous-bridge.js): Oyununuz harici bir sitede çalışsa bile HTML dosyanızda felerous-bridge.js bulunmalıdır. Oyun skorları, oturum kimliği ve başarımlar tarayıcı postMessage API'si üzerinden ana PlayZone arayüzüne iletilir.

15. Felerous Canlı Telemetri Protokolü (v1.0)

Çok oyunculu veya yaşayan dünyalara sahip web oyunlarında sunucu sağlığını, canlı oyuncu sayısını ve Drivatar bot aktivitelerini FELEROUS Store ve FDB vitrinine gerçek zamanlı aktarma standardıdır.

Standart REST Telemetri Endpoint'i (HTTP GET):

Çok oyunculu oyun sunucunuzda (örn: https://neon-volt.onrender.com/stats veya https://api.studio.com/stats) aşağıdaki JSON şemasını dönen hafif bir HTTP GET uç noktası tanımlamalısınız:

JSON — GET /stats veya /telemetry
{
  "protocol": "felerous-telemetry-v1",
  "status": "online",
  "service": "neon-volt-multiplayer",
  "timestamp": 1727701800000,
  "uptime": 14200,
  "performance": {
    "tps": 30.0,
    "tickIntervalMs": 33.33,
    "memoryMB": 42
  },
  "players": {
    "online": 3,
    "max": 30,
    "humans": 3,
    "bots": 10,
    "list": [
      { "id": "p_1", "name": "Vortex", "score": 2400, "isVerified": true }
    ]
  },
  "bots": {
    "count": 10,
    "archetypes": [
      { "name": "SiberCellat", "title": "Psikopat Avcı (Bwoniknife)", "score": 1420 }
    ]
  },
  "arena": {
    "radius": 2900,
    "foodCount": 650
  },
  "leaderboard": [
    { "rank": 1, "name": "SiberCellat", "score": 1420, "isPlayer": false },
    { "rank": 2, "name": "Vortex", "score": 2400, "isPlayer": true }
  ]
}

Zorunlu Sunucu HTTP Başlıkları (CORS):

Store vitrini ve FDB'nin tarayıcı seviyesinde canlı verileri sorgulayabilmesi için sunucu yanıtınızda şu başlıklar bulunmalıdır:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, OPTIONS
Cache-Control: no-cache, no-store, must-revalidate
Geliştirici Portalında Test Etme: Geliştirici Portalında oyununuzu yayınlarken veya güncellerken "Bu oyun canlı çok oyunculu sunucu ve telemetri destekliyor" kutucuğunu işaretleyip Telemetri URL'nizi girdiğinizde "Bağlantıyı Test Et" butonuna basarak sunucunuzun hazır olup olmadığını tek tıkla doğrulayabilirsiniz.

16. İnceleme Süreci, Dağıtım & Geliştirici Portalı

Oyununuzu milyonlarca oyuncuya güvenli ve yüksek performansla sunmak için FELEROUS Güvenlik Masası, Cloudflare R2 ve Geliştirici Portalı entegrasyonu:

Güvenlik & Kalite Standardı: Platform güvenliği, sandbox izolasyonu ve üst düzey kullanıcı deneyimi için her yeni oyun FELEROUS ekibinin manuel güvenlik & SDK testinden geçer. R2 bulut dağıtımı seçilen oyunlar onaylandıktan sonra ekibimiz tarafından arcade.felerous.com kovanına konuşlandırılır.
Canlı CDN Mimarisi: R2 barındırmalı oyunlar doğrudan felerous-games Cloudflare R2 kovanında ve https://arcade.felerous.com/[oyun-slug]/index.html özel alan adında barındırılır. SSL, küresel CDN önbellekleme ve sandbox iframe güvenliği otomatik olarak devrededir.

Yayınlama & İnceleme Adımları:

  1. Oyun dosyalarınızı standart klasör hiyerarşisinde (index.html, manifest.json, achievements.json, changelog.json, cover.png, banner.png, icon.png, js/, css/) hazırlayın ve bir ZIP arşivi haline getirin (veya harici barındırma kullanıyorsanız canlı web adresinizi hazırlayın).
  2. Geliştirici Portalı'na (/developer) gidin ve "Web Oyunları (PlayZone Arcade)" sekmesini açın.
  3. Oyun Başlığı, Motoru, Türü, Açıklaması, Dağıtım Türü (R2 veya Harici URL) ve çok oyunculu ise Telemetri bağlantısını girip "Web Oyununu İncelemeye Gönder" butonuna basın.
  4. FELEROUS Yönetim Masası paketi veya canlı bağlantıyı inceleyip güvenlik, 100dvh mobil düzeni, SafeStorage ve SDK köprüsünü test eder.
  5. Onaylanan oyun PlayZone vitrininde ve mağazada yayına girer.
  6. Oyun onaylandıktan sonra geliştirici; başlık, açıklama, kontroller ve yeni güncelleme paketleri sunma konusunda daha geniş ve özgür yönetim paneline sahip olur.
Kritik Güvenlik Kuralı — Oyun Bağlantısı & Dosya Değişiklikleri: Onaylanmış ve mağazada yayında olan bir oyunun Oyun Bağlantısı (game_url), İndirme Adresi (download_url), Yetkili Kökenleri (allowed_origins), Kapak / Banner Görselleri veya Başlığı konsoldan değiştirilirse; kötü niyetli yönlendirmeleri ve sahte içerikleri engellemek amacıyla güvenlik katmanı oyunu otomatik olarak yayından düşürür (is_published = false) ve durumunu tekrar inceleme bekliyor (pending) moduna alır. Değişiklikler FELEROUS ekibi tarafından onaylandıktan sonra oyun otomatik olarak mağazada tekrar yayına girer.
Kütüphaneye Otomatik Eklenme (Auto-Claim): Oyun yayınlandığı andan itibaren, herhangi bir kayıtlı oyuncu oyunu ilk açtığında veya ilk skorunu kaydettiğinde, sistem arka planda oyunu oyuncunun kütüphanesine (purchases tablosuna payment_method: 'arcade_play' olarak) ekler ve oyuncunun profilindeki "Sahip Olunan Oyun" sayacını artırır.

17. İçerik Politikası, Telif & %100 Ücretsiz Kutsal İlke

FELEROUS ekosisteminin değişmez yayın ilkeleri ve topluluk standartları:

FELEROUS DEĞİŞMEZ KUTSAL İLKESİ: %100 ÜCRETSİZ OYUN SAĞLAYICISI OLMAK

FELEROUS'un ana misyonu oyuncular için sıfır maliyetli, engelsiz ve saf bir ücretsiz oyun dağıtım platformu olmaktır. Cloudflare Pages + Cloudflare R2 (Sıfır çıkış / egress ücreti) + Supabase Serverless altyapımız sayesinde oyun dağıtımı için sunucu maliyetimiz 0 TL kalır. Oyunlar oyunculara hiçbir zaman gizli ödeme duvarı (paywall) veya kazanmak için öde (P2W) dayatması sunamaz.

Varlık & Telif Hakkı Sorumluluğu
Oyununuzda yer alan tüm müzik, ses efektleri, grafikler ve kod parçacıkları geliştiricinin sorumluluğundadır. İzinsiz telifli eserler (Nintendo, Disney vb. tescilli markalar) tespit edildiğinde oyun derhal karantinaya alınır.
PEGI Yaş Derecelendirmesi
Oyununuz PEGI 3, 7, 12, 16 veya 18 derecelerinden birine uygun olmalıdır. Aşırı şiddet, kumar, kötü amaçlı yazılım (kripto madenciliği) veya nefret söylemi içeren projeler doğrudan reddedilir.

18. Sıkça Sorulan Sorular & Sorun Giderme (Troubleshooting)

Geliştiricilerin entegrasyon sırasında en sık karşılaştığı durumlar ve pratik çözümleri:

S1: Yerel testte veya oyunu ilk açtığımda müzikler / sesler neden çalmıyor?
Cevap (Web Audio Autoplay Kuralı): Modern tarayıcılar (Chrome, Safari, Firefox), kullanıcı sayfayla etkileşime girmeden (tıklama, ekrana dokunma veya klavye tuşuna basma) önce ses çalınmasını engeller. Starter şablonumuzdaki sound.js motoru, oyuncunun ilk tuş veya dokunuşunda AudioContext.resume() çağırarak kilidi otomatik açacak şekilde tasarlanmıştır.
S2: submitScore() çağırıyorum ancak skorum liderlik tablosuna düşmüyor, neden?
Cevap: İki temel sebebi olabilir:
1) felerousBridge.init() içinde verdiğiniz appId ve bridgeToken, Geliştirici Konsolundaki oyununuzun anahtarlarıyla birebir uyuşmalıdır.
2) Maksimum Hız Kalkanı (Velocity Check): Oyun süreniz çok kısaysa ve imkansız bir hızda milyonlarca puan gönderilmişse güvenlik katmanı skoru şüpheli olarak işaretler.
S3: R2'ye yüklediğim oyun PlayZone vitrininde açıldığında siyah ekran kalıyor?
Cevap:
1) Oyun ana dosyanız mutlaka küçük harfle index.html olarak adlandırılmalıdır.
2) Tüm script, stil ve görsel yolları göreceli (relative) olmalıdır: /js/game.js yerine js/game.js veya ./js/game.js kullanılmalıdır.
S4: Yeni bir yama (v1.0.4) çıkardığımda ne yapmalıyım? Yeniden inceleme gerekir mi?
Cevap: Onaylı oyunlar için geliştirdiğimiz hızlı yama hattı sayesinde, konsoldaki oyun sayfanızdan yeni ZIP paketini yükleyebilirsiniz veya R2'deki manifest.json dosyasını güncelledikten sonra konsoldan " R2'den Eşitle" butonuna basabilirsiniz. Küçük hata düzeltmeleri otomatik olarak devreye girer.
S5: Köprü SDK'sı oyunumu PlayZone dışında (yerel sunucumda veya localhost'ta) açtığımda hata verir mi?
Cevap: Hayır! SDK v4.2 ile birlikte tam Yerel Simülasyon Modu (Local Dev Simulation) devreye alınmıştır. Oyun iframe dışında çalıştığında köprü bunu otomatik algılar; tarayıcı konsoluna renkli bir teşhis kartı basar, sanal bir test profili (DEV-TEST-001) tahsis eder ve onReady callback'ini otomatik tetikler. submitScore() ve unlockAchievement() çağrılarınız da konsolda ayrıntılı bir yük analiziyle simüle edilir. Böylece oyunu PlayZone'a yüklemeden önce %100 yerel ortamda test edebilirsiniz.
S6: İstemci koduna gizli token gömmem gerekir mi? Anahtarlar nerede saklanır?
Cevap: Hayır, SDK v4.3.8 ile birlikte istemci (tarayıcı) kodunda hiçbir gizli token (bridgeToken) bulundurulmaz; yalnızca herkese açık gameSlug ve appId kullanılır. Skor doğrulaması tek kullanımlık sunucu oturum bileti (session_ticket) ve hız limiti (velocity check) üzerinden yürütülür. Sunucu/webhook anahtarları ise umumi games tablosunda değil, yalnızca oyunun geliştiricisinin erişebildiği (RLS korumalı) game_secrets tablosunda saklanır.
S7: Oyunuma Steam-tarzı Atölye (Workshop & UGC) sistemini nasıl entegre edebilirim?
Cevap: SDK v4.0 ile birlikte gelen felerousBridge.workshop modülü sayesinde oyuncular harici bir portala ihtiyaç duymadan doğrudan oyun içinden felerousBridge.workshop.publish() ile tasarımlarını (taret, fabrika, harita veya blueprint) paylaşabilir. Diğer oyuncuların paylaştığı onaylı eserleri ise felerousBridge.workshop.getItems() metoduyla listeleyip doğrudan oyun motorunuza aktarabilirsiniz. Sıfır-İçerik Koruması gereği oyununuzda henüz en az 1 onaylı Atölye eseri yayınlanmadan mağazada Atölye vitrini oyunculara görünmez.

19. İnteraktif JSON Doğrulayıcı

Oyununuzu R2'ye yüklemeden önce manifest.json, achievements.json veya changelog.json dosyanızı buraya yapıştırıp şema geçerliliğini anında test edebilirsiniz:

manifest.json şeması kontrol edilecek.