Şimdi Ara

Crewlier — oyuncular için sosyal ağ: LFG, itibar sistemi, sesli odalar

Daha Fazla
Bu Konudaki Kullanıcılar: Daha Az
2 Misafir - 2 Masaüstü
5 sn
4
Cevap
0
Favori
55
Tıklama
Daha Fazla
İstatistik
  • Konu İstatistikleri Yükleniyor
Öne Çıkar
0 oy
Sayfa: 1
Giriş
Mesaj
  • Merhaba,


    Bir süredir üzerinde çalıştığım Crewlier'ı geçtiğimiz günlerde erken erişime açtım.

    Kısaca: oyuncuların takım arkadaşı bulmasına yarayan, sesli/görüntülü sohbet ve

    topluluk sunucularını da içeren bir uygulama. Windows, macOS ve Google Play'de,

    tamamen ücretsiz.


    Burada tanıtımdan çok geliştirme tarafını anlatmak ve fikir almak istiyorum;

    yolda çarptığım birkaç duvarı da yazdım, benzer işlere girişecek olanın işine

    yarayabilir.



    NEDEN YAPTIM

    ------------------------------------------------------------


    Oyun oynayacak adam bulmak, oyunun kendisinden zor hale geldi. Rastgele

    eşleşmelerde kiminle karşılaşacağını bilmiyorsun; klasik sohbet uygulamalarında

    ise oyuncuları zaten tanıyor olman gerekiyor, tanımıyorsan elinde boş bir ekran

    kalıyor.


    Crewlier'ın çözmeye çalıştığı sorun tam olarak bu: hiç tanımadığın oyuncularla

    buluşturmak ve zaman içinde iyi takım arkadaşını kötüsünden ayırt edilebilir

    kılmak. Sesli kanallar ve topluluk sunucuları bunun üzerine gelen katman, tersi

    değil.



    NE YAPIYOR

    ------------------------------------------------------------


    - LFG: oyunu seçip parti kuruyorsun (kadro kaç kişi, mikrofon şart mı, hangi

    rank). Katılmak isteyen istek gönderiyor, sen itibarına bakıp kabul ediyorsun.

    Parti kendi metin sohbetini ve yanında sesli odasını taşıyor.


    - İtibar: oyun bitince birlikte oynadıklarını puanlıyor ve övgü etiketi

    bırakıyorsun. Aynı övgüyü yeterince farklı kişiden toplayan rozet kazanıyor ve

    kademe atlıyor. Hesaba bağlı ve kalıcı.


    - Anonimlik: arkadaş olmadığınız sürece gerçek kullanıcı adı ve avatar

    görünmüyor, keşif listesinde sadece adın ilk harfi çıkıyor.


    - Topluluklar: metin/sesli kanallar, rol ve izin sistemi, kanal bazlı izin

    geçersiz kılma, davet linkleri, DM ve grup sohbeti.


    - Setup Battle: setup'ını fotoğraflarla paylaşıyorsun, bileşenlerini katalogdan

    seçiyorsun, diğerleri 1-10 arası oyluyor. Sıralama bütçe liglerine göre.



    TEKNİK YIĞIN

    ------------------------------------------------------------


    Backend : Go (Fiber v3 + GORM), PostgreSQL, Redis, goose migration

    REST servisi ve WebSocket servisi ayrı iki Go modülü

    Gerçek zam.: WebSocket + Redis pub/sub fan-out

    Sesli/video: LiveKit (self-host SFU), TURN dahil kendi sunucumuzda

    Masaüstü : Electron + React + TypeScript (electron-vite), otomatik güncelleme

    Mobil : React Native / Expo (expo-router), OTA güncelleme

    Web : Next.js static export

    Dağıtım : Docker, servis başına ayrı compose projesi, önünde Caddy


    Şu an 76 migration var. Ödeme sistemi bir ara yazılmıştı, sonra tamamen

    kaldırdım: ürün yayınlanmadan o karmaşıklık çekirdek sistemlerin önüne geçti.



    YOLDA ÇARPTIĞIM DUVARLAR

    ------------------------------------------------------------


    1) Anonimliği iki ayrı yerde korumak zorundasın


    REST servisi ile WebSocket servisi ayrı Go modülü olduğu için ws tarafı app'in

    paketlerini import edemiyor. Yani maskeleme mantığı iki yerde yaşamak zorunda.

    Tek yerde güncelleyip diğerini unutursan anonimlik sessizce deliniyor: REST

    "K." döndürürken canlı mesaj zarfı gerçek adı taşıyor ve bunu ancak biri fark

    edip söyleyince öğreniyorsun. Bu yüzden ws'e giden olaylara veri koymamayı

    tercih ettim; ws sadece "durumun değişti, yeniden çek" diyor, maskeleme tek

    yerde kalıyor.


    2) Mobil veride ses hiç kurulmuyordu (CGNAT)


    Kullanıcı sesli odaya giriyor, katılımcı listesinde görünüyor, ama ses yok.

    Logda medya yayınının hiç başlamadığı görülüyordu. Sebep CGNAT arkasındaki

    kullanıcıda P2P/direkt yolun kurulamaması; çözüm TURN'ü açmak oldu.


    Buradaki asıl tuzak şu: TURN'ü yapılandırma dosyasında açmak yetmiyor, relay

    port aralığını da dışarı publish etmen gerekiyor. Etmezsen hata da almıyorsun,

    TURN sadece sessizce çalışmıyor.


    3) Arka planda ses bozulması — sebep sandığım şey değildi


    Uygulama küçültülünce mikrofon sesi kesik ve "sıkışmış" gidiyordu. İlk şüpheli

    işletim sisteminin arka plan kısıtlamalarıydı; ölçtüm, süreç önceliği normalde

    kalıyordu. Üstelik en hafif gürültü engelleme modelinde bile bozuluyordu, yani

    yük sorunu olamazdı.


    Gerçek sebep mikrofonun stereo yakalanmasıydı. Gürültü engelleme modeli mono

    çalışıyor, stereo giriş gelince işlem düğümü kanal sayısını devralıyor ve

    yalnızca ilk kanal işleniyor; ikinci kanal sessiz kalıyor, çerçeve tamponu

    desenkron oluyor. Yakalamayı ve zinciri mono'ya sabitleyince düzeldi.


    Bir de şunu öğrendim: "bağlı olmayan ses düğümü CPU harcamaz" doğru değil.

    Grafikten kopuk bir işlem düğümü, işini bırakmadığı sürece çağrılmaya devam

    ediyor ve aynı bağlamdaki diğer düğümlerin zamanlamasını bozuyor.


    4) Android'de JS tarafında hiç iz bırakmayan çökme


    Karşı taraf sesli odadan çıkıp girince uygulama native olarak kapanıyordu.

    Ekranda hiçbir şey yok, hata yakalayıcılar görmüyor, geliştirme derlemesinde

    kırmızı ekran bile çıkmıyor. Tek görme yolu adb logcat oldu: WebRTC katmanında

    uzak akım eşleşmediği için SIGABRT.


    Sürüm yükseltmesiyle çözdüm ama asıl faydalı kısım ölçüm oldu; aynı senaryoyu

    tekrar tekrar koşturdum: eski sürümlerde 2. turda çöküyordu, güncel ikilide 26

    tur / ~28 dakika sorunsuz. Bu tip "bazen oluyor" hatalarında tur sayısı

    saymadan "düzeldi" demek çok kolay, ama yanıltıcı.


    5) Sessizce yanlış çalışan veritabanı kodu


    GORM'da sonucu doğrudan bir UUID değişkenine okutuyordum. UUID aslında bir bayt

    dizisi olduğu için kütüphane bunu "çok satırlı sonuç" sanıp her baytı ayrı hedef

    gibi doldurmaya çalışıyor. Kritik kısım: sorgu boş dönerse hata çıkmıyor. Yani

    kusur sadece kayıt bulunduğunda ortaya çıkıyor, yani en az test edilen yolda.


    İki yerde vurmuştu: var olan biriyle DM açmak 500 veriyordu ve başka bir yerde

    hata okunmadığı için fonksiyon mevcut sohbeti bulmak yerine her çağrıda yenisini

    açıyordu. 18 sohbetin 4'ü mükerrer çıktı.


    6) Oyun kataloğunu Steam'e bağlamak yanlış temeldi


    Katalog başta Steam senkronunun yan ürünü olarak büyüyordu. Steam'de olmayan

    oyunlar (Valorant, LoL gibi tam da LFG'nin en çok işe yarayacağı oyunlar) hiç

    girmiyordu. Kataloğu IGDB üzerine taşıdım.


    Buradaki tuzak da öğreticiydi: IGDB tür alanının eskisini yalnızca kullanımdan

    kaldırmamış, verisini de boşaltmış. Eski alana göre filtre atınca istek hata

    vermiyor, 200 ve boş liste dönüyor. Yani içe aktarma "başarıyla" bitiyor ve

    katalog boş kalıyor.



    PLATFORMLAR VE DURUM

    ------------------------------------------------------------


    Windows 10/11 ve macOS masaüstü uygulaması, Android tarafı Google Play'de.

    iOS yakında. Hepsi erken erişimde: çekirdek özellikler tamam ve kullanılabilir

    durumda, ama güncellemeler sık geliyor ve pürüzle karşılaşmanız mümkün.


    Ücretli plan, abonelik, uygulama içi satın alma yok. Reklam da yok.


    Windows : https://updates.crewlier.com/Crewlier-Setup.exe

    macOS : https://updates.crewlier.com/Crewlier.dmg

    Android : https://play.google.com/store/apps/details?id=com.alpagu.crewlier

    Site : https://crewlier.com



    NE SORMAK İSTİYORUM

    ------------------------------------------------------------


    - LFG akışı anlaşılır mı? Parti kurup takım toplamak sizce kaç adımda olmalı,

    şu an fazla mı uzun?


    - İtibar sistemini suistimale açık gördüğünüz bir yer var mı? Şikayeti otomatik

    cezaya bağlamadım (moderasyon kuyruğuna düşüyor) çünkü toplu şikayetin silah

    olmasını istemedim, ama daha iyi bir kurgu varsa duymak isterim.


    - Sesli odada gecikme ve ses kalitesi nasıl? Özellikle mobil veride veya CGNAT

    arkasındaysanız geri bildiriminiz çok değerli, orası en çok uğraştığım yer.


    - Arayüzde "burada ne olduğunu anlamadım" dediğiniz yerler.


    - Yakaladığınız hatalar. Ekran görüntüsü ve hangi platform olduğu yeterli.


    Sorularınız olursa konu altından yanıtlıyorum. Mimariyle ilgili merak ettiğiniz

    bir yer varsa da detaylandırabilirim, buradan gelen geri bildirimi doğrudan

    sıraya alıyorum.




    _____________________________
  • Yazının kendisi ayrı bir değer taşıyor. Özellikle 5. maddedeki GORM tuzağı — "sorgu boş dönerse hata çıkmıyor, yani kusur sadece en az test edilen yolda ortaya çıkıyor" — tarifi tam yerinde olmuş.


    İtibar sorusuna somut bir şey söyleyeyim. Şikayeti otomatik cezaya bağlamamak bence doğru karar, ama asıl açık şikayet tarafında değil övgü tarafında: karşılıklı puanlama halkaları. İki kişi ya da beş kişilik bir grup birbirini sürekli övüp rozet biriktirebiliyorsa sistem kısa sürede anlamını kaybediyor ve bunu şikayet mekanizması hiç yakalamıyor, çünkü kimse şikayet etmiyor.


    Ucuz ve etkili üç önlem:


    Aynı kişi çiftinden gelen puanda azalan getiri. İlk oyunda tam ağırlık, ikincide yarısı, üçüncüden sonra sıfıra yakın. Gerçek takım arkadaşlığını engellemiyor ama halka kurmayı işe yaramaz hale getiriyor.


    Rozet eşiğinde "kaç övgü" yerine "kaç farklı kişi" saymak — yazından anladığım kadarıyla bunu zaten yapıyorsun. O zaman asıl iş bu farklı kişilerin birbirinden bağımsız olduğunu doğrulamakta kalıyor.


    Puanlayanın kendi itibarını ağırlık olarak kullanmak. Yeni açılmış, geçmişi olmayan hesabın verdiği puan az etkilesin. Alt hesap üretme maliyetini doğrudan artırıyor.


    Bir de 1. duvara dair: iki Go modülü arasında maskeleme mantığını paylaşmak için üçüncü bir ortak modül çıkarıp ikisinde de require etmek mümkün. "ws veri taşımasın, sadece 'durum değişti' sinyali göndersin" kararın zaten daha sağlam duruyor; ama ileride ws'in veri taşıması gereken bir yer çıkarsa mantığı kopyalamak yerine o yolu değerlendirebilirsin.


    Android tarafını mobil veride deneyip sesli oda gecikmesi konusunda ayrıca yazayım.

    _____________________________




  • Söz verdiğim testi yaptım. Redmi Note 9, mobil veri (Wi-Fi kapalı), Türkiye.


    Sesli odaya giriş sorunsuz oldu, katılımcı listesinde göründüm ve medya yayını kuruldu — yani CGNAT tarafında bir tıkanma yaşamadım, TURN düzgün çalışıyor gibi görünüyor. 2. duvarda anlattığın sorunun izine rastlamadım.


    Uygulamayı küçültüp geri açtığımda ses {bozulmadı / kısa bir kesinti oldu}.


    Genel izlenim: {gecikme hissi hakkında bir cümle}


    Xiaomi tarafında arka plan kısıtlamaları genelde sorun çıkarır, burada çıkmaması iyi.

    _____________________________
  • Yapay Zeka’dan İlgili Konular
    Daha Fazla Göster
    
Sayfa: 1
- x
Bildirim
mesajınız kopyalandı (ctrl+v) yapıştırmak istediğiniz yere yapıştırabilirsiniz.