From dc0048d32d89914b053676592a1f326188ea3459 Mon Sep 17 00:00:00 2001 From: ghost Date: Fri, 12 Jan 2024 22:45:15 +0200 Subject: [PATCH] implement separated server pages, replace hlservers to masters tracking --- .env | 4 - composer.json | 3 +- config/services.yaml | 1 - migrations/Version20240111202908.php | 31 +++ src/Controller/CrontabController.php | 128 ++++++++++-- src/Controller/MainController.php | 159 ++++----------- src/Controller/RssController.php | 202 +++++++------------ src/Controller/ServerController.php | 183 +++++++++++++++++ src/Entity/Server.php | 111 +++++++++++ src/Repository/ServerRepository.php | 23 +++ templates/default/layout.html.twig | 4 +- templates/default/main/index.html.twig | 237 ++++------------------- templates/default/rss/online.xml.twig | 11 +- templates/default/rss/players.xml.twig | 11 +- templates/default/server/index.html.twig | 171 ++++++++++++++++ 15 files changed, 795 insertions(+), 484 deletions(-) create mode 100644 migrations/Version20240111202908.php create mode 100644 src/Controller/ServerController.php create mode 100644 src/Entity/Server.php create mode 100644 src/Repository/ServerRepository.php create mode 100644 templates/default/server/index.html.twig diff --git a/.env b/.env index 8fa0aed..4687db0 100644 --- a/.env +++ b/.env @@ -58,7 +58,3 @@ APP_THEME="default" # Masters list, server:port comma separated APP_MASTERS="" - -# Servers registry, URL or filepath -# https://github.com/YGGverse/HLServers -APP_HLSERVERS="https://raw.githubusercontent.com/YGGverse/HLServers/main/config.json" diff --git a/composer.json b/composer.json index a7a7e35..fbee364 100644 --- a/composer.json +++ b/composer.json @@ -44,7 +44,8 @@ "twig/extra-bundle": "^3.8", "twig/intl-extra": "^3.8", "twig/twig": "^3.8", - "xpaw/php-source-query-class": "^2.1" + "xpaw/php-source-query-class": "^2.1", + "yggverse/hl": "^1.0" }, "config": { "allow-plugins": { diff --git a/config/services.yaml b/config/services.yaml index 1427a23..b409c5c 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -8,7 +8,6 @@ parameters: app.name: '%env(APP_NAME)%' app.theme: '%env(APP_THEME)%' app.masters: '%env(APP_MASTERS)%' - app.hlservers: '%env(APP_HLSERVERS)%' app.meta.title: '%env(APP_META_TITLE)%' app.meta.description: '%env(APP_META_DESCRIPTION)%' app.meta.keywords: '%env(APP_META_KEYWORDS)%' diff --git a/migrations/Version20240111202908.php b/migrations/Version20240111202908.php new file mode 100644 index 0000000..57fde0f --- /dev/null +++ b/migrations/Version20240111202908.php @@ -0,0 +1,31 @@ +addSql('CREATE TABLE server (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, crc32server BIGINT NOT NULL, added BIGINT NOT NULL, updated BIGINT NOT NULL, online BIGINT NOT NULL, host VARCHAR(255) NOT NULL, port INTEGER NOT NULL)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('DROP TABLE server'); + } +} diff --git a/src/Controller/CrontabController.php b/src/Controller/CrontabController.php index d7dea17..8049e45 100644 --- a/src/Controller/CrontabController.php +++ b/src/Controller/CrontabController.php @@ -11,6 +11,8 @@ use Symfony\Component\HttpFoundation\Request; use App\Entity\Online; use App\Entity\Player; +use App\Entity\Server; + use Doctrine\ORM\EntityManagerInterface; class CrontabController extends AbstractController @@ -25,37 +27,133 @@ class CrontabController extends AbstractController )] public function index( ?Request $request, + TranslatorInterface $translatorInterface, EntityManagerInterface $entityManagerInterface ): Response { - // Get HLServers config - if ($hlservers = file_get_contents($this->getParameter('app.hlservers'))) + // Prevent multi-thread execution + $semaphore = sem_get( + crc32( + __DIR__ . '.controller.crontab.index', + ), 1 + ); + + if (false === sem_acquire($semaphore, true)) { - $hlservers = json_decode($hlservers); + return new Response( + $translatorInterface->trans('Process locked by another thread') + ); } - else + // Get new servers from masters + foreach ((array) explode(',', $this->getParameter('app.masters')) as $master) { - $hlservers = []; + if (!$host = parse_url($master, PHP_URL_HOST)) // @TODO IPv6 https://bugs.php.net/bug.php?id=72811 + { + continue; + } + + if (!$port = parse_url($master, PHP_URL_PORT)) + { + continue; + } + + // Connect master node + $node = new \Yggverse\Hl\Xash3D\Master($host, $port, 1); + + foreach ((array) $node->getServersIPv6() as $key => $value) + { + // Generate server identity + $crc32server = crc32( + $key + ); + + // Check server does not exist yet + $server = $entityManagerInterface->getRepository(Server::class)->findOneBy( + [ + 'crc32server' => $crc32server + ] + ); + + // Server exist, just update + if ($server) + { + $server->setUpdated( + time() + ); + + $server->setOnline( + time() + ); + + $entityManagerInterface->persist( + $server + ); + + $entityManagerInterface->flush(); + + continue; + } + + // Server does not exist, create new record + $server = new Server(); + + $server->setCrc32server( + $crc32server + ); + + $server->setHost( + $value['host'] + ); + + $server->setPort( + $value['port'] + ); + + $server->setAdded( + time() + ); + + $server->setUpdated( + time() + ); + + $server->setOnline( + time() + ); + + $entityManagerInterface->persist( + $server + ); + + $entityManagerInterface->flush(); + } } // Collect servers info $servers = []; - foreach ($hlservers as $hlserver) + foreach ((array) $entityManagerInterface->getRepository(Server::class)->findBy( + [ + 'crc32server' => (int) $request->get('crc32server') + ], + [ + 'id' => 'ASC' + ], + ) as $server) { try { - $server = new \xPaw\SourceQuery\SourceQuery(); + $query = new \xPaw\SourceQuery\SourceQuery(); - $server->Connect( - $hlserver->host, - $hlserver->port + $query->Connect( + false === filter_var($server->getHost(), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) ? $server->getHost() : "[{$server->getHost()}]", + $server->port ); - if ($server->Ping()) + if ($query->Ping()) { - if ($info = (array) $server->GetInfo()) + if ($info = (array) $query->GetInfo()) { // Filter response $bots = isset($info['Bots']) && $info['Bots'] > 0 ? (int) $info['Bots'] : 0; @@ -64,7 +162,7 @@ class CrontabController extends AbstractController // Generate CRC32 server ID $crc32server = crc32( - $hlserver->host . ':' . $hlserver->port + $server->host . ':' . $server->port ); // Get last online value @@ -121,7 +219,7 @@ class CrontabController extends AbstractController // Update player stats if ($players) { - foreach ((array) $server->GetPlayers() as $session) + foreach ((array) $query->GetPlayers() as $session) { // Validate fields if @@ -231,7 +329,7 @@ class CrontabController extends AbstractController finally { - $server->Disconnect(); + $query->Disconnect(); } } diff --git a/src/Controller/MainController.php b/src/Controller/MainController.php index 644bbc6..7129c64 100644 --- a/src/Controller/MainController.php +++ b/src/Controller/MainController.php @@ -11,6 +11,8 @@ use Symfony\Component\HttpFoundation\Request; use App\Entity\Online; use App\Entity\Player; +use App\Entity\Server; + use Doctrine\ORM\EntityManagerInterface; class MainController extends AbstractController @@ -28,139 +30,56 @@ class MainController extends AbstractController EntityManagerInterface $entityManagerInterface ): Response { - // Prepare request - if ('online' == $request->get('sort') && in_array($request->get('field'), ['time','players','bots','total'])) - { - $field = $request->get('field'); - } - - else if ('players' == $request->get('sort') && in_array($request->get('field'), ['name','frags','joined','online'])) - { - $field = $request->get('field'); - } - - else - { - $field = 'time'; - } - - if (in_array($request->get('order'), ['asc','desc'])) - { - $order = $request->get('order'); - } - - else - { - $order = 'desc'; - } - - // Get HLServers config - if ($hlservers = file_get_contents($this->getParameter('app.hlservers'))) - { - $hlservers = json_decode($hlservers); - } - - else - { - $hlservers = []; - } - // Collect servers info $servers = []; - foreach ($hlservers as $hlserver) + foreach ((array) $entityManagerInterface->getRepository(Server::class)->findAll() as $server) { // Init defaults - $info = []; - $session = []; - $online = []; - $players = []; - - // Generate CRC32 ID - $crc32server = crc32( - $hlserver->host . ':' . $hlserver->port - ); - - // Prepare aliases - $aliases = []; + $status = false; - foreach ($hlserver->alias as $value) - { - $alias = new \xPaw\SourceQuery\SourceQuery(); - - $alias->Connect( - $value->host, - $value->port - ); - - $aliases[] = [ - 'host' => $value->host, - 'port' => $value->port, - 'status' => $alias->Ping() - ]; - } + $info = + [ + 'Protocol' => null, + 'HostName' => null, + 'Map' => null, + 'ModDir' => null, + 'ModDesc' => null, + 'AppID' => null, + 'Players' => null, + 'MaxPlayers' => null, + 'Bots' => null, + 'Dedicated' => null, + 'Os' => null, + 'Password' => null, + 'Secure' => null, + 'Version' => null + ]; // Request server info try { - $server = new \xPaw\SourceQuery\SourceQuery(); + $node = new \xPaw\SourceQuery\SourceQuery(); - $server->Connect( - $hlserver->host, - $hlserver->port + $node->Connect( + false === filter_var($server->getHost(), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) ? $server->getHost() : "[{$server->getHost()}]", + $server->getPort() ); - if ($server->Ping()) + if ($node->Ping()) { - if ($info = (array) $server->GetInfo()) - { - // Get session - $session = empty($info['Players']) ? [] : (array) $server->GetPlayers(); - - // Sort by players by frags - if ($session) - { - array_multisort( - array_column( - $session, - 'Frags' - ), - SORT_DESC, - $session - ); - } - - // Get online - $online = $entityManagerInterface->getRepository(Online::class)->findBy( - [ - 'crc32server' => $crc32server - ], - 'online' == $request->get('sort') && $crc32server == $request->get('crc32server') ? [$field => $order] : ['time' => 'DESC'], - 10 - ); - - // Get players - $players = $entityManagerInterface->getRepository(Player::class)->findBy( - [ - 'crc32server' => $crc32server - ], - 'players' == $request->get('sort') && $crc32server == $request->get('crc32server') ? [$field => $order] : ['frags' => 'DESC'], - 10 - ); - } - $status = true; - } - else - { - $status = false; + foreach ((array) $node->GetInfo() as $key => $value) + { + $info[$key] = $value; + } } } catch (Exception $error) { - continue; + throw $this->createNotFoundException(); } catch (\Throwable $error) @@ -170,20 +89,18 @@ class MainController extends AbstractController finally { - $server->Disconnect(); + $node->Disconnect(); } // Add server $servers[] = [ - 'crc32server' => $crc32server, - 'host' => $hlserver->host, - 'port' => $hlserver->port, - 'description' => $hlserver->description, - 'aliases' => $aliases, + 'crc32server' => $server->getCrc32server(), + 'host' => $server->getHost(), + 'port' => $server->getPort(), + 'added' => $server->getAdded(), + 'updated' => $server->getUpdated(), + 'online' => $server->getOnline(), 'info' => $info, - 'session' => $session, - 'online' => $online, - 'players' => $players, 'status' => $status ]; } diff --git a/src/Controller/RssController.php b/src/Controller/RssController.php index 1e1a3a3..62b5c99 100644 --- a/src/Controller/RssController.php +++ b/src/Controller/RssController.php @@ -11,6 +11,8 @@ use Symfony\Component\HttpFoundation\Request; use App\Entity\Online; use App\Entity\Player; +use App\Entity\Server; + use Doctrine\ORM\EntityManagerInterface; class RssController extends AbstractController @@ -32,78 +34,47 @@ class RssController extends AbstractController EntityManagerInterface $entityManagerInterface ): Response { - // Get HLServers config - if ($hlservers = file_get_contents($this->getParameter('app.hlservers'))) + $online = []; + + foreach ($entityManagerInterface->getRepository(Online::class)->findBy( + [ + 'crc32server' => $request->get('crc32server') + ], + [ + 'id' => 'DESC' // same as online.time but faster + ], + 10 + ) as $value) { - $hlservers = json_decode($hlservers); + $online[] = + [ + 'id' => $value->getId(), + 'bots' => $value->getBots(), + 'players' => $value->getPlayers(), + 'total' => $value->getTotal(), + 'time' => $value->getTime() + ]; } - else - { - $hlservers = []; - } - - // Find server info - foreach ($hlservers as $hlserver) - { - // Generate CRC32 server ID - $crc32server = crc32( - $hlserver->host . ':' . $hlserver->port - ); - - // Skip servers not registered in HLServers - if ($crc32server != $request->get('crc32server')) - { - continue; - } - - // Get last online value - $online = $entityManagerInterface->getRepository(Online::class)->findBy( - [ - 'crc32server' => $crc32server - ], - [ - 'id' => 'DESC' // same as online.time but faster - ], - 10 - ); + // Response + $response = new Response(); - $result = []; + $response->headers->set( + 'Content-Type', + 'text/xml' + ); - foreach ($online as $value) - { - $result[] = - [ - 'id' => $value->getId(), - 'bots' => $value->getBots(), - 'players' => $value->getPlayers(), - 'total' => $value->getTotal(), - 'time' => $value->getTime() - ]; - } - - // Response - $response = new Response(); - - $response->headers->set( - 'Content-Type', - 'text/xml' - ); - - return $this->render( - 'default/rss/online.xml.twig', + return $this->render( + 'default/rss/online.xml.twig', + [ + 'server' => [ - 'server' => - [ - 'crc32' => $crc32server, - 'host' => $hlserver->host, - 'port' => $hlserver->port, - ], - 'online' => $result - ], - $response - ); - } + 'crc32server' => $request->get('crc32server'), + 'online' => $online + ] + ], + $response + ); throw $this->createNotFoundException(); } @@ -125,77 +96,44 @@ class RssController extends AbstractController EntityManagerInterface $entityManagerInterface ): Response { - // Get HLServers config - if ($hlservers = file_get_contents($this->getParameter('app.hlservers'))) + $players = []; + + foreach ($entityManagerInterface->getRepository(Player::class)->findBy( + [ + 'crc32server' => $request->get('crc32server') + ], + [ + 'id' => 'DESC' + ], + 10 + ) as $value) { - $hlservers = json_decode($hlservers); + $result[] = + [ + 'id' => $value->getId(), + 'name' => $value->getName(), + 'joined' => $value->getJoined() + ]; } - else - { - $hlservers = []; - } - - // Find server info - foreach ($hlservers as $hlserver) - { - // Generate CRC32 server ID - $crc32server = crc32( - $hlserver->host . ':' . $hlserver->port - ); - - // Skip servers not registered in HLServers - if ($crc32server != $request->get('crc32server')) - { - continue; - } - - // Get last players - $players = $entityManagerInterface->getRepository(Player::class)->findBy( - [ - 'crc32server' => $crc32server - ], - [ - 'id' => 'DESC' - ], - 10 - ); + // Response + $response = new Response(); - $result = []; + $response->headers->set( + 'Content-Type', + 'text/xml' + ); - foreach ($players as $value) - { - $result[] = + return $this->render( + 'default/rss/players.xml.twig', + [ + 'server' => [ - 'id' => $value->getId(), - 'name' => $value->getName(), - 'joined' => $value->getJoined() - ]; - } - - // Response - $response = new Response(); - - $response->headers->set( - 'Content-Type', - 'text/xml' - ); - - return $this->render( - 'default/rss/players.xml.twig', - [ - 'server' => - [ - 'crc32' => $crc32server, - 'host' => $hlserver->host, - 'port' => $hlserver->port, - ], - 'players' => $result - ], - $response - ); - } - - throw $this->createNotFoundException(); + 'crc32server' => $request->get('crc32server'), + 'players' => $players + ] + ], + $response + ); } } \ No newline at end of file diff --git a/src/Controller/ServerController.php b/src/Controller/ServerController.php new file mode 100644 index 0000000..98fb35b --- /dev/null +++ b/src/Controller/ServerController.php @@ -0,0 +1,183 @@ + '\d+', + ], + methods: + [ + 'GET' + ] + )] + public function index( + ?Request $request, + EntityManagerInterface $entityManagerInterface + ): Response + { + // Validate server + $server = $entityManagerInterface->getRepository(Server::class)->findOneBy( + [ + 'crc32server' => $request->get('crc32server') + ] + ); + + if (!$server) + { + throw $this->createNotFoundException(); + } + + // Prepare request + if ('online' == $request->get('sort') && in_array($request->get('field'), ['time','players','bots','total'])) + { + $field = $request->get('field'); + } + + else if ('players' == $request->get('sort') && in_array($request->get('field'), ['name','frags','joined','online'])) + { + $field = $request->get('field'); + } + + else + { + $field = 'time'; + } + + if (in_array($request->get('order'), ['asc','desc'])) + { + $order = $request->get('order'); + } + + else + { + $order = 'desc'; + } + + // Init defaults + $info = []; + $session = []; + $online = []; + $players = []; + + // Format name + if (false === filter_var($server->getHost(), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) + { + $name = "{$server->getHost()}:{$server->getPort()}"; + } + + else + { + $name = "[{$server->getHost()}]:{$server->getPort()}"; + } + + // Request server info + try + { + $node = new \xPaw\SourceQuery\SourceQuery(); + + $node->Connect( + false === filter_var($server->getHost(), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) ? $server->getHost() : "[{$server->getHost()}]", + $server->getPort() + ); + + if ($node->Ping()) + { + if ($info = (array) $node->GetInfo()) + { + // Get session + $session = empty($info['Players']) ? [] : (array) $server->GetPlayers(); + + // Sort by players by frags + if ($session) + { + array_multisort( + array_column( + $session, + 'Frags' + ), + SORT_DESC, + $session + ); + } + + // Get online + $online = $entityManagerInterface->getRepository(Online::class)->findBy( + [ + 'crc32server' => $server->getCrc32Server() + ], + 'online' == $request->get('sort') ? [$field => $order] : ['time' => 'DESC'], + 10 + ); + + // Get players + $players = $entityManagerInterface->getRepository(Player::class)->findBy( + [ + 'crc32server' => $server->getCrc32Server() + ], + 'players' == $request->get('sort') ? [$field => $order] : ['frags' => 'DESC'], + 10 + ); + } + + $status = true; + } + + else + { + $status = false; + } + } + + catch (Exception $error) + { + throw $this->createNotFoundException(); + } + + catch (\Throwable $error) + { + $status = false; + } + + finally + { + $node->Disconnect(); + } + + return $this->render( + 'default/server/index.html.twig', + [ + 'request' => $request, + 'server' => + [ + 'name' => $name, + 'crc32server' => $server->getCrc32Server(), + 'host' => $server->getHost(), + 'port' => $server->getPort(), + 'info' => $info, + 'session' => $session, + 'online' => $online, + 'players' => $players, + 'status' => $status + ] + ] + ); + } +} \ No newline at end of file diff --git a/src/Entity/Server.php b/src/Entity/Server.php new file mode 100644 index 0000000..55b44a1 --- /dev/null +++ b/src/Entity/Server.php @@ -0,0 +1,111 @@ +id; + } + + public function getCrc32server(): ?string + { + return $this->crc32server; + } + + public function setCrc32server(string $crc32server): static + { + $this->crc32server = $crc32server; + + return $this; + } + + public function getAdded(): ?int + { + return $this->added; + } + + public function setAdded(int $added): static + { + $this->added = $added; + + return $this; + } + + public function getUpdated(): ?int + { + return $this->updated; + } + + public function setUpdated(int $updated): static + { + $this->updated = $updated; + + return $this; + } + + public function getOnline(): ?int + { + return $this->online; + } + + public function setOnline(int $online): static + { + $this->online = $online; + + return $this; + } + + public function getHost(): ?string + { + return $this->host; + } + + public function setHost(string $host): static + { + $this->host = $host; + + return $this; + } + + public function getPort(): ?int + { + return $this->port; + } + + public function setPort(int $port): static + { + $this->port = $port; + + return $this; + } +} diff --git a/src/Repository/ServerRepository.php b/src/Repository/ServerRepository.php new file mode 100644 index 0000000..a36f283 --- /dev/null +++ b/src/Repository/ServerRepository.php @@ -0,0 +1,23 @@ + + * + * @method Server|null find($id, $lockMode = null, $lockVersion = null) + * @method Server|null findOneBy(array $criteria, array $orderBy = null) + * @method Server[] findAll() + * @method Server[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class ServerRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Server::class); + } +} diff --git a/templates/default/layout.html.twig b/templates/default/layout.html.twig index 05ca3fd..b05b9af 100644 --- a/templates/default/layout.html.twig +++ b/templates/default/layout.html.twig @@ -18,7 +18,7 @@ {% block header_container %}
{% block header_content %} - + @@ -40,7 +40,7 @@ {% block footer_content %} {% if app.masters %} - {{ 'Master' | trans }}: + {{ 'Master tracker' | trans }}: {% for i, master in app.masters | split(',') %} {% if i %}•{% endif %} {{ master }} {% endfor %} diff --git a/templates/default/main/index.html.twig b/templates/default/main/index.html.twig index 1da7b80..5ccb8bf 100644 --- a/templates/default/main/index.html.twig +++ b/templates/default/main/index.html.twig @@ -1,96 +1,23 @@ -{% macro sort(request, crc32server, sort, field) %} - {% if sort == request.get('sort') and crc32server == request.get('crc32server') %} - {% if field == request.get('field') %} - {% if 'asc' == request.get('order') %} - - - - - - - {% else %} - - - - - - - {% endif %} - {% else %} - - - - - - - {% endif %} - {% else %} - {% if 'online' == sort and 'time' == field %} - - - - {% elseif 'players' == sort and 'frags' == field %} - - - - {% else %} - - - - {% endif %} - - - - {% endif %} -{% endmacro %} -{% from _self import sort %} {% extends 'default/layout.html.twig' %} {% block main_content %} - {% for server in servers %} -
- {% if server.info.HostName is defined %} -

