Head

Weltkarten erstellen

Inzwischen existieren sehr viele externe Seiten die Daten aus Travian auf verschiedene Art und Weise darstellen. In den meisten Fällen handelt es sich dabei um Karten und Statistiken.

Dieses Tutorial soll Licht ins Dunkel bringen und euch zeigen, wie ihr selbst ein solches Tool für eure Allianz oder gleich für Alle bauen könnt. Allerdings wird euch hier nicht das Programmieren beigebracht. Das solltet ihr bereits können. Ich habe auch extra darauf geachtet, dieses Tutorial möglichst unabhängig zu halten und nicht auf eine bestimmte Sprache zu begrenzen. Allerdings benutze ich im Beispiel PHP mit MySQL, da dies die wohl gängigste Lösung ist.

Inhalt

  1. Was für Vorkenntnisse werden benötigt?
  2. Was benötige ich auf meinem Server/Webspace?
  3. Woher kommen die Daten?
  4. In welchen Format sind die Daten?
  5. Was für Informationen stehen zur Verfügung?
  6. Wie bekomme ich die Daten auf meinen Server?
  7. Beispiel: Statische Allymap

Was für Vorkenntnisse werden benötigt?

Ihr solltet eine webtaugliche Programmiersprache eurer Wahl beherrschen. Außerdem setze ich solide SQL-Kenntnisse mit einer Datenbank eurer Wahl voraus.

Was benötige ich auf meinem Server/Webspace?

Sehr populär ist die Kombination von PHP und MySQL, allerdings sollte man beachten dass die meisten Anbieter PHP im Safemode laufen lassen. Hierbei wird PHP aber leider so stark eingeschränkt, dass ein effizientes und automatisches Updaten der Daten fast unmöglich wird.

Warum funktioniert es mit dem Safemode nicht?
  • direkte Systembefehle über system() sind gesperrt
  • der Zugriff auf entfernte Dateien wird verhindert

Näheres dazu im Abschnitt “Wie bekomme ich die Daten auf meinen Server?

Woher kommen die Daten?

Da der Einsatz von Bots und Scripten im Spiel selbst verständlicherweise verboten ist, muss es einen anderen Weg geben um an die Daten zu kommen. Dazu stellt die Travian Games GmbH für jede Spielwelt einen täglich aktualisierten SQL-Dump zu Verfügung. In diesem Auszug sind grundlegende Infos zu jedem Dorf auf dem Server enthalten.

Der Dump wird jeden morgen um ca. 7 Uhr neu erstellt und steht in zwei Varianten zu Verfügung: unkomprimiert (Endung .sql) und gzip-komprimiert (Endung .sql.gz).

Zu finden ist die Datei immer im Wurzelverzeichnis der Spielwelt.

Beispiele:

In welchen Format sind die Daten?

Wie bereits oben erwähnt, sind die Dateien SQL-Dumps, beinhalten also nichts anderes als SQL-Insert-Befehle. Wichtig ist, das keine erweiterten Inserts verwendet werden, pro Datensatz gibt es also einen Insert-Befehl. (Wären es erweiterte Inserts, würden mehrere Datensätze in einem Insert zusammengefasst werden)

In allen alten Travian 2 Welten sind die Daten noch ANSI-encodiert, danach, also ab Travian 3, sind die Dateien UTF-8-encodiert.

Wenn man die entsprechende Tabelle in der Datenbank anlegen will, kann man dieses Stück SQL-Code benutzen:

CREATE TABLE `x_world` (
  `id` int(9) unsigned NOT NULL default '0',
  `x` smallint(3) NOT NULL default '0',
  `y` smallint(3) NOT NULL default '0',
  `tid` tinyint(1) unsigned NOT NULL default '0',
  `vid` int(9) unsigned NOT NULL default '0',
  `village` varchar(20) NOT NULL default '',
  `uid` int(9) NOT NULL default '0',
  `player` varchar(20) NOT NULL default '',
  `aid` int(9) unsigned NOT NULL default '0',
  `alliance` varchar(8) NOT NULL default '',
  `population` smallint(5) unsigned NOT NULL default '0',
  UNIQUE KEY `id` (`id`)
);

Was für Informationen stehen zur Verfügung?

