aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Metin2

Metin2 Database Sitesi Yapımı (Item & Mob Proto)

Bir Metin2 database sitesi, oyundaki item ve canavar verisini ziyaretçilerin arayıp filtreleyebileceği bir web wiki'sine dönüştürür. Oyuncular "bu eşya nereden düşüyor?", "hangi mob kaç level?" ya da "bu kostümün bonusları ne?" gibi soruların cevabını oyuna girmeden bulabilir. Bu yazıda item_proto ve mob_proto verisini alıp temiz bir web veritabanına aktararak aranabilir, performanslı bir database sitesi kurmayı adım adım anlatıyorum.

Veri kaynaklarını anlamak: proto dosyaları

Metin2'de oyunun bildiği her item ve canavar iki ana yapıda tanımlıdır: item_proto ve mob_proto. Çoğu serverde bunlar hem ikili (binary) item_proto/mob_proto dosyaları hem de düz metin kaynakları olarak bulunur:

  • item_proto / item_names.txt — her eşyanın vnum'u, tipi (silah, zırh, kostüm, iksir…), alt tipi, value0–5 alanları, bonusları (apply'lar), fiyatı ve isimleri.
  • mob_proto / mob_names.txt — her canavarın vnum'u, seviyesi, rank'ı (pawn/boss/king…), can/saldırı değerleri, deneyimi ve isimleri.
  • item_names.txt ve mob_names.txt — vnum → yerelleştirilmiş isim eşlemesi. Çok dilli bir wiki için bu dosyalar kritiktir.

Web sitesi için en temiz yol, bu veriyi player veritabanındaki canlı tablolara dokunmadan ayrı bir wiki veritabanına aktarmaktır. Böylece oyun sunucusunu hiç yormadan, istediğin şemayı kurabilirsin.

Veriyi web veritabanına aktarmak

Pek çok server, proto verisini MySQL'de de tutar (örneğin player.item_proto tablosu). Eğer sende düz metin dosyaları varsa, bunları bir kez ayrıştırıp (parse) kendi wiki tablolarına yazan küçük bir import betiği yazmak en sağlıklısıdır. Önce sade bir şema kuralım:

