İstek Listesi
🚀 FELEROUS PLAYZONE ECOSYSTEM

Felerous Arcade SDK v4.3.8 Rehberi

HTML5 Canvas, Phaser 3 ve WebGL oyunlarınızı PlayZone platformuna 2 satırda bağlayarak oyunculara sıfır indirmeyle ulaştırın. Çift motorlu köprü mimarisi, gerçek zamanlı skor telemetrisi, 18 kademeli profil başarımları, Modüler CubeRig 2.5D Avatarlar, Arkadaş İsimli Botlar ve Steam-tarzı Topluluk Atölyesi (Workshop UGC).

⚡ 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
    bridgeToken: 'fel_sec_ORNEK_UYGULAMA_ANAHTARI',    // Konsoldan alınan oyun kanal anahtarınız
    mountBadge: true,                                  // Köşeye canlı [🏆 Liderlik | 👤 Oyuncu] rozeti ekler
    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 (Tek sayı veya detaylı obje kabul eder):
  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 birebir aynı sözleşmeyle desteklenir:

Metot / Özellik Motor Dönüş Tipi Açıklama & Kullanım Örneği
init(options) Tüm Motorlar Promise<Player> Başlangıç el sıkışması: { gameSlug, appId, mountBadge, onReady }.
submitScore(input, tier) Tüm Motorlar ScorePayload Polimorfik Tak-Çalıştır: Tek sayı (submitScore(14500, 'lvl2')) veya detaylı obje (submitScore({ score: 14500, difficultyTier: 'lvl2', durationSeconds: 95 })) kabul eder.
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 HTMLElement Oyunun köşesine (top-right, top-left vb.) minik tıklanabilir [🏆 Liderlik | 👤 Oyuncu] rozeti koyar.
unlockAchievement(id) Tüm Motorlar void Belirtilen başarımı anında Supabase bulutuna mühürler ve HUD bildirimini tetikler.
requestLeaderboard(tier) / getLeaderboard(tier) Tüm Motorlar void Platformdan ham Top 10 sıralama verisini talep eder (felerous:leaderboard_update olayını ateşler).
saveCloudData(slot, data) / loadCloudData(slot) Tüm Motorlar Promise<any> Oyuncunun ilerlemesini buluta ve yerel önbelleğe kaydeder / geri yükler.
getFriends() / getFriendBotNames(opts) / getFriendsOrBots(count) Tüm Motorlar Promise<Array> Oyuncunun onaylı arkadaşlarını veya botlara atanmaya hazır isim/profil listesini döner.
workshop.publish(data) / getItems(filters) / subscribe(id) / vote(id, dir) Tüm Motorlar Promise<Object> Steam-tarzı Topluluk Atölyesi (UGC): oyun içinden harita, taret veya blueprint paylaşma ve indirme.
openReviews() / exitToPlayzone() Tüm Motorlar void Oyun içi İnceleme Modalını açar veya güvenli şekilde PlayZone vitrinine çıkış yapar.
player (Özellik) Tüm Motorlar FelerousPlayer Aktif oyuncu kimliği: Kanonik (name, felerousId, avatar, isGuest, userId) ve alias (username, displayName, felId, avatarUrl, id). Asla null dönmez.
attachScene(scene) / attachGame(game) / bindPhaserGame(game) Phaser 3 Özel this Aktif Phaser sahnesini veya Game örneğini bağlar. Otomatik scene.pause(), sound.mute ve delta süre sayacını devreye sokar.
applyTint(sprite, color) / hexToInt(hex) Phaser 3 Özel void / number Hex renk kodunu (örn: '#38bdf8') WebGL 0xRRGGBB 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 3 kullanıyorsan felerous-bridge_phaser.js ve create() içinde felerousBridge.attachScene(this) çağır).
2. Oyun başlangıcında felerousBridge.init({ gameSlug: 'oyun-slug', onReady: (player) => console.log(player.name, player.felerousId) }) ile oturumu başlat.
3. Oyun bittiğinde skoru ilet: felerousBridge.submitScore(score, 'lvl1'); ve küresel skor tablosunu aç: felerousBridge.showLeaderboard();
4. Oyuncu kimliğini felerousBridge.player.name (veya player.username) ü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.