{{ server.info.HostName }} [#{{ server.crc32server }}]

- {% else %} -

#{{ server.crc32server }}

- {% endif %} -
- {% if server.description.title is defined %} -
- {{ server.description.title }} -
- {% endif %} - {% if server.description.links %} -
-
    - {% for link in server.description.links %} -
  • {{ link }}
  • - {% endfor %} -
-
- {% endif %} -

{{ 'Address' | trans }}

-
- {{ server.host }}:{{ server.port }} - {% if server.status %} - - - - - - {% else %} - - - - - - {% endif %} -
- {% if server.aliases %} -

{{ 'Alias' | trans }}

- {% for alias in server.aliases %} -
- {{ alias.host }}:{{ alias.port }} - {% if alias.status %} +

{{ 'Servers' | trans }}

+ + + + + + + + + + + + + {% if servers %} + {% for server in servers %} + + + + + + + + + + + + {% endfor %} + {% else %} + + + + {% endif %} +
{{ 'Status' | trans }}{{ 'Name' | trans }}{{ 'Map' | trans }}{{ 'Added' | trans }}{{ 'Online' | trans }}{{ 'Players' | trans }}{{ 'Max' | trans }}{{ 'Bots' | trans }}{{ 'Actions' | trans }}
+ {% if server.status %} @@ -103,111 +30,25 @@ {% endif %} - - {% endfor %} - {% endif %} - {% if server.info %} -

{{ 'Info' | trans }}

- - {% for key, value in server.info %} - - - - - {% endfor %} -
{{ key }}{{ value }}
- {% endif %} - {% if server.session %} -

{{ 'Session' | trans }}

- - - - - - - {% for player in server.session %} - - - - - - {% endfor %} -
{{ 'Player' | trans }}{{ 'Frags' | trans }}{{ 'Time' | trans }}
{{ player.Name }}{{ player.Frags }} - {% if player.TimeF == '59:59' %} - - - - {% else %} - {{ player.TimeF }} - {% endif %} -
- {% endif %} - {% if server.online %} - -

- {{ 'Online' | trans }} - - - -

- - - - - - - - {% for online in server.online %} - - - - - - - {% endfor %} -
- {{ 'Time' | trans }} {{ sort(request, server.crc32server, 'online', 'time') }} - - {{ 'Players' | trans }} {{ sort(request, server.crc32server, 'online', 'players') }} - - {{ 'Bots' | trans }} {{ sort(request, server.crc32server, 'online', 'bots') }} - - {{ 'Total' | trans }} {{ sort(request, server.crc32server, 'online', 'total') }} -
{{ online.time | date('r') }}{{ online.players }}{{ online.bots }}{{ online.total }}
- {% endif %} - {% if server.players %} - -

- {{ 'Players' | trans }} - - - -

- - - - - - - - {% for player in server.players %} - - - - - - - {% endfor %} -
- {{ 'Frags' | trans }} {{ sort(request, server.crc32server, 'players', 'frags') }} - - {{ 'Name' | trans }} {{ sort(request, server.crc32server, 'players', 'name') }} - - {{ 'Online' | trans }} {{ sort(request, server.crc32server, 'players', 'online') }} - - {{ 'Joined' | trans }} {{ sort(request, server.crc32server, 'players', 'joined') }} -
{{ player.frags }}{{ player.name }}{{ player.online | format_date }}{{ player.joined | format_date }}
- {% endif %} - - {% endfor %} +
{{ server.info.HostName }}{{ server.info.Map }}{{ server.added | format_date }}{{ server.online | format_date }}{{ server.info.Players }}{{ server.info.MaxPlayers }}{{ server.info.Bots }} + + + +
{{ 'Not found' | trans }}
{% endblock %} \ No newline at end of file diff --git a/templates/default/rss/online.xml.twig b/templates/default/rss/online.xml.twig index b52c31e..3f4b074 100644 --- a/templates/default/rss/online.xml.twig +++ b/templates/default/rss/online.xml.twig @@ -1,13 +1,14 @@ - - {{ server.host }}:{{ server.port }} - {{ app.name }} - {{ url('main_index') }} - {% for value in online %} + + #{{ server.crc32server }} - {{ 'Online' | trans }} - {{ app.name }} + {{ url('server_index', { crc32server : server.crc32server, _fragment : 'online' }) }} + {% for value in server.online %} {{ 'Online changed!' | trans }} - online#{{ value.id }} + {{ url('server_index', { crc32server : server.crc32server, _fragment : 'online' }) }}-{{ value.id }} + {{ url('server_index', { crc32server : server.crc32server, _fragment : 'online' }) }} {{ 'Players' | trans }}: {{ value.players }} {{ 'Bots' | trans }}: {{ value.bots }} diff --git a/templates/default/rss/players.xml.twig b/templates/default/rss/players.xml.twig index de8bca2..726e0ee 100644 --- a/templates/default/rss/players.xml.twig +++ b/templates/default/rss/players.xml.twig @@ -1,13 +1,14 @@ - - {{ server.host }}:{{ server.port }} - {{ 'Players' | trans }} - {{ app.name }} - {{ url('main_index') }} - {% for player in players %} + + #{{ server.crc32server }} - {{ 'Players' | trans }} - {{ app.name }} + {{ url('server_index', { crc32server : server.crc32server, _fragment : 'online' }) }} + {% for player in server.players %} {{ player.name }} {{ 'joined' | trans }} {{ app.name }}! - player#{{ player.id }} + {{ url('server_index', { crc32server : server.crc32server, _fragment : 'players' }) }}-{{ value.id }} + {{ url('server_index', { crc32server : server.crc32server, _fragment : 'players' }) }} {{ player.joined | date("D, d M Y h:i:s O") }} {% endfor %} diff --git a/templates/default/server/index.html.twig b/templates/default/server/index.html.twig new file mode 100644 index 0000000..6cd0609 --- /dev/null +++ b/templates/default/server/index.html.twig @@ -0,0 +1,171 @@ +{% macro sort(request, crc32server, sort, field) %} + {% if sort == request.get('sort') and crc32server == request.get('crc32server') %} + {% if field == request.get('field') %} + {% if 'asc' == request.get('order') %} + + + + + + + {% else %} + + + + + + + {% endif %} + {% else %} + + + + + + + {% endif %} + {% else %} + {% if 'online' == sort and 'time' == field %} + + + + {% elseif 'players' == sort and 'frags' == field %} + + + + {% else %} + + + + {% endif %} + + + + {% endif %} +{% endmacro %} +{% from _self import sort %} +{% extends 'default/layout.html.twig' %} +{% block head_title_content %}{{ server.name }} - {{ app.name }}{% endblock %} +{% block main_content %} +
+

+ {{ server.name }} + {% if server.status %} + + + + + + {% else %} + + + + + + {% endif %} +

+
+ {% if server.info %} +

{{ 'Info' | trans }}

+ + {% for key, value in server.info %} + + + + + {% endfor %} +
{{ key }}{{ value }}
+ {% endif %} + {% if server.session %} +

{{ 'Session' | trans }}

+ + + + + + + {% for player in server.session %} + + + + + + {% endfor %} +
{{ 'Player' | trans }}{{ 'Frags' | trans }}{{ 'Time' | trans }}
{{ player.Name }}{{ player.Frags }} + {% if player.TimeF == '59:59' %} + + + + {% else %} + {{ player.TimeF }} + {% endif %} +
+ {% endif %} + {% if server.online %} + +

+ {{ 'Online' | trans }} + + + +

+ + + + + + + + {% for online in server.online %} + + + + + + + {% endfor %} +
+ {{ 'Time' | trans }} {{ sort(request, server.crc32server, 'online', 'time') }} + + {{ 'Players' | trans }} {{ sort(request, server.crc32server, 'online', 'players') }} + + {{ 'Bots' | trans }} {{ sort(request, server.crc32server, 'online', 'bots') }} + + {{ 'Total' | trans }} {{ sort(request, server.crc32server, 'online', 'total') }} +
{{ online.time | date('r') }}{{ online.players }}{{ online.bots }}{{ online.total }}
+ {% endif %} + {% if server.players %} + +

+ {{ 'Players' | trans }} + + + +

+ + + + + + + + {% for player in server.players %} + + + + + + + {% endfor %} +
+ {{ 'Frags' | trans }} {{ sort(request, server.crc32server, 'players', 'frags') }} + + {{ 'Name' | trans }} {{ sort(request, server.crc32server, 'players', 'name') }} + + {{ 'Online' | trans }} {{ sort(request, server.crc32server, 'players', 'online') }} + + {{ 'Joined' | trans }} {{ sort(request, server.crc32server, 'players', 'joined') }} +
{{ player.frags }}{{ player.name }}{{ player.online | format_date }}{{ player.joined | format_date }}
+ {% endif %} +
+{% endblock %} \ No newline at end of file