Merhaba, ben Krips. Uzun süre sonra tekrardan BELKİ 2-3 kişinin işine yarayacak bir rehber konusu açmak istedim. :evet:
Bu konuda Rage Multiplayer üzerinde sıfırdan bir sunucu geliştirirken, server tarafı ile client tarafının nasıl çalıştığını, hangi kodun nerede yazılması gerektiğini ve genel mimari mantığı geliştirici perspektifiyle anlatacağım.
Amaç hazır sistem kurmak değil. Amaç çalışan bir serverın arkasındaki düşünceyi anlamak.
Bu anlatım özellikle San Andreas Multiplayer (SA-MP)-DAN Rage Multiplayer (RAGE-MP)-E geçen, Csharp backend ve HTML/CSS frontend kullanmak isteyen geliştiriciler için hazırlanmıştır. Kodlar bilinçli olarak kısa tutulmuştur. Buradaki önemli nokta satır sayısı değil, mantığın oturmasıdır.
Hazırsanız başlayalım. :pc:
1. Rage Multiplayer de Temel Mimari Mantık
Rage:MP de sistem iki ana parçaya ayrılır.
Sunucu tarafı backend-tir. Client tarafı frontend-tir.
Backend Csharp ile yazılır (örnek) ve oyunun tüm kurallarını belirler. Frontend HTML ve CSS ile yazılır ve oyuncuya sadece arayüz sunar.
Temel kural şudur. Client hiçbir zaman güvenilir değildir.
2. Backend Neden Her Şeyin Merkezidir?
Para, karakter, envanter, yetki, spawn, vb vb komutlar gibi tüm kritik veriler backend'te tutulur. Client tarafı bu verilere sadece backend izin verdiği sürece erişir. Cliente güvenerek yazılan her sistem zamanla exploit üretir.
Bu yüzden frontend sadece veri ister. Kararı backend verir.
3. Server Kurulumu ve Klasör Yapısı
Rage:MP server dosyaları resmi siteden indirilir ve herhangi bir dizine çıkartılır. (( https://wiki.rage.mp/wiki/Getting_Started_with_Server ))
Temel yapı şu şekildedir
xxxroleplay/
dotnet/
client_packages/
conf.json
Csharp backend kodları dotnet klasöründe yer alır.
Client tarafı HTML ve Javascript dosyaları client_packages içinde tutulur.
4. Csharp Backend Giriş Noktası
Backend tarafında ilk çalışan dosya server.cs (dosya adı örnektir, vs üzerinden rename yaparak kendinize özel bir proje adı koyabilirsiniz) dosyasıdır.
using GTANetworkAPI;
public class server : Script
{
public GameMode()
{
NAPI.Util.ConsoleOutput("server aktif");
}
}
Bu dosya server ayağa kalktığında çalışır.
Burada ağır işlemler yapılmaz.
5. Oyuncu Server Bağlandığında Olanlar
Oyuncu sunucuya girdiği anda PlayerConnected eventi tetiklenir.
[ServerEvent(Event.PlayerConnected)]
public void OnPlayerConnected(Player player)
{
player.Dimension = (uint)player.Id;
player.TriggerEvent("client:showLogin");
}
Oyuncu izole edilir ve login ekranı açılır. Henüz oyuna spawn edilmez.
6. Client Tarafı Dosya Yapısı
Client tarafında arayüz dosyaları şu şekilde tutulur:
client_packages/
ui/
login.html
login.css
login.js
index.js
index.js client tarafının giriş dosyasıdır.
7. HTML Login Arayüzü Mantığı
login.html sadece arayüzdür. Kontrol yapmaz, karar vermez.
<input id="username">
<input id="password" type="password">
<button onclick="login()">giris</button>
Frontendin görevi sadece kullanıcıdan veri almaktır.
8. Client Tarafında UI Açılması
let browser = null;
mp.events.add("client:showLogin", () => {
browser = mp.browsers.new("package://ui/login.html");
});
Bu event backend tarafından çağrılır. Client sadece ekrana basar.
9. Frontend den Backende Veri Gönderme
function login() {
const user = document.getElementById("username").value;
const pass = document.getElementById("password").value;
mp.trigger("server:giriskontrolbaba", user, pass);
}
Frontend doğrulama yapmaz. Veriyi backende yollar.
10. Backendte Login Kontrolü
[RemoteEvent("server:giriskontrolbaba")]
public void giriskontrolbaba(Player player, string user, string pass)
{
if (user.Length < 3)
{
player.TriggerEvent("client:girissonuc", false);
return;
}
player.TriggerEvent("client:girissonuc", true);
}
Gerçek sistemde burada veritabanı olur. Mantık değişmez.
11. Login Sonucunun Cliente Gösterilmesi
mp.events.add("client:girissonuc", (success) => {
if(success) alert("giriş başarılı");
});
Client sonucu gösterir. Karar backendte verilmiştir.
12. Karakter Sisteminin Temel Mantığı
Karakter bilgileri backendte tutulur. Client sadece seçim ekranını gösterir.
Skin, spawn noktası ve karakter yetkileri vb vb. backend tarafından belirlenir.
13. Spawn Sistemi
Oyuncunun nerede spawn olacağına backend karar verir.
player.Position = new Vector3(402.9, -996.5, -99.0);
Client bu karara müdahale edemez.
14. Komut Sistemi Mantığı
Komutlar backendte yazılır.
[Command("test")]
public void testkomutu(Player player)
{
player.SendChatMessage("fullstackdeveloper");
}
Gördüğünüz gibi test komutu çalıştığı zaman chat de bizi fullstackdeveloper metni karşılıyor. Yetki ve kontrolerde burada yapılır.
15. Yeni Başlayanların Yaptığı Temel Hatalar
Her şeyi client tarafında yapmak
Şifre ve para gibi verileri frontend'te tutmak
Hazır altyapıyı anlamadan kullanmak
Server ve client ayrımını karıştırmak
Bu hatalar zamanla serverı kırılgan hale getirir.
16. Event İsimlendirme ve Katman Ayrımı
Yeni başlayanların yaptığı en büyük hatalardan biri, tüm eventleri tek dosyada ve kontrolsüz şekilde yazmaktır.
Event isimleri mutlaka yönü belli edecek şekilde olmalıdır.
client:showLogin
server:giriskontrolbaba
Bu sayede hangi eventin nereden nereye gittiği her zaman nettir.
Ayrıca backend tarafında login, karakter, envanter, admin gibi sistemler mutlaka ayrı class ve dosyalarda tutulmalıdır.
Her şeyi tek Script dosyasına yazmak kısa vadede kolay gibi görünür ama proje büyüdükçe yönetilemez hale gelir.
17. RemoteEvent Kullanırken Yapılması Gereken Kontroller
Client tarafından tetiklenen her RemoteEvent potansiyel olarak suistimale açıktır.
Bu yüzden backend tarafında her zaman şu kontroller yapılmalıdır:
Oyuncu gerçekten login olmuş mu
Oyuncu doğru karakteri mi kullanıyor
Oyuncunun o işlemi yapmaya yetkisi var mı
Örnek bir kontrol mantığı:
[RemoteEvent("server:buyItem")]
public void buyItem(Player player, int itemId)
{
if (!player.HasData("LOGGED_IN")) return;
if(itemId <= 0) return;
// gerçek sistemde burada para ve stok kontrolü yapılır
}
Client tarafında butona basılmış olması, o işlemin yapılacağı anlamına gelmez.
Son karar her zaman backendtedir.
18. Player Data ve State Yönetimi
RageMP tarafında oyuncuya ait geçici bilgiler backend tarafında tutulmalıdır.
player.SetData("LOGGED_IN", true);
player.SetData("CHAR_ID", 5);
Bu bilgiler client tarafına yazılmaz.
Login oldu mu, hangi karakter aktif, hangi ekran açık gibi state bilgileri backendte yönetilir.
Bu yaklaşım özellikle reconnect, crash ve yeniden spawn senaryolarında ciddi avantaj sağlar.
19. Dimension Mantığını Doğru Kullanmak
Dimension sistemi genelde sadece interior için kullanılıyor sanılıyor.
Aslında en güçlü kullanım alanı izolasyondur.
Login, karakter seçimi ve create ekranlarında oyuncular mutlaka ana dünyadan ayrılmalıdır.
player.Dimension = (uint)(player.Id + 1000);
Bu sayede login ekranındaki bir oyuncu ile oyundaki başka bir oyuncu birbirini asla görmez.
Özellikle roleplay sunucularında bu konu ileride birçok görsel ve senkron problemini baştan engeller.
20. Backend Tarafında Servis Mantığı Kurmak
Orta ve büyük projelerde doğrudan Script sınıfları içinde iş yapmak yerine servis katmanı oluşturmak çok daha sağlıklıdır.
Örneğin:
CharacterService
AccountService
InventoryService
Script sınıfları sadece event alır ve ilgili servise yönlendirir.
Bu yapı test edilebilirliği artırır ve sistemi ileride başka bir projeye taşımanızı kolaylaştırır.
21. Veritabanı Erişimini Event İçine Gömmemek
Yeni başlayanlar genellikle RemoteEvent içinde doğrudan SQL sorgusu çalıştırır.
Bu yöntem ilk başta çalışır ama sistem büyüdükçe:
kod tekrarına
performans problemlerine
kontrolsüz bağlantılara
sebep olur.
Doğru yaklaşım, veritabanı erişimini tek bir katmanda toplamaktır.
Örneğin:
AccountRepository
CharacterRepository
RemoteEvent sadece iş akışını yönetir, veri erişimini değil.
22. Asenkron İşlemler ve Server Tick Bilinci
RageMP sunucusunda ana thread üzerinde uzun süren işlemler yapmak, tüm oyuncuların lag hissetmesine sebep olur.
Özellikle:
veritabanı sorguları
dosya işlemleri
dış servis çağrıları
mutlaka asenkron çalıştırılmalıdır.
Aksi halde tek bir oyuncunun yaptığı işlem, tüm serverı yavaşlatır.
23. Client Tarafında Mantık Şişirmemek
Client tarafı sadece:
arayüz
kamera
animasyon
görsel geri bildirim
için kullanılmalıdır.
Para düşürme, item verme, level atlama gibi tüm mantık backendte kalmalıdır.
Client tarafında yazılan her ekstra mantık, exploit yüzeyini büyütür.
24. Loglama ve Hata Takibi Altyapısı
Gerçek bir projede sadece ConsoleOutput yeterli değildir.
Login, para transferi, admin işlemleri gibi kritik aksiyonlar mutlaka loglanmalıdır.
En azından şu ayrım yapılmalıdır:
INFO - normal akış
WARN - şüpheli durum
ERROR - sistem hatası
Bu alışkanlık, canlı sunucuya geçtiğinizde sizi büyük ölçüde kurtarır.
25. Test Sunucusu ve Canlı Sunucu Ayrımı
Tek bir sunucu üzerinde hem geliştirme yapıp hem oyuncu oynatmak, ileride büyük sorun çıkarır.
En azından:
test veritabanı
test config
ayrı log klasörü
kullanılmalıdır.
Bu sayede yaptığınız denemeler canlı oyuncu verisini riske atmaz.
26. Gerçek Hayatta Karşılaşılan Tipik Exploit Senaryosu
En çok karşılaşılan örneklerden biri:
Client tarafında satın alma butonuna basıldığında sadece tek bir trigger atıldığı sanılır.
Gerçekte aynı event saniyede onlarca kez tetiklenebilir.
Bu yüzden backend tarafında:
işlem kilidi
cooldown
işlem sırasında state kontrolü
yapılmadan yazılan her sistem exploit üretir.
if(player.HasData("BUSY")) return;
player.SetData("BUSY", true);
// işlem yapılır
player.ResetData("BUSY");
Bu basit kontrol bile birçok açığı kapatır.
27. Proje Büyürken En Çok Zorlayan Konu: Bağımlılıklar
Küçük projelerde her sınıfın her sınıfı bilmesi sorun gibi görünmez.
Ancak proje büyüdükçe bu durum bağımlılık cehennemine dönüşür.
Bu yüzden servisler birbirine doğrudan değil, mümkün olduğunca arayüzler (interface) üzerinden bağlanmalıdır.
Bu yaklaşım uzun vadede kodun ömrünü ciddi şekilde uzatır.
28. Tavsiye
RageMP'de iyi bir sistem yazmak, sadece API bilmek değildir.
Asıl farkı oluşturan şey:
nerede client
nerede backend
nerede veri
nerede kural
olduğunu zihninizde net ayırabilmenizdir.
Bu ayrımı doğru yaptığınız anda, framework değişse bile geliştirici olarak ayakta kalırsınız.
Sonuç ve Son Söz
Bu konudaki amacım Rage Multiplayerde sadece çalışan bir server kurmayı değil, geliştiricinin yazdığı sistemin arkasındaki mantığı net şekilde kavramasını sağlamaktı. çünkü bu mimariyi doğru anladığınızda ister küçük bir roleplay sunucusu kurun ister büyük ölçekli bir proje geliştirin, karşılaştığınız her sorunda neyin nerede bozulduğunu bilir, başkasının altyapısına bağımlı kalmadan kendi sisteminizi bilinçli ve sürdürülebilir şekilde yönetebilirsiniz. :oku2:
Bilgi paylaştıkça çoğalır, sağlam sistemler tek başına değil birlikte kurulur.
Başarılı.
Başarılı. Kritik olan bu sorunları çok hızlı bir şekilde teşhis edip tedaviyi uygulamışsın.
Umarım bu bilgin ve başarın katlanarak devam eder.
konu geliştirildi ve güncellendi, aklıma geldikçe yeni şeylerde ekleyeceğim.
Alıntı yapılan: MaRVeL - 17 Şubat 2026, 01:21:30Konuya tekrar tekrar bakıyorum ama benim için çok ağır ve fazla. Yeni yeni Rage için adapta olmaya çalışıyorum fakat yinede anlayamadım. Çok karmaşık geliyor. Basit bir kayıt sistemli mod bulsam bile sQL olayını bağlasamda o sunucu SAMP'taki gibi buglu bölgede spawn ediyor. Sanırım bir süre daha uğraşacağım.
Başlangıçta Ragemp nin karmaşık gelmesi çok normal. SAMP ile mantık farklı ve yeni adapte olmaya çalışmak zaman alıyor.
En önemli nokta, sabırlı olmak ve adım adım ilerlemek. Önce basit bir kayıt ve login sistemi kur, verileri mutlaka backend üzerinden yönet. Spawn ve karakter sistemlerini küçük parçalara bölerek test et, her şeyi tek seferde yapmaya çalışma.
Eventleri ve data yönetimini doğru kavradığında, samptan Ragemp ye geçişin çok daha kolay olacak ve sistemin mantığını net şekilde anlayacaksın. Hata yapmak doğal, her deneme öğrenmek için bir fırsattır.
Azimle ilerlersen kısa sürede kendi modunu güvenli ve stabil bir şekilde geliştirebilecek seviyeye gelirsin. Sabırlı ol ve denemekten çekinme. :)