Browse Source

initial release

main 1.0.0
ghost 12 months ago
parent
commit
c91e69fc73
  1. 1
      .gitignore
  2. 21
      README.md
  3. 17
      composer.json
  4. 125
      src/Xash3D/Master.php

1
.gitignore vendored

@ -0,0 +1 @@ @@ -0,0 +1 @@
/vendor/

21
README.md

@ -1,2 +1,21 @@ @@ -1,2 +1,21 @@
# hl-php
PHP library for Half-Life API
PHP 8 library for Half-Life API with native IPv6 / Yggdrasil support
## Install
`composer require yggverse/hl`
## Usage
### Xash3d
#### Master
```
$master = new Yggverse\Hl\Xash3d\Master('hl.ygg', 27010);
var_dump(
$master->getServersIPv6()
);
```

17
composer.json

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
{
"name": "yggverse/hl",
"description": "PHP 8 library for Half-Life API with native IPv6 / Yggdrasil support ",
"type": "library",
"license": "MIT",
"autoload": {
"psr-4": {
"Yggverse\\Hl\\": "src/"
}
},
"authors": [
{
"name": "YGGverse"
}
],
"require": {}
}

125
src/Xash3D/Master.php

@ -0,0 +1,125 @@ @@ -0,0 +1,125 @@
<?php
declare(strict_types=1);
namespace Yggverse\Hl\Xash3d;
class Master
{
private $_socket;
public function __construct(
string $host,
int $port,
int $timeout = 5
)
{
$this->_socket = fsockopen(
"udp://{$host}",
$port
);
stream_set_timeout(
$this->_socket,
$timeout
);
}
public function __destruct()
{
if ($this->_socket)
{
fclose(
$this->_socket
);
}
}
public static function getServersIPv6(
int $limit = 100,
string $region = "\xFF",
string $host = "0.0.0.0:0",
int $port = 0,
string $gamedir = "valve"
): ?array
{
// Is connected
if (!$this->_socket)
{
return null;
}
// Filter query
if (!fwrite($this->_socket, "1{$region}{$host}:{$port}\0\gamedir\t{$gamedir}\0"))
{
fclose(
$this->_socket
);
return null;
}
// Skip header
if (!fread($this->_socket, 6))
{
return null;
}
// Get servers
$servers = [];
for ($i = 0; $i < $limit; $i++)
{
// Get host
if (false === $host = fread($this->_socket, 16))
{
return null;
}
// Is end of packet
if (true === str_starts_with($host, 0))
{
break;
}
// Skip invalid host
if (false === $host = inet_ntop($host))
{
continue;
}
// Decode first byte for port
if (false === $byte1 = fread($this->_socket, 1))
{
return null;
}
// Decode second byte for port
if (false === $byte2 = fread($this->_socket, 1))
{
return null;
}
// Calculate port value
$port = ord($byte1) * 256 + ord($byte2);
// Validate IPv6 result
if (
false !== strpos($host, '.') || // filter_var not always works with mixed IPv6
false === filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) ||
false === filter_var($port, FILTER_VALIDATE_INT)
)
{
continue;
}
$servers["[{$host}]:{$port}"] = // keep unique
[
'host' => $host,
'port' => $port
];
}
return $servers;
}
}
Loading…
Cancel
Save