Schlüsseln wir einfach mal die Spalten der Tabelle auf:

Spalte Erklärung
id Nummer des Feldes, beginnt links oben bei der Koordinate (-400|400) mit 1 und endet rechts unten bei (400|-400)
x X-Koordinate
y y-Koordinate
tid Die Volksnummer. 1 = Römer, 2 = Germanen, 3 = Gallier, 4 = Natur und 5 = Nataren
vid Dorfnummer
village Dorfname
uid Spielernummer (auch bekannt als User-ID)
player Spielername
aid Allianznummer
alliance Allianzname
population Bevölkerung dieses Dorfes

Wichtig: Off- und Deffwerte stehen KEINE zur Verfügung!

Wie bekomme ich die Daten auf meinen Server?

Manuell ist das meistens kein Problem: Man lädt sich einfach den aktuellen Dump herunter und spielt ihn anschließend mit einem Tool wie zum Beispiel PHPmyAdmin in die Datenbank ein.

Was aber wenn das Alles automatisch jeden morgen von selbst geschehen soll? Im Idealfall läuft es dann so ab:

  1. Ein Cronjob startet das Updatescript
  2. Ein Downloadtool lädt den Dump herunter
  3. Ein DB-Client spielt den Dump in die Datenbank ein

Dieses Updatescript ist jedoch kein PHP- oder ähnliches Script das zur Webseitengeneration verwendet wird, sondern ein Shellscript, welches auf der Konsole der Servers läuft. Nun haben aber leider nur die wenigsten Leute Shellzugang zu dem Server auf dem ihre Seiten liegen.

Eigentlich spielt das aber keine Rolle, da man diese Prozesse auch per system()-Befehl in einem normalen PHP-Script starten kann. Da aber die meisten Provider PHP aus Sicherheitsgründen im Safemode betreiben, der unter anderem den system()-Befehl deaktiviert, bleibt den meisten nur die Möglichkeit alles komplett in PHP abzuwickeln.

Das funktioniert aber nur in den seltensten Fällen da die meisten Anbieter die Ausführungszeit der Scripte auf 10 oder max. 30 Sekunden beschränken, was bei großen Welten je nach Performance des Servers recht knapp wird. Außerdem ist meist auch der Zugriff auf Dateien und Dienste außerhalb des Servers gesperrt. Somit kommt man also gar nicht an die Daten...

Um es deutlich zu sagen: Ihr könnt es euch abschminken auf funpic.de eine Allymap zu betreiben :) Wenn ihr wirklich ernsthaft vorhabt, ein Tool für Travian anzubieten, dann solltet ihr euch nach einem flexibleren und besseren Hoster umsehen!

Ihr habt jetzt also den Safemode aus oder Shellzugang zu eurem Webserver? Fein, dann können wir weitermachen!

Hier jetzt ein konkretes Beispiel für ein Updatescript mit PHP, wget (Downloadtool für die Kommandozeile) und MySQL (benötigt wird der Server an sich sowie der Kommandozeilenclient „mysql“) unter Linux bzw. Unix-like-Betriebssystemen.

Auf Fehlerbehandlung wurde zwecks besserer Übersichtlichkeit weitgehend verzichtet.

Damit das Script läuft, solltet ihr im Verzeichnis des Scriptes einen Unterordner „data“ erstellen. Für diesen müssen die Rechte auch so gesetzt werden, dass der Benutzer des Webserver dort reinschreiben darf! Außerdem muss noch eine DB mit der Tabelle „x_world“ von oben erzeugt werden. Die Zugangsdaten dann oben im Script bei den Einstellungen eintragen.

Quellcode Updatescript

<?php
    
    
// Einstellungen
    
$mysqlhost 'localhost';
    
$mysqluser 'user';
    
$mysqlpass 'passwort';
    
$mysqldb 'datenbank';
    
    
// Datenbankverbindung aufbauen und Datenbank auswählen
    
$db = @mysql_connect($mysqlhost$mysqluser$mysqlpass) OR die('Can not connect to DB-Server!');
    
$db_select = @mysql_select_db($mysqldb) OR die('Can not select DB!');
    
    
// map.sql per Systembefehl via "wget" in den Ordner data/ laden.
    // WICHTIG: PHP muss es erlaubt sein in den Ordner schreiben zu können, falls nötig also die Rechte setzen!
    