CREATE TABLE wiki_items (
  vnum      INT UNSIGNED PRIMARY KEY,
  name      VARCHAR(64) NOT NULL,
  type      VARCHAR(32) NOT NULL,
  subtype   VARCHAR(32) NULL,
  level     SMALLINT UNSIGNED DEFAULT 0,
  price     INT UNSIGNED DEFAULT 0,
  KEY idx_name (name),
  KEY idx_type (type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE wiki_mobs (
  vnum  INT UNSIGNED PRIMARY KEY,
  name  VARCHAR(64) NOT NULL,
  level SMALLINT UNSIGNED DEFAULT 0,
  rank  VARCHAR(16) NULL,
  exp   INT UNSIGNED DEFAULT 0,
  KEY idx_name (name),
  KEY idx_level (level)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Bonus alanlarını (apply tipleri ve değerleri) ayrı bir wiki_item_attrs tablosunda vnum'a bağlı satırlar olarak tutmak, ileride "saldırı gücü +X olan tüm eşyalar" gibi aramaları mümkün kılar.

Tab ile ayrılmış proto'yu ayrıştırmak

item_names.txt gibi dosyalar genellikle TAB ile ayrılmış sütunlardan oluşur ve ilk satır başlıktır. PHP ile güvenli bir import şöyle görünür:

<?php
$fh = fopen('item_names.txt', 'r');
fgets($fh); // başlık satırını atla

$stmt = $pdo->prepare(
  "INSERT INTO wiki_items (vnum, name, type)
   VALUES (:vnum, :name, :type)
   ON DUPLICATE KEY UPDATE name = VALUES(name)"
);

while (($line = fgets($fh)) !== false) {
    $cols = explode("\t", trim($line));
    if (count($cols) < 2) continue;
    $stmt->execute([
        ':vnum' => (int) $cols[0],
        ':name' => $cols[1],
        ':type' => 'unknown',
    ]);
}
fclose($fh);

Tip ve bonus bilgisini item_proto'dan okuyup aynı satırı güncelleyebilirsin. Import'u oyun güncellemesinde tekrar çalıştırmak için ON DUPLICATE KEY UPDATE kullanmak, veriyi her seferinde sıfırlamadan tazelemeni sağlar.

Arama ve filtreleme API'si

Bir Metin2 database sitesinin kalbi aramadır. Kullanıcı bir isim parçası yazınca eşleşen item ve mob'ları döndüren bir endpoint kuralım. Kullanıcı girdisini asla doğrudan sorguya gömme; hazır ifade (prepared statement) ile parametre olarak bağla:

<?php
$q = trim($_GET['q'] ?? '');
$type = $_GET['type'] ?? null;

$sql = "SELECT vnum, name, type, level FROM wiki_items WHERE name LIKE :q";
$params = [':q' => '%' . $q . '%'];

if ($type) {
    $sql .= " AND type = :type";
    $params[':type'] = $type;
}
$sql .= " ORDER BY level DESC, name ASC LIMIT 50";

$stmt = $pdo->prepare($sql);
$stmt->execute($params);
header('Content-Type: application/json; charset=utf-8');
echo json_encode($stmt->fetchAll());

Çok sayıda eşya için name LIKE '%...%' yavaşlayabilir. Site büyüdüğünde MySQL FULLTEXT indeksine veya bir arama motoruna (Meilisearch gibi) geçmeyi düşün; ama birkaç bin satır için indeksli LIKE fazlasıyla yeterlidir.

Drop ilişkisini kurmak: "nereden düşer?"

Oyuncuların en çok aradığı bilgi, bir eşyanın hangi canavardan düştüğüdür. Drop verisi server'da mob_drop_item.txt, common_drop_item.txt ve drop_item_group gibi kaynaklarda tutulur. Bu ilişkiyi mob vnum ile item vnum'u bağlayan bir tabloya aktarırsan, iki yönlü sorgu açılır:

CREATE TABLE wiki_drops (
  mob_vnum  INT UNSIGNED NOT NULL,
  item_vnum INT UNSIGNED NOT NULL,
  chance    DECIMAL(8,4) NULL,
  PRIMARY KEY (mob_vnum, item_vnum),
  KEY idx_item (item_vnum)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Artık bir item sayfasında "bu eşyayı düşüren canavarlar"ı, bir mob sayfasında ise "bu canavarın drop listesi"ni JOIN ile listeleyebilirsin. Drop şansını gösterirken, dosyalardaki ham olasılık formatının server tipine göre farklılaşabileceğini unutma; bilmiyorsan oranı kesin gibi sunma, "yaklaşık" olarak belirt.

Arayüz: tooltip ve ikonlar

Veri ne kadar doğru olsa da sunum kötüyse kimse kullanmaz. İyi bir item sayfası, oyundaki tooltip'i taklit eder: isim, tip, level şartı, bonus listesi ve fiyat. İkonlar için oyun istemcisindeki item ikonlarını PNG olarak dışa aktarıp vnum ile eşleştirebilirsin. Birkaç pratik öneri:

  • Veritabanından gelen her metni ekrana basarken htmlspecialchars() ile kaçışla — özel karakterli isimler XSS'e yol açabilir.
  • Bonusları okunur etiketlere çevir (örn. apply tipi 1 → "Maksimum Can"). Bu eşlemeyi küçük bir sözlük dosyasında tut.
  • Mobil için tabloları yatay kaydırılabilir bir kapsayıcıya al; taşmayı önler.

Performans, önbellek ve SEO

Database siteleri okuma-ağırlıklıdır: veri nadiren değişir, ama çok okunur. Bu yapı önbelleklemeye çok uygundur. Her item ve mob sayfası kalıcı bir URL'ye sahip olmalı (örn. /item/27003) ve sonuçları birkaç dakika önbellekte tutmalısın. SEO açısından her sayfaya açıklayıcı bir <title>, meta açıklama ve mümkünse JSON-LD verisi eklemek, "Metin2 [eşya adı]" aramalarında görünürlüğünü artırır. Tüm item ve mob URL'lerini içeren bir sitemap.xml üretmek de aramaya çıkmanı hızlandırır.

Sık Sorulan Sorular

Wiki sitesi oyun sunucusunu etkiler mi?

Doğru kurulduğunda hayır. Proto verisini ayrı bir wiki veritabanına aktarıp, siteyi sadece o tablolardan okutursan canlı oyun veritabanına hiç dokunmazsın.

Düz metin proto dosyam yok, sadece binary var. Ne yapmalıyım?

Çoğu server, MySQL'de bir item_proto/mob_proto tablosu da tutar; oradan okuyabilirsin. Yoksa proto dosyalarını metne dönüştüren topluluk araçları (proto unpacker'lar) ile düz metin sürümünü çıkarman gerekir.

İsimler bozuk karakterlerle görünüyor, neden?

Genellikle karakter seti uyuşmazlığıdır. Tabloları utf8mb4 ile oluştur, import'ta dosyanın gerçek kodlamasını (çoğu proto için Latin/Windows kodlaması olabilir) UTF-8'e dönüştür ve sayfaya <meta charset="utf-8"> ekle.

Sunucun için profesyonel bir database/wiki sitesi mi istiyorsun? Proto verini güvenle aktarıp aranabilir, hızlı ve çok dilli bir wiki kurabilirim. Projeni konuşmak için benimle iletişime geç.

Bu kategorideki tüm yazılar →

Devamı için