diff --git a/README.md b/README.md index e8be6ce..29d6356 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Web Monitor for Half-Life based on [HLServers](https://github.com/YGGverse/HLSer * `chown -R www-data:www-data var` * `cp .env .env.local` -* `crontab -e` > `* * * * * /usr/bin/curl --silent http://localhost/crontab/online &> /dev/null` +* `crontab -e` > `* * * * * /usr/bin/curl --silent http://localhost/crontab/index &> /dev/null` ## Update diff --git a/migrations/Version20240107151414.php b/migrations/Version20240107151414.php new file mode 100644 index 0000000..07070fc --- /dev/null +++ b/migrations/Version20240107151414.php @@ -0,0 +1,31 @@ +addSql('CREATE TABLE player (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, crc32server BIGINT NOT NULL, crc32name BIGINT NOT NULL, joined BIGINT NOT NULL, updated BIGINT NOT NULL, online BIGINT NOT NULL, frags BIGINT NOT NULL, name VARCHAR(255) NOT NULL)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('DROP TABLE player'); + } +} diff --git a/src/Controller/CrontabController.php b/src/Controller/CrontabController.php index d95faf5..7c580cb 100644 --- a/src/Controller/CrontabController.php +++ b/src/Controller/CrontabController.php @@ -10,19 +10,20 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; use App\Entity\Online; +use App\Entity\Player; use Doctrine\ORM\EntityManagerInterface; class CrontabController extends AbstractController { #[Route( - '/crontab/online', - name: 'crontab_online', + '/crontab/index', + name: 'crontab_index', methods: [ 'GET' ] )] - public function online( + public function index( ?Request $request, EntityManagerInterface $entityManagerInterface ): Response @@ -62,14 +63,14 @@ class CrontabController extends AbstractController $total = $players + $bots; // Generate CRC32 server ID - $crc32Server = crc32( + $crc32server = crc32( $hlserver->host . ':' . $hlserver->port ); // Get last online value $online = $entityManagerInterface->getRepository(Online::class)->findOneBy( [ - 'crc32server' => $crc32Server + 'crc32server' => $crc32server ], [ 'id' => 'DESC' // same as online.time but faster @@ -82,16 +83,16 @@ class CrontabController extends AbstractController is_null($online) || $players !== $online->getPlayers() - || - $bots !== $online->getBots() - || - $total !== $online->getTotal() + // || + // $bots !== $online->getBots() + // || + // $total !== $online->getTotal() ) { $online = new Online(); $online->setCrc32server( - $crc32Server + $crc32server ); $online->setTime( @@ -116,6 +117,104 @@ class CrontabController extends AbstractController $entityManagerInterface->flush(); } + + // Update player stats + if ($players) + { + foreach ((array) $server->GetPlayers() as $session) + { + // Validate fields + if + ( + !isset($session['Name']) || mb_strlen($session['Name']) > 255 + || + !isset($session['TimeF']) || (int) $session['TimeF'] < 0 + || + !isset($session['Frags']) || (int) $session['Frags'] < 0 + ) + { + continue; + } + + // Skip bots + if ($session['TimeF'] == '59:59') + { + continue; + } + + // Generate CRC32 server ID + $crc32name = crc32( + $session['Name'] + ); + + $player = $entityManagerInterface->getRepository(Player::class)->findOneBy( + [ + 'crc32server' => $crc32server, + 'crc32name' => $crc32name, + ] + ); + + // Player exists + if ($player) + { + $player->setUpdated( + time() + ); + + $player->setOnline( + time() + ); + + if ((int) $session['Frags'] > $player->getFrags()) + { + $player->setFrags( + (int) $session['Frags'] + ); + } + } + + // Create new player + else + { + $player = new Player(); + + $player->setCrc32server( + $crc32server + ); + + $player->setCrc32name( + $crc32name + ); + + $player->setJoined( + time() + ); + + $player->setUpdated( + time() + ); + + $player->setOnline( + time() + ); + + $player->setName( + (string) $session['Name'] + ); + + $player->setFrags( + (int) $session['Frags'] + ); + } + + // Update DB + $entityManagerInterface->persist( + $player + ); + + $entityManagerInterface->flush(); + } + } } } } diff --git a/src/Entity/Player.php b/src/Entity/Player.php new file mode 100644 index 0000000..72e88b2 --- /dev/null +++ b/src/Entity/Player.php @@ -0,0 +1,126 @@ +id; + } + + public function getCrc32server(): ?string + { + return $this->crc32server; + } + + public function setCrc32server(string $crc32server): static + { + $this->crc32server = $crc32server; + + return $this; + } + + public function getCrc32name(): ?string + { + return $this->crc32name; + } + + public function setCrc32name(string $crc32name): static + { + $this->crc32name = $crc32name; + + return $this; + } + + public function getJoined(): ?string + { + return $this->joined; + } + + public function setJoined(string $joined): static + { + $this->joined = $joined; + + return $this; + } + + public function getUpdated(): ?string + { + return $this->updated; + } + + public function setUpdated(string $updated): static + { + $this->updated = $updated; + + return $this; + } + + public function getOnline(): ?string + { + return $this->online; + } + + public function setOnline(string $online): static + { + $this->online = $online; + + return $this; + } + + public function getFrags(): ?string + { + return $this->frags; + } + + public function setFrags(string $frags): static + { + $this->frags = $frags; + + return $this; + } + + public function getName(): ?string + { + return $this->name; + } + + public function setName(string $name): static + { + $this->name = $name; + + return $this; + } +} diff --git a/src/Repository/PlayerRepository.php b/src/Repository/PlayerRepository.php new file mode 100644 index 0000000..eaf39d3 --- /dev/null +++ b/src/Repository/PlayerRepository.php @@ -0,0 +1,23 @@ + + * + * @method Player|null find($id, $lockMode = null, $lockVersion = null) + * @method Player|null findOneBy(array $criteria, array $orderBy = null) + * @method Player[] findAll() + * @method Player[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class PlayerRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Player::class); + } +}