🛠️ 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: 'neonvolt',
  title: 'Özel Arena Parkuru Mk-IV',
  category: 'map',                  // 'map', 'skin', 'blueprint', 'mod'
  description: 'Gelişmiş neon engeller ve çift hızlı hızlandırma hatlarına sahip arena haritası.',
  footprint: '2x2',                 // Ayak izi (1x1, 2x2, 3x3 vb.)
  previewImage: canvas.toDataURL('image/png'), // Küçük resim (thumbnail)
  blueprintData: myMapModelData,    // JSON formatında model/çizim verisi (Maks 512KB)
  tags: ['neon', 'arena', 'speed', 'custom']
});

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: 'neonvolt',
  category: 'map',                  // Opsiyonel filtre
  search: 'neon',                   // 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)

Oyunlarda en eğlenceli dinamiklerden biri yapay zeka botlarının ve NPC'lerin isimleridir. Felerous Arcade SDK v4.2 ile geliştiriciler, standart rastgele bot isimlerinin yerine (örn: AlphaBot, BetaBot) oyuncunun FELEROUS Store'daki gerçek arkadaşlarının kullanıcı adlarını oyun içi botlara, düşmanlara veya refakatçilere atayabilir.

🎉 Oyun Deneyimini Kişiselleştirin
v4.2 Yeniliği

Oyun geliştirici isterse bu sistemi oyun kodlarına entegre edip bir "🤖 Arkadaş İsimli Botlar (Açık/Kapalı)" anahtarına bağlar. Oyuncu dilediğinde bu seçeneği açarak, düşman kulelerini veya düşen kristalleri arkadaşlarının adıyla görebilir ("Ahmet_TR seni vurdu!" veya "Subushaki kristali toplandı!").

