diff --git a/src/GameQ/Protocols/Rust.php b/src/GameQ/Protocols/Rust.php index 356cc19f..dfbc45f7 100644 --- a/src/GameQ/Protocols/Rust.php +++ b/src/GameQ/Protocols/Rust.php @@ -25,9 +25,81 @@ * * @package GameQ\Protocols * @author Austin Bischoff + * @author Nikolay Ipanyuk */ class Rust extends Source { + /** + * Server keywords + * + * mp - Max players + * cp - Current players + * qp - Queue players + * born - Time to create a new save / Wipe time (unixtime) + * pt - Protocol type (rak - RakNet, sw - SteamNetworking) + * h - Hash Assembly-CSharp.dll + * v - Protocol version + * cs - Build version + * st - Status server (ok - Normal work, rst - Server restarting) + * gm - Game mode + * oxide - Oxide/uMod (https://umod.org/) + * carbon - Carbon (https://carbonmod.gg/) + * modded - Modded flag + * + * @type array + */ + private $server_keywords = [ + 'mp', + 'cp', + 'qp', + 'born', + 'pt', + 'h', + 'v', + 'cs', + 'st', + 'gm', + 'oxide', + 'carbon', + 'modded' + ]; + + /** + * Server tags (https://wiki.facepunch.com/rust/server-browser-tags) + * + * @type array + */ + private $server_tags = [ + 'monthly', + 'biweekly', + 'weekly', + 'vanilla', + 'hardcore', + 'softcore', + 'pve', + 'roleplay', + 'creative', + 'minigame', + 'training', + 'battlefield', + 'broyale', + 'builds' + ]; + + /** + * Region tags (https://wiki.facepunch.com/rust/server-browser-tags) + * + * @type array + */ + private $region_tags = [ + 'na', + 'sa', + 'eu', + 'wa', + 'ea', + 'oc', + 'af' + ]; /** * String name of this protocol class @@ -42,23 +114,70 @@ class Rust extends Source * @type string */ protected $name_long = "Rust"; - + /** - * Overload so we can get max players from mp of keywords and num players from cp keyword + * Processing of server tags and more correct indication of the current number of players and the maximum number of players * * @param Buffer $buffer */ protected function processDetails(Buffer $buffer) { $results = parent::processDetails($buffer); - - if ($results['keywords']) { - //get max players from mp of keywords and num players from cp keyword - preg_match_all('/(mp|cp)([\d]+)/', $results['keywords'], $matches); - $results['max_players'] = intval($matches[2][0]); - $results['num_players'] = intval($matches[2][1]); + if (isset($results['keywords']) and strlen($results['keywords']) > 0) { + $keywords = explode(',', $results['keywords']); + if (sizeof($keywords) > 0) { + $results = array_merge($results, $this->parseKeywords($keywords)); + foreach (['cp' => 'num_players', 'mp' => 'max_players'] as $keyword => $key) { + if (isset($results['server.keywords'][$keyword])) { + $results[$key] = intval($results['server.keywords'][$keyword]); + } + } + } } return $results; } + + /** + * Parse keywords + * + * @param array $keywords + */ + protected function parseKeywords(array $keywords = []) + { + $result = [ + 'server.keywords' => [], + 'unhandled.tags' => [], + 'server.tags' => [] + ]; + + foreach ($keywords as $gametag) { + $parsed = false; + $gametag = trim(mb_strtolower($gametag)); + if (in_array($gametag, $this->server_tags)) { + $parsed = true; + $result['server.tags'][] = $gametag; + } elseif (in_array($gametag, $this->region_tags)) { + $parsed = true; + $result['region'] = mb_strtoupper($gametag); + } else { + foreach ($this->server_keywords as $server_keyword) { + if (strpos($gametag, $server_keyword) === 0) { + $parsed = true; + if ($gametag == $server_keyword) { + $result['server.keywords'][$gametag] = true; + } else { + $result['server.keywords'][$server_keyword] = mb_substr($gametag, mb_strlen($server_keyword)); + } + } + } + } + + if (!$parsed) { + $result['unhandled.tags'][] = $gametag; + } + } + + return $result; + } }