et-nik /
gameap
| 1 | <?php |
||||
| 2 | |||||
| 3 | namespace Gameap\Services; |
||||
| 4 | |||||
| 5 | use Gameap\Exceptions\Services\EmptyCommandException; |
||||
| 6 | use Gameap\Exceptions\Services\InvalidCommandException; |
||||
| 7 | use Gameap\Exceptions\Services\ServerInactiveException; |
||||
| 8 | use Gameap\Models\Server; |
||||
| 9 | use GameQ\Exception\Protocol as GameqProtocolException; |
||||
| 10 | use GameQ\Exception\Query as GameqQueryException; |
||||
| 11 | use GameQ\Exception\Server as GameqServerException; |
||||
| 12 | use GameQ\GameQ; |
||||
| 13 | use Knik\Gameap\GdaemonCommands; |
||||
| 14 | use Storage; |
||||
| 15 | |||||
| 16 | class ServerService |
||||
| 17 | { |
||||
| 18 | public const CONSOLE_MAX_SYMBOLS = 10000; |
||||
| 19 | |||||
| 20 | /** |
||||
| 21 | * @var GameQ |
||||
| 22 | */ |
||||
| 23 | protected $gameq; |
||||
| 24 | |||||
| 25 | /** |
||||
| 26 | * @var GdaemonCommands |
||||
| 27 | */ |
||||
| 28 | protected $gdaemonCommands; |
||||
| 29 | |||||
| 30 | /** |
||||
| 31 | * @var string |
||||
| 32 | */ |
||||
| 33 | protected $storageDisk = 'local'; |
||||
| 34 | |||||
| 35 | /** |
||||
| 36 | * ServerService constructor. |
||||
| 37 | * |
||||
| 38 | * @param GameQ $gameq |
||||
| 39 | * @param GdaemonCommands $gdaemonCommands |
||||
| 40 | */ |
||||
| 41 | public function __construct(GameQ $gameq, GdaemonCommands $gdaemonCommands) |
||||
| 42 | 3 | { |
|||
| 43 | $this->gameq = $gameq; |
||||
| 44 | 3 | $this->gdaemonCommands = $gdaemonCommands; |
|||
| 45 | 3 | } |
|||
| 46 | 3 | ||||
| 47 | /** |
||||
| 48 | * Add default server disk |
||||
| 49 | * |
||||
| 50 | * @param Server $server |
||||
| 51 | */ |
||||
| 52 | public function registerDisk(Server $server): void |
||||
| 53 | { |
||||
| 54 | foreach ($server->file_manager_disks as $diskName => $diskConfig) { |
||||
| 55 | if (empty(config("filesystems.disks.{$diskName}"))) { |
||||
| 56 | config(["filesystems.disks.{$diskName}" => $diskConfig]); |
||||
| 57 | } |
||||
| 58 | } |
||||
| 59 | } |
||||
| 60 | |||||
| 61 | /** |
||||
| 62 | * @param Server $server |
||||
| 63 | * @return array|string[] |
||||
| 64 | * @throws \Exception |
||||
| 65 | */ |
||||
| 66 | public function query(Server $server): array |
||||
| 67 | 6 | { |
|||
| 68 | $host = "{$server->server_ip}:{$server->query_port}"; |
||||
| 69 | 6 | ||||
| 70 | try { |
||||
| 71 | $query = $this->gameq->setOption('timeout', 5) |
||||
| 72 | 6 | ->addServer([ |
|||
| 73 | 6 | 'type' => $server->game->engine, |
|||
| 74 | 6 | 'host' => $host, |
|||
| 75 | 6 | ]) |
|||
| 76 | ->process(); |
||||
| 77 | 6 | } catch (GameqServerException | GameqQueryException | GameqProtocolException $exception) { |
|||
| 78 | return [ |
||||
| 79 | 'status' => 'query not supported for this game', |
||||
| 80 | ]; |
||||
| 81 | } |
||||
| 82 | |||||
| 83 | |||||
| 84 | $serverResult = $query[$host] ?? null; |
||||
| 85 | 6 | ||||
| 86 | if (!empty($serverResult['gq_online'])) { |
||||
| 87 | 6 | $result = [ |
|||
| 88 | 'status' => ($serverResult['gq_online'] ?? null) ? 'online' : 'offline', |
||||
| 89 | 3 | 'hostname' => $serverResult['gq_hostname'] ?? null, |
|||
| 90 | 3 | 'map' => $serverResult['gq_mapname'] ?? null, |
|||
| 91 | 3 | 'players' => ($serverResult['gq_numplayers'] ?? 0) . '/' . ($serverResult['gq_maxplayers'] ?? 0), |
|||
| 92 | 3 | 'version' => $serverResult['version'] ?? null, |
|||
| 93 | 3 | 'password' => ($serverResult['gq_password'] ?? null) ? 'yes' : 'no', |
|||
| 94 | 3 | 'joinlink' => $serverResult['gq_joinlink'] ?? null, |
|||
| 95 | 3 | ]; |
|||
| 96 | } else { |
||||
| 97 | $result = [ |
||||
| 98 | 'status' => 'offline', |
||||
| 99 | 6 | ]; |
|||
| 100 | } |
||||
| 101 | |||||
| 102 | return $result; |
||||
| 103 | 6 | } |
|||
| 104 | |||||
| 105 | /** |
||||
| 106 | * @param Server $server |
||||
| 107 | * @param string $command |
||||
| 108 | * @param array $extraData |
||||
| 109 | * @return string |
||||
| 110 | */ |
||||
| 111 | public function replaceShortCodes(Server $server, string $command, array $extraData = []): string |
||||
| 112 | 15 | { |
|||
| 113 | foreach ($extraData as $key => $value) { |
||||
| 114 | 15 | $command = str_replace('{' . $key . '}', $value, $command); |
|||
| 115 | 9 | } |
|||
| 116 | |||||
| 117 | $replaceArray = [ |
||||
| 118 | 'node_work_path' => $server->dedicatedServer->work_path, |
||||
| 119 | 15 | 'node_tools_path' => $server->dedicatedServer->work_path . "/tools", |
|||
| 120 | 15 | 'host' => $server->server_ip, |
|||
| 121 | 15 | 'port' => $server->server_port, |
|||
| 122 | 15 | 'query_port' => $server->query_port, |
|||
| 123 | 15 | 'rcon_port' => $server->rcon_port, |
|||
| 124 | 15 | 'dir' => $server->full_path, |
|||
| 125 | 15 | 'id' => $server->id, |
|||
| 126 | 15 | 'uuid' => $server->uuid, |
|||
| 127 | 15 | 'uuid_short' => $server->uuid_short, |
|||
| 128 | 'game' => $server->game_id, |
||||
| 129 | 'user' => $server->su_user, |
||||
| 130 | 15 | ]; |
|||
| 131 | 15 | ||||
| 132 | foreach ($replaceArray as $key => $value) { |
||||
| 133 | $command = str_replace('{' . $key . '}', $value, $command); |
||||
| 134 | 15 | } |
|||
| 135 | |||||
| 136 | return $command; |
||||
| 137 | } |
||||
| 138 | |||||
| 139 | /** |
||||
| 140 | * @param Server $server |
||||
| 141 | * @param string $command |
||||
| 142 | * @param array $extraData |
||||
| 143 | * @return string |
||||
| 144 | * |
||||
| 145 | * @throws InvalidCommandException |
||||
| 146 | 15 | * @throws EmptyCommandException |
|||
| 147 | */ |
||||
| 148 | 15 | public function getCommand(Server $server, string $command, array $extraData = []): string |
|||
| 149 | 15 | { |
|||
| 150 | $property = 'script_' . $command; |
||||
| 151 | 15 | $attributes = $server->dedicatedServer->getAttributes(); |
|||
| 152 | 12 | ||||
| 153 | if (array_key_exists($property, $attributes)) { |
||||
| 154 | 12 | $script = $server->dedicatedServer->getAttribute($property); |
|||
| 155 | |||||
| 156 | if (empty($script)) { |
||||
| 157 | throw new EmptyCommandException(); |
||||
| 158 | 12 | } |
|||
| 159 | |||||
| 160 | return $this->replaceShortCodes($server, $script, $extraData); |
||||
| 161 | 3 | } |
|||
| 162 | |||||
| 163 | throw new InvalidCommandException(); |
||||
| 164 | } |
||||
| 165 | |||||
| 166 | /** |
||||
| 167 | * @param Server $server |
||||
| 168 | 6 | * @return string |
|||
| 169 | * @throws ServerInactiveException|InvalidCommandException |
||||
| 170 | 6 | */ |
|||
| 171 | 3 | public function getConsoleLog(Server $server): string |
|||
| 172 | { |
||||
| 173 | $this->checkServer($server); |
||||
| 174 | 3 | $this->configureGdaemon($server); |
|||
| 175 | 3 | ||||
| 176 | try { |
||||
| 177 | $command = $this->getCommand($server, 'get_console'); |
||||
| 178 | $result = $this->gdaemonCommands->exec($command, $exitCode); |
||||
| 179 | } catch (EmptyCommandException $e) { |
||||
| 180 | $this->registerDisk($server); |
||||
| 181 | 3 | $result = Storage::disk('server')->get('output.txt'); |
|||
| 182 | } |
||||
| 183 | |||||
| 184 | if (mb_strlen($result) > self::CONSOLE_MAX_SYMBOLS) { |
||||
| 185 | $result = mb_substr($result, mb_strlen($result) - self::CONSOLE_MAX_SYMBOLS, self::CONSOLE_MAX_SYMBOLS); |
||||
| 186 | } |
||||
| 187 | 3 | ||||
| 188 | // Fix |
||||
| 189 | 3 | // Malformed UTF-8 characters, possibly incorrectly encoded |
|||
| 190 | $result = mb_convert_encoding($result, 'UTF-8', 'UTF-8'); |
||||
| 191 | |||||
| 192 | return $result; |
||||
|
0 ignored issues
–
show
Bug
Best Practice
introduced
by
Loading history...
|
|||||
| 193 | } |
||||
| 194 | |||||
| 195 | /** |
||||
| 196 | * @param Server $server |
||||
| 197 | 9 | * @param string $command |
|||
| 198 | * @return bool |
||||
| 199 | 9 | * |
|||
| 200 | 6 | * @throws InvalidCommandException |
|||
| 201 | * @throws ServerInactiveException |
||||
| 202 | */ |
||||
| 203 | 6 | public function sendConsoleCommand(Server $server, string $command): bool |
|||
| 204 | 6 | { |
|||
| 205 | if ($server->processActive() === false) { |
||||
| 206 | throw new ServerInactiveException('Server is down'); |
||||
| 207 | } |
||||
| 208 | |||||
| 209 | $this->configureGdaemon($server); |
||||
| 210 | |||||
| 211 | try { |
||||
| 212 | $command = $this->getCommand($server, 'send_command', ['command' => $command]); |
||||
| 213 | $this->gdaemonCommands->exec($command, $exitCode); |
||||
| 214 | } catch (EmptyCommandException $e) { |
||||
| 215 | $this->registerDisk($server); |
||||
| 216 | |||||
| 217 | 6 | if (Storage::disk('server')->put('input.txt', $command)) { |
|||
| 218 | // Success |
||||
| 219 | $exitCode = 0; |
||||
| 220 | } else { |
||||
| 221 | // Failure |
||||
| 222 | $exitCode = 1; |
||||
| 223 | } |
||||
| 224 | } |
||||
| 225 | 9 | ||||
| 226 | return $exitCode === 0; |
||||
| 227 | 9 | } |
|||
| 228 | 9 | ||||
| 229 | /** |
||||
| 230 | 9 | * Setting up gdaemon commands configuration |
|||
| 231 | * |
||||
| 232 | * @param Server $server |
||||
| 233 | */ |
||||
| 234 | private function configureGdaemon(Server $server): void |
||||
| 235 | { |
||||
| 236 | 15 | $this->gdaemonCommands->setConfig( |
|||
| 237 | $server->dedicatedServer->gdaemonSettings($this->storageDisk) |
||||
| 238 | 15 | ); |
|||
| 239 | 6 | } |
|||
| 240 | |||||
| 241 | 9 | /** |
|||
| 242 | * @param Server $server |
||||
| 243 | * @throws ServerInactiveException |
||||
| 244 | */ |
||||
| 245 | private function checkServer(Server $server): void |
||||
|
0 ignored issues
–
show
The parameter
$server is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. Loading history...
|
|||||
| 246 | { |
||||
| 247 | // There is no checkers for server status |
||||
| 248 | } |
||||
| 249 | } |
||||
| 250 |