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

Een Metin2 ranking-site bouwen met PHP en MySQL

Een Metin2 ranking-site is een kleine maar krachtige webtoepassing die speler- en gildegegevens uit de database van je server haalt en aan bezoekers toont als geordende tabellen. Op deze pagina's zien spelers hun eigen level, de positie van hun gilde en hun PvP-statistieken; ze houden de community levend, voeden de competitie en geven je server een professionele uitstraling. In dit artikel laat ik stap voor stap zien hoe je vanaf nul een veilige en performante ranking-pagina bouwt met PHP en MySQL.

De Metin2-databasestructuur begrijpen

Metin2-servers verdelen hun gegevens over meerdere MySQL-databases: spelerinformatie staat meestal in de player-database, terwijl accounts in de account-database staan. Voor een ranking-site zijn de twee tabellen die ons interesseren:

  • player.player — bevat de name, het level, de exp, de playtime, het job (klasse) en het guild_id van elk personage.
  • player.guild — slaat de gildenaam (name), het level, de exp en de gildeoorlog-resultaten (win, draw, loss) op.

Een belangrijke opmerking: een ranking-site mag de tabellen waar de gameserver naartoe schrijft nooit wijzigen. De veiligste aanpak is een alleen-lezen MySQL-gebruiker aanmaken die alleen SELECT-query's kan uitvoeren.

CREATE USER 'ranking'@'localhost' IDENTIFIED BY 'een_sterk_wachtwoord';
GRANT SELECT ON player.player TO 'ranking'@'localhost';
GRANT SELECT ON player.guild TO 'ranking'@'localhost';
FLUSH PRIVILEGES;

Een veilige databaseverbinding (PDO)

De moderne, veilige manier om in PHP met MySQL te verbinden is PDO. Dankzij prepared statements zijn we beschermd tegen SQL-injectie. De verbinding in één bestand bundelen maakt het later eenvoudiger te beheren:

<?php
// db.php
$host = '127.0.0.1';
$db   = 'player';
$user = 'ranking';
$pass = 'een_sterk_wachtwoord';

$dsn = "mysql:host=$host;dbname=$db;charset=utf8mb4";
$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => false,
];

try {
    $pdo = new PDO($dsn, $user, $pass, $options);
} catch (PDOException $e) {
    http_response_code(500);
    exit('Kan geen verbinding maken met de database.');
}

In plaats van het databasewachtwoord hard in je broncode te zetten, is het veiliger om het in productie uit een .env-bestand of een omgevingsvariabele van de server te lezen.

De spelersranglijst ophalen

De meest klassieke tabel van een Metin2 ranking-site sorteert spelers op level en ervaring. Om de echte voortgang van een personage te rangschikken, sorteren we eerst op level en bij gelijkspel op exp:

<?php
$stmt = $pdo->prepare(
    "SELECT name, level, exp, playtime
     FROM player
     ORDER BY level DESC, exp DESC
     LIMIT :limit"
);
$stmt->bindValue(':limit', 50, PDO::PARAM_INT);
$stmt->execute();
$players = $stmt->fetchAll();

50 rijen per pagina tonen is zowel leesbaar als performant. Wil je er meer tonen, overweeg dan paginering toe te voegen.

De gegevens in een HTML-tabel tonen

Elke tekst die uit de database komt, moet met htmlspecialchars() worden ge-escaped voordat hij op de pagina belandt; anders kunnen spelersnamen met speciale tekens een XSS-lek openen. De kolom playtime wordt in minuten opgeslagen, dus we zetten die voor de leesbaarheid om naar uren:

<table>
  <thead>
    <tr><th>#</th><th>Naam</th><th>Level</th><th>Tijd</th></tr>
  </thead>
  <tbody>
  <?php foreach ($players as $i => $p): ?>
    <tr>
      <td><?= $i + 1 ?></td>
      <td><?= htmlspecialchars($p['name']) ?></td>
      <td><?= (int) $p['level'] ?></td>
      <td><?= round($p['playtime'] / 60) ?> u</td>
    </tr>
  <?php endforeach; ?>
  </tbody>
