İçeriğe geç
UA.
Tüm projeler
CanlıFull-stackHaz 2026 — Devam ediyor

TTRPG Companion

Bir masaüstü kampanyası için gerçek zamanlı masa — ve kimsenin güvenmek zorunda olmadığı bir sunucu.

İki telefonda yan yana bir karakter sayfası ve pixel-art savaş arenası.
Rolüm
Tek geliştirici — API, gerçek zamanlı hub, kural motoru ve istemci.
Durum
Canlı

Problem

Bir masaüstü kampanyası yürütmek; canları, inisiyatif sırasını, envanteri, durum etkilerini ve ilişkileri kâğıt fişler ile grup sohbeti arasında takip etmek demek. Masanın bir kısmı uzaktayken bütün o ortak durum tek bir kişinin aklında yaşıyor — her zar atışı da öyle, ve geri kalan herkesin buna inanmaktan başka seçeneği yok.

Ne yaptım

Arkadaşlarımla yürüttüğüm kampanya için sıra tabanlı bir yardımcı. Tek bir Expo istemcisi — iOS, Android ve react-native-web sayesinde düz bir tarayıcı bağlantısı — SignalR hub'ı üzerinden bir .NET 8 API ile konuşuyor; böylece her oyuncu aynı fişleri, aynı inisiyatif sırasını ve aynı savaş turunu olduğu anda görüyor. Kurallar sunucuda: zar, savaş fazları, özellikler, durum etkileri, tetiklenen tepkiler, arena düzenleyicileri ve bir gün-dinlenme döngüsünü kapsayan kırk civarı domain servisi.

Nasıl görünüyor

  • Savaş arenası: arka sokakta pixel-art sprite'lar, altında tur sırası ve saldırı zarı paneli.
    Devam eden bir çekişmeli saldırı. Saldıran zarını giriyor, savunma karşı oyuncunun cihazında açılıyor ve sonucu sunucu belirliyor.
  • Karakter seçimi: can, kuvvet, çeviklik, racon ve parasıyla bir pixel-art portre ve bir arka hikâye.
    Üç oynanabilir karakter; her birinin statları ve hikâyenin içinden geldiği kısım.
  • Can çubuğu, bağlantı rozeti ve statlar, yetenekler, eşyalar, durumlar, hikâye, cüzdan ve ilişkiler bölümleri olan bir karakter sayfası.
    Her oyuncunun canlı güncellendiğini gördüğü sayfa — köşedeki rozet süs değil, SignalR bağlantısı.

Mimari

  1. İstemci

    iOS, Android ve tarayıcı için tek kod tabanı. Asıl kullanılan web sürümü: grup sohbetine atılan bir bağlantı, beş kişiden bir şey kurmasını istemekten iyidir.

    • Expo
    • React Native
    • expo-router
    • react-native-web
  2. Gerçek zamanlı hub

    Masadaki her eylem — katılmak, zar atmak, saldırmak, turu bitirmek — odaya yayınlanan bir hub metodu. Yeniden katılmak, kaçırılanı tekrar oynatmak yerine güncel durumu okuyor.

    • SignalR
    • .NET 8
  3. Kural motoru

    Zar, savaş fazları, özellikler, durum etkileri, tetiklenen tepkiler ve arena düzenleyicileri. Her kural bir servis; böylece yeni bir mekanik, mevcut bir dosyada yeni bir dal değil yeni bir dosya oluyor.

    • C#
    • Domain services
  4. Kalıcılık

    Odalar, karakterler, inisiyatif ve yürüyen savaş turu bellekte değil satırlarda. Lokalde SQLite, dağıtımda PostgreSQL; aynı context'in arkasında.

    • EF Core 8
    • PostgreSQL
    • SQLite

Kararlar ve ödünleşmeler

  • Zarı sunucu atıyor

    Kendi sayısını üreten bir istemci, daha iyi sayılar üretmeye ikna edilebilen bir istemcidir. Ham d20 sunucuda atılıyor; stat, ekipman ve ilişki düzenleyicileri de orada uygulanıyor — böylece masaya ulaşan sonuç, yolda kimsenin düzenlemiş olamayacağı bir sonuç oluyor.

  • Ama gerçek zar da sayılıyor

    Fiziksel masadaki insanlar zarlarını kaldırmayacak ve onlara kaldırmalarını söyleyen bir uygulama kapatılan bir uygulamadır. Sunucu atışının yanında, kendi attığınız sayıyı girmek için bir yol var; aynı kurallar ona da işliyor. Hile koruması uzaktaki oyuncuları, odadakileri disipline etmeden savunuyor.

  • Bağlantılar bellekte, oyun veritabanında

    SignalR bağlantıları tek kullanımlık — telefon uyur, tünel düşer, bir dağıtım süreci yeniden başlatır. Onları doğruluk kaynağı saymak, kopan bir bağlantının kaybedilen bir oturum olması demekti. Bunun yerine oda durumu kalıcılaştırılıyor; böylece yeniden bağlanmak bir kurtarma değil, bir okuma.

  • Oyun yöneticisinin ne yapabileceği bir sunucu kuralı

    İzleyici, oyuncu ve yönetici; istemcinin kimsenin bulamayacağını umduğu butonları gizlemesi yerine, kendi erişim seviyeleri olan ayrı hub metotlarından giriyor. Yalnızca arayüzde var olan yetki, herkesin geliştirici araçlarıyla kendine verebileceği yetkidir.

Sonuç

Arkadaşlar hiçbir şey kurmadan bir bağlantıyla katılıyor, oturum oyun ortasındaki bir dağıtımı atlatıyor ve kimse bir zar atışı için kimsenin sözüne güvenmek zorunda kalmıyor.