system('wget http://s1.travian.com/map.sql -O data/tmp.sql');

    
// Prüfen die Datei heruntergeladen wurde und größer als Null Bytes ist
    
if (file_exists('data/tmp.sql') AND filesize('data/tmp.sql')) {
        
        
// Tabelle leeren
        
$query 'TRUNCATE TABLE x_world';
        
$result = @mysql_query($query) OR die('Can not clear table x_world!');
        
        
// map.sql mit Hilfe des Programms "mysql" ausführen. 
        // WICHTIG: Bei T2 Welten muss das Charset auf "latin1" gestellt werden!
        
system('mysql --host='.$mysqlhost.' --user='.$mysqluser.' --password='.$mysqlpass.' --default-character-set=utf8 '.$mysqldb.' < data/tmp.sql');
        
        echo 
'Update finished!';
        
    } else {
        
        echo 
'Failed downloading map.sql or file is empty!';

    }
    
    
// Falls die temporäre Datei existiert diese löschen
    
if (file_exists('data/tmp.sql')) {
        
unlink('data/tmp.sql');
    }
    
    
// Datenbankverbindung schließen
    
@mysql_close($db);

?>

Eine weitere Möglichkeit das Updatescript zu schreiben ist mit Hilfe von cURL. Dadurch kann man auch die system()-Befehle umgehen.

<?php
    
    // Einstellungen
    $mysqlhost = 'localhost';
    $mysqluser = 'user';
    $mysqlpass = 'passwort';
    $mysqldb = 'datenbank';
    
    $sqlDatei = 'http://s1.travian.com/map.sql';
    
    // Datenbankverbindung aufbauen und Datenbank auswählen
    $db = @mysql_connect($mysqlhost, $mysqluser, $mysqlpass) OR die('Can not connect to DB-Server!');
    $db_select = @mysql_select_db($mysqldb) OR die('Can not select DB!');
    
    // Neue Datei wir erzeugt
    $newFile = fopen('data/tmp.sql', 'w');
    // Zuerst wird versucht ueber fopen() auf die Datei zuzugreifen
    if ($resource = @fopen($sqlDatei, 'r')) {
        while ($zeile = fgets($resource)) fwrite($newFile, $zeile);
        fclose($resource);
    }
    //Dann über cURL (wenn installiert)
    elseif ($resource = curl_init($sqlDatei)) {
        curl_setopt($resource, CURLOPT_RETURNTRANSFER, true);
        fwrite($newFile, curl_exec($resource));
    }
    // Ansonsten Beende mit Fehlermeldung
    else die("Dein Server unterstützt leider keine Methode um die Datei zu holen.");
    //Datei schließen
    fclose($newFile);
    

    // Prüfen die Datei heruntergeladen wurde und größer als Null Bytes ist
    if (file_exists('data/tmp.sql') AND filesize('data/tmp.sql')) {
        
        // Tabelle leeren
        $query = 'TRUNCATE TABLE x_world';
        $result = @mysql_query($query) OR die('Can not clear table x_world!');
        
        // WICHTIG: Bei T2 Welten muss das Charset auf "latin1" gestellt werden!
        // SQL-Befehle aus der Datei Zeile für Zeile ausführen
        $sqlDatei = fopen('data/tmp.sql', 'r');
        while ($sqlBefehl = fgets($sqlDatei)) mysql_query($sqlBefehl);
        echo 'Update finished!';
        
    } else echo 'Failed downloading map.sql or file is empty!';
    
    // Falls die temporäre Datei existiert diese löschen
    if (file_exists('data/tmp.sql')) {
        unlink('data/tmp.sql');
    }
    
    // Datenbankverbindung schließen
    @mysql_close($db);

?>

Danke an Mathias Haimerl für diese Möglichkeit der Updatefunktion!

Beispiel: Statische Allymap

Beispielkarte

Dieses kleine Script zeigt wie man eine simple Allymap bastelt. Man gibt oben in den Einstellungen die Zugangsdaten und die ID der Allianz an, die man hervorheben will. Damit erstellt das Script dann ein Bild auf dem alle Dörfer des Server eingezeichnet sind. Die Dörfer der gewünschten Allianz sind zusätzlich hervorgehoben.

