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




Yeni Kayıt

Konudaki Resimler