</table>

Een gildenranglijst toevoegen

Een gildenranglijst naast de spelerstabel plaatsen versterkt de competitie binnen de community. We kunnen gildes sorteren op level en het aantal gewonnen gildeoorlogen:

<?php
$stmt = $pdo->query(
    "SELECT name, level, win, draw, loss
     FROM guild
     ORDER BY level DESC, win DESC
     LIMIT 20"
);
$guilds = $stmt->fetchAll();

Je kunt ook de tabellen player en guild via guild_id samenvoegen om extra tabellen te maken zoals "de drukst bevolkte gildes".

Paginering en zoeken toevoegen

Naarmate je server groeit, wil je niet dat spelers genoegen nemen met alleen de top 50; iedereen is benieuwd naar zijn eigen positie. Daarom maken paginering en een eenvoudige zoekfunctie op naam de ranking-site veel bruikbaarder. We lezen het paginanummer uit de URL en casten het nog steeds om alles veilig te houden:

<?php
$page    = max(1, (int) ($_GET['page'] ?? 1));
$perPage = 50;
$offset  = ($page - 1) * $perPage;

$stmt = $pdo->prepare(
    "SELECT name, level, exp
     FROM player
     ORDER BY level DESC, exp DESC
     LIMIT :limit OFFSET :offset"
);
$stmt->bindValue(':limit', $perPage, PDO::PARAM_INT);
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
$stmt->execute();

Zet bij het zoeken op naam de invoer van de gebruiker nooit rechtstreeks in de query; gebruik LIKE in een prepared statement en bind het als parameter. Dat is veilig én laat spelers snel hun eigen personages vinden.

De pagina afstemmen op het thema van je server

Presentatie telt net zo zwaar als de technische basis. Een ranking-pagina oogt professioneel wanneer ze hetzelfde kleurenpalet, lettertype en logo-taal gebruikt als de hoofdsite van de server. De top drie benadrukken met goud/zilver/brons-kleuren, gilde-emblemen tonen en een mobielvriendelijke tabel ontwerpen verbeteren de bezoekerservaring merkbaar. De tabel op kleine schermen in een horizontaal scrollbare container plaatsen voorkomt overflow.

Prestaties en caching

Voor elke bezoeker een live query draaien belast de database naarmate je spelersaantal groeit. Omdat ranglijsten niet per seconde veranderen, is het heel verstandig om de resultaten kort te cachen:

  • Bewaar het queryresultaat enkele minuten in een bestand of Redis-cache en vernieuw het bij het verlopen.
  • Zorg dat de kolommen waarop je sorteert (level, exp) een MySQL-index hebben.
  • Host de ranking-site los van de machine van de gameserver en verbind alleen met de alleen-lezen gebruiker.

Veelgestelde vragen

Vertraagt de ranking-site de gameserver?

Niet als hij correct is opgezet. Gebruik je een alleen-lezen gebruiker, geïndexeerde query's en een paar minuten caching, dan blijft de databasebelasting verwaarloosbaar.

Waarom worden speciale tekens in spelersnamen verkeerd weergegeven?

Meestal is het een mismatch in de tekenset. Controleer of je charset=utf8mb4 gebruikt in de PDO-verbinding en of je HTML-pagina <meta charset="utf-8"> bevat.

Op welke velden moet ik rangschikken?

De meest gebruikelijke keuzes zijn level + ervaring, gildelevel en PvP/kill-statistieken. Afhankelijk van je servertype kunnen velden als speeltijd of goud ook interessant zijn.

Wil je een professionele ranking-site voor je server? Met PHP en MySQL ontwerp en bouw ik veilige, snelle ranglijst-pagina's die passen bij het thema van je server. Neem contact op om over je project te praten.

Bu kategorideki tüm yazılar →

Devamı için