
There are already a great number of external pages which collect information from Travian and display it in many different ways. These pages are mostly maps and statistics. This tutorial has been written to give you some hints on how these pages can be programmed. First of all, this tutorial is an example of a PHP / MySQL solution (probably the solution which is most used) and you should already know how to use these languages as this tutorial is not about teaching you how to program.
You should have a web-safe/web-usable programming language at your service. Also, this tutorial requires sound SQL-knowledge of a database of your choice.
A very popular combination is PHP and MySQL, however, you have to keep in mind that most host run PHP in Safemode. This deprives us of any efficient ways of automatically updating the data as PHP is far too limited in this set up.
Why doesn't it work in Safemode?More about this in the section "How do I get the information transferred to my server?".
As using bots and scripts in the game is illegal there has to be a different way of getting the information. Travian Games GmbH offers up to date SQL-Dumps of each game world, which offer basic information for each village on that particular world.
These dumps are updated each morning around 7am (GMT+1) and are available in two different versions: uncompressed (ending .sql) and gzip-compressed (ending .sql.gz).
The name these dumps have depends on the language of the game world. All German game worlds use the name "karte.sql[.gz]" whereas the other game worlds use "map.sql[.gz]".
The file can be found in the root directory of the game world.
Examples:As already mentioned above the files are SQL-Dumps and therefore they contain nothing but SQL-Insert-Commands. It is important to keep in mind that no advanced inserts are used and that there is one insert per record (would advanced inserts be used several records would be collected in a single insert).
The old Travian 2 game worlds used ANSI-encoding for the files, however, nowadays all dumps are UTF-8-encoded.
If you want to create the matching table in a database you can use the following piece of SQL-Code:
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`) );
Let's break down the table's columns:
| Column | Explanation |
|---|---|
| id | The number of the field, starts in the top left corner at the coordinate (-400|400) and ends in the bottom right corner at (400|-400) |
| x | X-Coordinate |
| y | y-Coordinate |
| tid | The tribe number. 1 = Roman, 2 = Teuton, 3 = Gaul, 4 = Nature and 5 = Natar |
| vid* | Village number |
| village | Village name |
| uid* | Player number also known as User-ID |
| player | Player name |
| aid | Alliance number |
| alliance | Alliance name |
| population | The village's number of inhabitants |
* Please note that neither vid nor uid are given twice. They both get assigned at the time the village or the player is created and are not changed any more (even if the village is conquered).
Important: Neither Off- nor Def-values are available!
Doing this manually shouldn't be much of a problem in most cases: You can just download the most recent dump and import it into your database using PHPmyAdmin, for example.
But what about doing this automatically each morning? The ideal answer looks similar to this:
This update script is by no means a PHP-Script or anything similar which is used to generate a webpage. It is a shell-script running on the server's console. Sadly however, not many people have shell access to the server running their page.
Normally this wouldn't be much of a problem as you can run these processes via the system()-command in a normal PHP-script. Unfortunately, most providers run in safemode for security reasons and the system()-command is disabled. The only option left for those unlucky ones is to use PHP for everything.
Most providers limit script running times to 10 to 30 seconds (pretty short time in which to download a large server's SQL-Dump). Additionally, accessing external files and services outside the server might be prohibited preventing you from even getting the files.
To be more explicit: Don't even consider using a free host if you’re really considering writing this mapping tool.
Okay, you finally got rid of safemode or gained shell access to your web server? Good, in that case we can continue!
The following example is a working one written in PHP and MySQL (you'll need a server and the commandline client "mysql"). You will need wget (Download tool for the commandline), too.
To keep it clear, error handling has been omitted to a large extent.
In order to let the script run you have to create a folder called "data" in the directory of the script. Of course you have to enable "write" rights for the web server's user. Additionally you have to create a DB with the table "x_world" as described above. Afterwards enter the access information at the top of the script.
<?php
// Preferences
$mysqlhost = 'localhost';
$mysqluser = 'user';
$mysqlpass = 'password';
$mysqldb = 'database';
// Create database connection and select database
$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!');
// load the map.sql via system command using "wget" into the folder data/
// IMPORTANT: PHP has to be allowed to write into that folder, if necessary set the needed rights!
system('wget http://s1.travian.com/map.sql -O data/tmp.sql');
// Check whether the file has been downloaded and is larger than zero bytes
if (file_exists('data/tmp.sql') AND filesize('data/tmp.sql')) {
// Empty table
$query = 'TRUNCATE TABLE x_world';
$result = @mysql_query($query) OR die('Can not clear table x_world!');
// Execute map.sql using the program "mysql"
// IMPORTANT: The charset "latin1" has to be used for T2 game worlds (if there should be any left with that version)
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!';
}
// In case the temporary file exists it will be deleted
if (file_exists('data/tmp.sql')) {
unlink('data/tmp.sql');
}
// Close database connection
@mysql_close($db);
?>
The following small script shows how to create a simple ally map. At the top simply enter the access codes and the ID of the alliance to highlight. With that information the script will generate a map of the whole server's villages and highlight those of the named alliance.
To enable this script's smooth and complete execution you have to have the following PHP extensions: GD-Lib and Image functions as well as the MySQL DB and table as described above in the update script.
You shouldn’t run this image-script too often as it does use up quite a high amount of resources. That's why rather than directly putting this script into an accessible/viewable page, put it somewhere else and let it cache a file once a day. To do this just read the other parameters of the imagepng() function.
<?php
// aid of the highlighted Alliance
$marked_aid = 2403;
// Preferences
$mysqlhost = 'localhost';
$mysqluser = 'user';
$mysqlpass = 'password';
$mysqldb = 'database';
// Create database connection and select database
$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!');
// Create image: Map goes from -400 to 400
// -> sums up to 2*400+1 (+1 due to the 0 in the centre)
$image = imagecreate(801, 801);
// Choose the colours of background, normal village and highlighted alliance
$color_background = imagecolorallocate($image, 255, 255, 255);
$color_normal = imagecolorallocate($image, 200, 200, 200);
$color_marked = imagecolorallocate($image, 255, 0, 0);
// Fill images background with chosen colour
imagefill($image, 0, 0, $color_background);
// Select ALL villages from the DB and order by ascending ID
// (Fields are numbered from top left to bottom right)
$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!');
// Check whether there any villages at all
if (mysql_num_rows($result)) {
// Select first village
$row = @mysql_fetch_assoc($result);
// These variables save the location on which we are currently drawing
$x_pointer = 0;
$y_pointer = 0;
// Outer loop for the Y-coordinates
for($y=400; $y >= -400; $y--) {
// Inner loop for the X-coordinates
for ($x=-400; $x <= 400; $x++) {
// Once we reached the coordinates matching the current record selected from the DB:
if ($row['x'] == $x AND $row['y'] == $y) {
// Selecting the village color depending on the aid
if ($row['aid'] == $marked_aid) {
$color = $color_marked;
} else {
$color = $color_normal;
}
// Drawing the village with the selected color
imagefilledrectangle($image, $x_pointer, $y_pointer, ($x_pointer + 1), ($y_pointer + 1), $color);
// Select next record
$row = @mysql_fetch_assoc($result);
}
// Increase pointer for X-coordinate
$x_pointer++;
}
// Increase pointer for Y-coordinate
$y_pointer++;
// We reached the end of a line and have to set the X-pointer to 0 again
$x_pointer = 0;
}
}
// Select the HTTP-Header for the selected filetype
header("Content-Type: image/png");
// Generate image and print it
imagepng($image);
?>