array( 'name' => 'Server 1', 'url' => 'https://travianz.org/', 'login' => 'https://travianz.org/login.php', 'signup' => 'https://travianz.org/anmelden.php', 'image' => 'en1_big.jpg', 'status' => 'https://travianz.org/index.php?server_status=1', 'newsbox' => 'https://travianz.org/index.php?server_newsbox=1' ), 2 => array( 'name' => 'Server 2', 'url' => 'https://s2.travianz.org/', 'login' => 'https://s2.travianz.org/login.php', 'signup' => 'https://s2.travianz.org/anmelden.php', 'image' => 'en2_big.jpg', 'status' => 'https://s2.travianz.org/index.php?server_status=1', 'newsbox' => 'https://s2.travianz.org/index.php?server_newsbox=1' ), 3 => array( 'name' => 'Speed 3x', 'url' => 'https://speed.travianz.org/', 'login' => 'https://speed.travianz.org/login.php', 'signup' => 'https://speed.travianz.org/anmelden.php', 'image' => 'enx_big.jpg', 'status' => 'https://speed.travianz.org/index.php?server_status=1', 'newsbox' => 'https://speed.travianz.org/index.php?server_newsbox=1' ) // Adauga aici worlds noi, ex: // 4 => array( // 'name' => 'Server 3', // 'url' => 'https://s3.travianz.org/', // 'login' => 'https://s3.travianz.org/login.php', // 'signup' => 'https://s3.travianz.org/anmelden.php', // 'image' => 'en3_big.jpg', // 'status' => 'https://s3.travianz.org/index.php?server_status=1', // 'newsbox' => 'https://s3.travianz.org/index.php?server_newsbox=1' // ), ); /* * Fiecare instanta de joc isi expune propriile statistici prin endpoint-ul * ?server_status=1 de mai jos - ruleaza pe DB-ul instantei CURENTE, deci * Server 1 nu poate afla niciodata contoarele de la Server 2/3. */ if (isset($_GET['server_status'])) { header('Content-Type: application/json; charset=utf-8'); $tribes = '1, 2, 3, 6, 7, 8, 9'; $users = 0; $active = 0; $online = 0; $return = mysqli_query( $link, "SELECT COUNT(*) AS Total FROM " . TB_PREFIX . "users WHERE tribe IN(" . $tribes . ")" ); if ($return) { $row = mysqli_fetch_assoc($return); $users = isset($row['Total']) ? (int)$row['Total'] : 0; } $return = mysqli_query( $link, "SELECT COUNT(*) AS Total FROM " . TB_PREFIX . "users WHERE timestamp > " . (time() - (3600 * 24)) . " AND tribe IN(" . $tribes . ")" ); if ($return) { $row = mysqli_fetch_assoc($return); $active = isset($row['Total']) ? (int)$row['Total'] : 0; } $return = mysqli_query( $link, "SELECT COUNT(*) AS Total FROM " . TB_PREFIX . "users WHERE timestamp > " . (time() - (60 * 10)) . " AND tribe IN(" . $tribes . ")" ); if ($return) { $row = mysqli_fetch_assoc($return); $online = isset($row['Total']) ? (int)$row['Total'] : 0; } echo json_encode(array( 'status' => 'online', 'players' => $users, 'active' => $active, 'online' => $online )); exit; } /* * Endpoint public nou: ?server_newsbox=1 * Expune, in JSON, exact aceleasi date pe care in-game le arata deja * Templates/News/newsbox1.tpl (jucatori online, viteza, harta, protectie, * top player etc.) - aceleasi query-uri/conditii, doar output JSON in loc * de HTML, ca sa poata fi citit de lobby-ul altui world (sau de acest * index.php insusi, pentru propriile date). */ if (isset($_GET['server_newsbox'])) { header('Content-Type: application/json; charset=utf-8'); $online_total = 0; $return = mysqli_query( $link, "SELECT COUNT(*) AS Total FROM " . TB_PREFIX . "users WHERE timestamp > " . (time() - (60 * 10)) . " AND tribe != 0 AND tribe != 4 AND tribe != 5" ); if ($return) { $row = mysqli_fetch_assoc($return); if ($row && isset($row['Total'])) { $online_total = (int)$row['Total']; } } $top_username = '-'; $top_query = mysqli_query( $link, "SELECT username FROM " . TB_PREFIX . "users WHERE " . (INCLUDE_ADMIN ? 'access > 0 AND ' : 'access > 0 AND access < 8 AND ') . "id > 5 AND tribe IN (1,2,3,6,7,8,9) AND tribe > 0 ORDER BY oldrank ASC LIMIT 1" ); if ($top_query) { $row = mysqli_fetch_assoc($top_query); if ($row && !empty($row['username'])) { $top_username = $row['username']; } } if (CP == 0) { $village_exp = 'Fast'; } else if (CP == 1) { $village_exp = 'Slow'; } else { $village_exp = '-'; } if (MEDALINTERVAL >= 86400) { $medal_interval = (MEDALINTERVAL / 86400) . ' Days'; } else { $medal_interval = (MEDALINTERVAL / 3600) . ' Hours'; } $peaceTypes = array('None', 'Normal', 'Christmas', 'New Year', 'Easter'); $peace_system = isset($peaceTypes[PEACE]) ? $peaceTypes[PEACE] : 'Unknown'; echo json_encode(array( 'online_users' => $online_total, 'speed' => SPEED, 'troop_speed' => INCREASE_SPEED, 'evasion_speed' => EVASION_SPEED, 'map_size' => WORLD_MAX, 'village_exp' => $village_exp, 'protection_hours' => (int)(PROTECTION / 3600), 'medal_interval' => $medal_interval, 'start_date' => START_DATE, 'peace_system' => $peace_system, 'best_player' => $top_username )); exit; } /* * Fetch generic, in PARALEL (curl_multi), de JSON de la o lista de * URL-uri indexate dupa id de world. Folosit atat pentru server_status * cat si pentru server_newsbox - un singur loc care stie sa vorbeasca * HTTP catre celelalte worlds. */ define('MULTI_STATUS_CONNECT_TIMEOUT', 2); define('MULTI_STATUS_TIMEOUT', 3); function fetchJsonFromServers(array $urlsById) { $results = array(); if (!function_exists('curl_multi_init')) { // cURL indisponibil - toate worlds-urile raman fara date live. foreach ($urlsById as $id => $url) { $results[$id] = null; } return $results; } $multiHandle = curl_multi_init(); $handles = array(); foreach ($urlsById as $id => $url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, MULTI_STATUS_CONNECT_TIMEOUT); curl_setopt($ch, CURLOPT_TIMEOUT, MULTI_STATUS_TIMEOUT); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_multi_add_handle($multiHandle, $ch); $handles[$id] = $ch; } $running = null; do { curl_multi_exec($multiHandle, $running); curl_multi_select($multiHandle); } while ($running > 0); foreach ($handles as $id => $ch) { $decoded = null; $httpCode = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE); $response = curl_multi_getcontent($ch); if ($response !== false && $response !== null && $httpCode === 200) { $data = json_decode($response, true); if (is_array($data)) { $decoded = $data; } } curl_multi_remove_handle($multiHandle, $ch); curl_close($ch); $results[$id] = $decoded; } curl_multi_close($multiHandle); return $results; } function normalizeServerStatus($data) { $default = array('status' => 'offline', 'players' => 0, 'active' => 0, 'online' => 0); if (!is_array($data) || !isset($data['players'])) { return $default; } return array( 'status' => isset($data['status']) ? $data['status'] : 'online', 'players' => (int)$data['players'], 'active' => isset($data['active']) ? (int)$data['active'] : 0, 'online' => isset($data['online']) ? (int)$data['online'] : 0 ); } function normalizeServerNewsbox($data) { $default = array( 'online_users' => 0, 'speed' => '-', 'troop_speed' => '-', 'evasion_speed' => '-', 'map_size' => '-', 'village_exp' => '-', 'protection_hours' => '-', 'medal_interval' => '-', 'start_date' => '-', 'peace_system' => '-', 'best_player' => '-' ); if (!is_array($data)) { return $default; } $result = $default; foreach ($default as $key => $unused) { if (isset($data[$key]) && $data[$key] !== '') { $result[$key] = $data[$key]; } } return $result; } /* * Helpere de afisare pentru cardurile de newsbox: cand un world nu a * raspuns (ex. inca nu are endpoint-ul ?server_newsbox=1 activ), toate * campurile raman pe placeholder-ul '-' din normalizeServerNewsbox(). Fara * aceste helpere, sufixele (x / ore) s-ar lipi de placeholder si ar iesi * afisari confuze de genul "-x" in loc de un simplu "-". */ function mi_newsbox_value($value, $suffix = '') { $value = (string)$value; if ($value === '-' || $value === '') { return '-'; } return htmlspecialchars($value, ENT_QUOTES, 'UTF-8') . $suffix; } function mi_newsbox_map_size($value) { $value = (string)$value; if ($value === '-' || $value === '') { return '-'; } $escaped = htmlspecialchars($value, ENT_QUOTES, 'UTF-8'); return $escaped . 'x' . $escaped; } /* * Cache scurt pentru fetch-urile intre worlds (status + newsbox). * Fara asta, FIECARE vizitator pe pagina asta declanseaza N cereri HTTP * catre celelalte worlds - inutil pentru date cvasi-statice si pune * sarcina degeaba pe serverele celorlalte worlds. */ function getCachedJson($cacheFile, $ttlSeconds, callable $fetcher) { if (is_readable($cacheFile) && (time() - filemtime($cacheFile)) < $ttlSeconds) { $cached = json_decode(file_get_contents($cacheFile), true); if (is_array($cached)) { return $cached; } // Anomalie: fisierul de cache exista dar nu e JSON valid - trecem // peste el si reluam fetch-ul live in loc sa incredem date corupte. } $data = $fetcher(); $cacheDir = dirname($cacheFile); if (!is_dir($cacheDir)) { @mkdir($cacheDir, 0755, true); } // Best-effort: daca var/cache nu e writable, pur si simplu nu se // cacheaza si fiecare request face fetch live. @file_put_contents($cacheFile, json_encode($data)); return $data; } define('MULTI_STATUS_CACHE_TTL', 30); define('MULTI_NEWSBOX_CACHE_TTL', 60); $serverStats = getCachedJson(__DIR__ . '/var/cache/server_status.json', MULTI_STATUS_CACHE_TTL, function () use ($servers) { $urls = array(); foreach ($servers as $id => $server) { $urls[$id] = $server['status']; } $raw = fetchJsonFromServers($urls); $stats = array(); foreach ($raw as $id => $data) { $stats[$id] = normalizeServerStatus($data); } return $stats; }); $serverNewsboxes = getCachedJson(__DIR__ . '/var/cache/server_newsbox.json', MULTI_NEWSBOX_CACHE_TTL, function () use ($servers) { $urls = array(); foreach ($servers as $id => $server) { $urls[$id] = $server['newsbox']; } $raw = fetchJsonFromServers($urls); $newsboxes = array(); foreach ($raw as $id => $data) { $newsboxes[$id] = normalizeServerNewsbox($data); } return $newsboxes; }); foreach ($servers as $serverId => $server) { $servers[$serverId]['stats'] = isset($serverStats[$serverId]) ? $serverStats[$serverId] : normalizeServerStatus(null); $servers[$serverId]['newsbox'] = isset($serverNewsboxes[$serverId]) ? $serverNewsboxes[$serverId] : normalizeServerNewsbox(null); } /* * Pastreaza variabilele vechi pentru restul paginii legacy. * Contorul din lobby de mai jos foloseste suma tuturor worlds-urilor. */ $users = 0; $active = 0; $online = 0; foreach ($servers as $server) { $users += $server['stats']['players']; $active += $server['stats']['active']; $online += $server['stats']['online']; } ?> <?php echo SERVER_NAME; ?>
Travian 4

:
:
:

:

  • Screenshot
  • Screenshot
  • Screenshot
  • Screenshot
  • Screenshot
  • Screenshot
  • Screenshot

Available Worlds

:
:
:
:
:
:
:
:
:
:
:

Close

Close
Close

Close

Screenshot