✓ Sıfır Veri Sızıntısı (Zero Leakage) • ✓ Çevrimdışı / Misafir Fallback Havuzu • ✓ Yerel Geliştirici Simülasyonu • ✓ Unity & Godot & JS Uyumlu
🔒 Gizlilik İzolasyonu & Sıfır Sızıntı (Zero-Leakage Architecture)
  • Hassas Veri İzolasyonu: Oyun iframe'ine oyuncunun e-posta adresi, şifresi, oturum tokeni veya özel profil ayarları ASLA aktarılmaz. PlayZone köprüsü yalnızca kamuya açık { id, name, username, avatar_url } alanlarını filtreleyerek sunar.
  • Yedek İsim Havuzu (Fallback Pool): Oyuncu misafir oturumundaysa, çevrimdışıysa veya oyunun ihtiyaç duyduğu bot sayısından daha az arkadaşı varsa (örneğin 3 arkadaşı var ama oyunda 10 bot var), getFriendBotNames() eksik kalanları geliştiricinin tanımladığı fallbackNames havuzundan otomatik tamamlar. Oyun asla hata vermez veya takılmaz.
  • Yerel Simülasyon Desteği: Geliştirici kendi bilgisayarında (localhost, file://) oyunu test ederken PlayZone iframe'i dışında bile olsa SDK otomatik mock arkadaş listesi üreterek geliştirme akışını kesintisiz sürdürür.

Metot Referansı

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. options: { count: 10, fallbackNames: [...], shuffle: true }. Arkadaş isimlerini fallback havuzuyla güvenle harmanlar.
felerousBridge.onFriends(callback) void Arkadaş listesi platformdan geldiğinde tetiklenen reaktif olay dinleyicisidir.
felerousBridge.social.getBotNamePool(opts) Promise<string[]> Sosyal modül altındaki kısayol metodudur (window.FelerousSocialBridge).

1. JavaScript & HTML5 Canvas Uygulaması

Aşağıdaki örnek, oyun içi bir Toggle Switch ile oyuncunun bu özelliği açıp kapatabilmesini, ayarın SafeStorage'da saklanmasını ve bot doğuşunda (spawn) arkadaş isimlerinin Canvas üzerine çizilmesini gösterir:

JavaScript (Oyun Motoru & Canvas Çizimi)
class MyGame {
  constructor() {
    this.useFriendBots = SafeStorage.getItem('friend_bots_enabled') !== 'false';
    this.botNames = [];
    this.bots = [];
    
    this.setupFriendBotToggle();
    this.loadBotNames();
  }

  // 1. Ayarı ve Butonu Bağla
  setupFriendBotToggle() {
    const toggle = document.getElementById('toggle-friend-bots');
    if (toggle) {
      toggle.checked = this.useFriendBots;
      toggle.addEventListener('change', (e) => {
        this.useFriendBots = e.target.checked;
        SafeStorage.setItem('friend_bots_enabled', this.useFriendBots ? 'true' : 'false');
        this.loadBotNames(); // İsim havuzunu yenile
      });
    }
  }

  // 2. Felerous SDK ile İsim Havuzunu Yükle
  async loadBotNames() {
    if (!this.useFriendBots) {
      // Özellik kapalıysa varsayılan bot isimlerini kullan
      this.botNames = ['AlphaBot', 'BetaBot', 'OmegaBot', 'Titan', 'Ghost'];
      return;
    }

    try {
      this.botNames = await felerousBridge.getFriendBotNames({
        count: 15,
        fallbackNames: ['AlphaBot', 'BetaBot', 'OmegaBot', 'Spectre', 'Viper', 'Ghost'],
        shuffle: true
      });
      console.log('🤖 Bot isimleri hazırlandı:', this.botNames);
    } catch (err) {
      this.botNames = ['AlphaBot', 'BetaBot', 'OmegaBot'];
    }
  }

  // 3. Bot Doğarken İsim Ata
  spawnBot() {
    const randomName = this.botNames[Math.floor(Math.random() * this.botNames.length)] || 'Bot';
    this.bots.push({
      x: Math.random() * canvas.width,
      y: 0,
      name: randomName,
      speed: 3
    });
  }

  // 4. Canvas Üzerinde Botu ve İsmini Çiz
  render(ctx) {
    for (const bot of this.bots) {
      // Bot gövdesi
      ctx.fillStyle = '#ef4444';
      ctx.fillRect(bot.x - 15, bot.y - 15, 30, 30);

      // Botun üstüne arkadaş ismini yaz
      ctx.font = '11px -apple-system, sans-serif';
      ctx.fillStyle = '#bae6fd';
      ctx.textAlign = 'center';
      ctx.fillText(bot.name, bot.x, bot.y - 20);
    }
  }
}

2. Godot Engine (GDScript Web Export)

Godot 4 WebGL export projelerinde JavaScriptBridge sınıfı üzerinden arkadaş listesini çekip bot düğümlerinize (Label3D veya Label) atayabilirsiniz:

GDScript (Godot 4)
extends Node

var friend_bot_names: Array = []
var _js_callback: JavaScriptObject

func _ready():
    if OS.has_feature("web"):
        _js_callback = JavaScriptBridge.create_callback(_on_friends_received)
        # HTML5 katmanındaki felerousBridge'e çağrı yap
        JavaScriptBridge.eval("""
            if (window.felerousBridge) {
                window.felerousBridge.getFriendBotNames({ count: 10, fallbackNames: ['CyberBot', 'DroidX', 'Titan'] })
                    .then(names => window._godotFriendsCallback(JSON.stringify(names)));
            }
        """)
        var window = JavaScriptBridge.get_interface("window")
        window._godotFriendsCallback = _js_callback

func _on_friends_received(args):
    if args.size() > 0:
        var json_str = args[0]
        var parsed = JSON.parse_string(json_str)
        if typeof(parsed) == TYPE_ARRAY:
            friend_bot_names = parsed
            print("Godot: Arkadaş Bot İsimleri Yüklendi: ", friend_bot_names)

func spawn_bot():
    var bot_instance = preload("res://Bot.tscn").instantiate()
    if friend_bot_names.size() > 0:
        bot_instance.bot_name = friend_bot_names.pick_random()
    add_child(bot_instance)

3. Unity WebGL (C# & .jslib)

Unity WebGL projelerinde Assets/Plugins/WebGL/FelerousBridge.jslib köprü eklentisi kullanarak isimleri C# koduna aktarabilirsiniz:

Assets/Plugins/WebGL/FelerousBridge.jslib
mergeInto(LibraryManager.library, {
    FetchFriendBotNames: function (gameObjectNamePtr, callbackMethodNamePtr) {
        var objName = UTF8ToString(gameObjectNamePtr);
        var methodName = UTF8ToString(callbackMethodNamePtr);
        
        if (window.felerousBridge) {
            window.felerousBridge.getFriendBotNames({ count: 10 })
                .then(function(names) {
                    SendMessage(objName, methodName, JSON.stringify(names));
                });
        }
    }
});
C# (Unity GameManager.cs)
using System.Runtime.InteropServices;
using UnityEngine;

public class GameManager : MonoBehaviour
{
    [DllImport("__Internal")]
    private static extern void FetchFriendBotNames(string gameObjectName, string callbackMethodName);

    public string[] friendBotNames;

    void Start()
    {
#if UNITY_WEBGL && !UNITY_EDITOR
        FetchFriendBotNames(gameObject.name, "OnFriendNamesReceived");
#else
        friendBotNames = new string[] { "AlphaBot", "BetaBot", "OmegaBot" };
#endif
    }

    public void OnFriendNamesReceived(string jsonArray)
    {
        friendBotNames = JsonUtility.FromJson<string[]>(jsonArray);
        Debug.Log("Unity: Arkadaş bot isimleri yüklendi!");
    }
}
💡
Oyun Tasarımı İpucu (Takım Bazlı Botlar):
Çok oyunculu veya takım tabanlı oyunlarda (örn. Mavi Takım vs Kırmızı Takım), oyuncunun gerçek arkadaşlarının isimlerini kendi takımındaki yapay zeka müttefiklerine verirseniz ("Ahmet_TR seni koruyor!"), oyuncunun arkadaşlarıyla birlikte oynuyormuş gibi hissetmesini sağlayabilir ve oturum süresini katlayabilirsiniz!

🎭 11. Küp Avatar (CubeRig v1) & Canlı NPC Havuzu Mimarisi (v4.3.8)

FELEROUS ekosisteminin devrimsel "Tek Kimlik, Sınırsız Temsil" mimarisi: Oyuncular Felerous Store profilinde (profile.html) kendi 2.5D Küp Avatarlarını tasarlar; bu avatar hem PlayZone arcade dünyalarında canlı bir rakip veya liderlik yarışçısı olarak yerini alır, hem de ekosistemdeki bağımsız oyunlarda canlı bir müttefik, komutan veya şehir sakini olarak taşınır.

CubeRig v1 & Canlı NPC Ekosistem Özellikleri
  • Omuz Perspektifli Z-Order Katmanlaması: Karakterler sağa baktığında sağ kol gövde arkasına düşer ve sol kol öne gelir (sola baktığında tam tersi). 2.5D derinlik hissi kağıt bebek hissini ortadan kaldırır.
  • 14 Katmanlı Z-Index Hiyerarşisi: Gölge, bacaklar, gövde, kafa, yüz hatları (kadın/erkek, allık, kirpik), saç ve şapkalar, sokak modası kıyafetleri (hoodie, takım elbise, crop-top), aksesuarlar ve çantalar.
  • Kültürel & Başarım Prestij Yuvaları: Klasik Pala Bıyık, Nazar Boncuğu, Ay-Yıldızlı Milli Forma, Nostaljik Kasket ile 5 ve 15 başarım açanlara özel Altın Vizör, Zümrüt Taç ve Amiral Zırhı.
  • Canlı Oyuncu NPC Havuzu (RPC): getNPCPool() çağrısıyla sistemdeki gerçek oyuncuların profilleri AVM müşterisi, uzay pilotu veya uzaylı tüccar olarak oyununuza akar ($W = 120 + 65 \cdot \ln(1 + H) + 8 \cdot \sqrt{A}$ logaritmik bütçe formülüyle).
🧩 Modüler CubeRig SDK: Yalnızca Avatar Kullanan Oyunlar Yükler

Standart arcade oyunlarının yükleme süresini ve boyutunu minimumda tutmak için Küp Avatar motoru çekirdek köprüden bağımsız hale getirilmiştir. Oyununuza CubeRig karakterlerini dahil etmek için betiği eklemeniz yeterlidir:

<script src="https://store.felerous.com/js/felerous-cuberig-sdk.js"></script>

felerousBridge.avatars Metot Referansı

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: 20).
felerousBridge.avatars.getMyAvatar(rigFamily) Promise<Object> Oyuncunun profile.html'de tasarladığı aktif CubeRig spec JSON verisini döner (Varsayılan: 'cube_v1').
felerousBridge.avatars.saveMyAvatar(spec, photoDataUrl) Promise<Object> Yeni avatar spec'ini ve isteğe bağlı $256 \times 256$ avatar profil görselini Supabase'e kaydeder.
felerousBridge.avatars.getNPCPool(options) Promise<Array> Canlı oyuncu avatarlarından oluşan NPC havuzunu çeker.
options: { count: 15, category: 'fashion', minWealth: 100, maxWealth: 3000, vipOnly: false }

Kullanım Örneği: Avatar Çizimi & NPC Havuzu

JavaScript (Canvas 2.5D Entegrasyonu)
// 1. Köprüyü ve Avatar Çiziciyi Başlatın
const bridge = window.felerousBridge;
const renderer = new FelerousAvatarRenderer({ pixelScale: 2 });

// 2. Oyuncunun Kendi Avatarını Alıp Çizdirin
const mySpec = await bridge.avatars.getMyAvatar('cube_v1');
renderer.render(ctx, mySpec, 200, 300, {
  facing: 'right',             // 'left' veya 'right' (Omuz Z-Order katmanlaması otomatik)
  isWalking: true,             // Yürüyüş mafsal salınımı
  walkCycleTime: performance.now(),
  holdsBag: true,              // Elinde AVM alışveriş poşeti
  bagColor: '#e74c3c'
});

// 3. Canlı Oyuncu NPC Havuzunu Çekip Oyuna Doldurun
const npcs = await bridge.avatars.getNPCPool({ count: 10, category: 'fashion' });
npcs.forEach((npc, index) => {
  console.log(`[NPC Doğdu] ${npc.player_name} — Bütçe: ₺${npc.simulated_budget} — VIP: ${npc.is_vip}`);
  // NPC avatar verisini sahneye ekleyin:
  // spawnCustomer(npc.avatar_spec, npc.player_name, npc.simulated_budget);
});

🦀 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.

⚡
Geliştirici Dostu Şeffaflık (Transparent IPC): Oyun kodunuzda hiçbir if (isDesktop) ayrımı yapmanıza gerek yoktur. felerous-bridge.js çalışma anında ortamı otomatik tespit eder. Tarayıcıdaysa güvenli window.postMessage, masaüstü istemcisindeyse yerel Rust çekirdeğine window.__TAURI__.core.invoke ile doğrudan bağlanır.
Protokol Ortam Mekanizma Gecikme
Web PlayZone Chrome, Edge, Safari, Firefox iFrame ➔ window.postMessage / window.onmessage < 2ms
Tauri v2 Desktop Windows (.exe), Linux, macOS Rust Core ➔ invoke('felerous_bridge_dispatch') & listen('felerous_platform_message') < 0.1ms (Sıfır IPC Darboğazı)

💬 12.1 Oyuncu İncelemeleri & Topluluk Oylaması (PlayZone Reviews HUD — v4.2)

PlayZone oyunları, oyuncuların oyun deneyimini anında oylayabilmesi (👍 Tavsiye Ediyorum / 👎 Tavsiye Etmiyorum) ve klasik inceleme metinleri yazabilmesi için yerleşik bir Oyuncu İncelemeleri Motoru barındırır.

⭐ Steam Modeli Topluluk Skoru Nasıl Çalışır?

Oyuncuların verdiği oylar doğrudan Supabase public.reviews tablosuna işlenir ve public.game_review_summary görünümü üzerinden anlık hesaplanır:

  • Ezici Çoğunlukla Olumlu: En az 5 inceleme ve %95+ olumlu tavsiye oranı.
  • Çok Olumlu: %80 - %94 arası olumlu tavsiye oranı.
  • Çoğunlukla Olumlu: %70 - %79 arası olumlu tavsiye oranı.
  • Karışık: %40 - %69 arası denge durumu.
  • Çoğunlukla Olumsuz: %40 altı olumsuz çoğunluk.
Oyun İçi Oylama Çağrısı (Game Over, Ana Menü veya Ayarlar Ekranı)
// Oyun bittiğinde veya oyuncu ana menüde "⭐ Oyunu Değerlendir" butonuna bastığında:
function onGameOverOrFeedbackClick() {
    // PlayZone üst çubuğundaki oylama & yorum modalını tetikler:
    felerousBridge.openReviews();
}
💡
Geliştirici Avantajı: Oyuncuların oy vermesi için oyundan çıkıp mağaza sayfasına gitmelerine gerek yoktur. Modal oyunun üzerinde yarı şeffaf bir katman (HUD) olarak açılır; oyuncu saniyeler içinde oyunu değerlendirip oynamaya devam edebilir.

⭐ 12.2 Google Zengin Sonuçlar & Schema.org Standardı (Otomatik SEO)

PlayZone'a yüklenen her oyun, FELEROUS sunucu katmanı (api/playzone.js) tarafından Google standartlarında Zengin Sonuç (Rich Snippet) etiketleriyle indekslenir.

🔍 Google Arama Motoru İçin Uygulanan Otomatik Standartlar

  • VideoGame + WebApplication Çift Türü: Google'ın "Yalnızca tek başına VideoGame tipine zengin sonuç kartı göstermeme" kuralı gereği, oyununuz otomatik olarak ["VideoGame", "WebApplication"] tipiyle sunulur.
  • Canlı Yıldız Skoru (AggregateRating): Oyuncuların verdiği incelemeler 1.0 - 5.0 ölçeğinde hesaplanarak Google arama sonuçlarında altın yıldızlar (⭐⭐⭐⭐⭐ 4.8 / 5) ve inceleme sayısı olarak görünür.
  • Ücretsiz Oynanabilir Fiyatlandırma: offers: { price: "0", priceCurrency: "TRY" } tanımıyla Google oyununuzu "Ücretsiz Oyna" kartı olarak öne çıkarır.
Googlebot'a Sunulan Dinamik JSON-LD Şeması Örneği
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": ["VideoGame", "WebApplication"],
  "name": "Düşen Sicimler",
  "applicationCategory": "GameApplication",
  "operatingSystem": "Web Browser, HTML5, WebGL",
  "inLanguage": "tr",
  "offers": {
    "@type": "Offer",
    "price": "0",
    "priceCurrency": "TRY",
    "availability": "https://schema.org/InStock"
  },
  "author": {
    "@type": "Organization",
    "name": "Subushaki"
  },
  "publisher": {
    "@type": "Organization",
    "name": "FELEROUS",
    "url": "https://felerous.com"
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.8",
    "bestRating": "5",
    "worstRating": "1",
    "ratingCount": "18"
  }
}
</script>

📱 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 (100dvh en sonda yer alarak modern tarayıcılarda öncelik kazanır):

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 ve yalnızca running durumuna geçtiğinde dinleyiciyi kaldırır:

unlockAudio Snippet
function unlockAudio() {
  if (!window.audioCtx) return;
  if (window.audioCtx.state === 'suspended') {
    window.audioCtx.resume().then(() => {
      if (window.audioCtx.state === 'running') {
        document.removeEventListener('pointerdown', unlockAudio);
      }
    }).catch(() => {});
  } else if (window.audioCtx.state === 'running') {
    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.5 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_html5.js / felerous-bridge_phaser.js): Oyununuz harici bir sitede çalışsa bile HTML dosyanızda resmi Felerous SDK köprüsü 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": "Vortex", "score": 2400, "isPlayer": true },
    { "rank": 2, "name": "SiberCellat", "score": 1420, "isPlayer": false }
  ]
}

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, shortcut.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.
🎮
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. İ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.