Damit das Script läuft benötigt ihr PHP mit der GD-Lib und den Imagefunktionen sowie MySQL mit der DB und der Tabelle aus dem Updatescript oben.

Beachtet aber das man ein solches Bilder-Script nicht unbedingt auf Seiten die öfters abgerufen werden einbinden sollte, da es doch einiges an Ressourcen braucht um ein solches Bild zu erzeugen. Stattdessen solltet ihr das Bild einmal am Tag neu erstellen und dann cachen, also in einer Datei zwischenspeichern. Schaut euch einfach mal die weiteren Parameter von imagepng() an, da steht wie man das Bild einfach in einer Datei ablegt!

Quellcode Allymap

<?php

    
// aid der markierten Allianz
    
$marked_aid 2403;
    
    
// Einstellungen
    
$mysqlhost 'localhost';
    
$mysqluser 'user';
    
$mysqlpass 'passwort';
    
$mysqldb 'datenbank';
    
    
// Datenbankverbindung aufbauen und Datenbank auswählen
    
$db = @mysql_connect($mysqlhost$mysqluser$mysqlpass) OR die('Can not connect to DB-Server!');
    
$db_select = @mysql_select_db($mysqldb) OR die('Can not select DB!');
    
    
// Bild erstellen: Karte geht von -400 bis 400
    // -> macht 2*400+1 (+1 wegen der 0 in der Mitte)
    
$image imagecreate(801801);
    
    
// Festlegen der RGB farben von Hintergrund, normalen Dorf und Dorf der markierten Allianz
    
$color_background imagecolorallocate($image255255255);
    
$color_normal imagecolorallocate($image200200200);
    
$color_marked imagecolorallocate($image25500);

    
// Bild mit der Hintergrundfarbe auffüllen
    
imagefill($image00$color_background);

    
// ALLE Dörfer aus der DB auslesen und nach aufsteigender Feldernummer ordnen
    // (Felder werden von links oben nach rechts unten durchnumeriert)
    
$query 'SELECT x, y, aid FROM x_world ORDER BY id ASC';
    
$result = @mysql_query($query) OR die('Can not select villages from table x_world!');
    
    
// Prüfen ob überhaupt Dörfer gefunden wurden
    
if (mysql_num_rows($result)) {
        
        
// Erstes Dorf auslesen
        
$row = @mysql_fetch_assoc($result);
        
        
// In diesen Variablen ist gespeichert wo wir gerade zeichen
        
$x_pointer 0;
        
$y_pointer 0;
        
        
// Äußere Schleife für die Y-Koordinaten
        
for($y=400$y >= -400$y--) {
        
            
// Innere Schleife für die X-Koordinaten
            
for ($x=-400$x <= 400$x++) {
                
                
// Wenn wir beim Feld sind zu dem der aktuelle Datensatz gehört
                
if ($row['x'] == $x AND $row['y'] == $y) {
                    
                    
// Festlegen der Farbe in Abhänigkeit der aid
                    
if ($row['aid'] == $marked_aid) {
                        
$color $color_marked;
                    } else {
                        
$color $color_normal;
                    }
                    
                    
// Dorf mit der gewünschten Farbe einzeichen
                    
imagefilledrectangle($image$x_pointer$y_pointer, ($x_pointer 1), ($y_pointer 1), $color);
                    
                    
// Nächsten Datensatz holen
                    
$row = @mysql_fetch_assoc($result);
                }
                
                
// Zeiger für die X-Position erhöhen
                
$x_pointer++;
            }
            
            
// Zeiger für die Y-Position erhöhen
            
$y_pointer++;
            
            
// Wir sind am Ende einer Reihe, deshalb setzen wir den X-Zeiger zurück
            
$x_pointer 0;
        }    
    }
    
    
// Den für diesen Dateityp passenden HTTP-Header ausgeben
    
header("Content-Type: image/png");
    
    
// Bild generieren und ausgeben
    
imagepng($image);

?>
Suche

FAQ Einstellungen


Fehler melden | Letztes Update: 2010-08-30 16:49:48
Imprint | © 2004 - 2010 Travian Games GmbH