Skip to content

Commit

Permalink
Add AzLink support for Steam games
Browse files Browse the repository at this point in the history
  • Loading branch information
MrMicky-FR committed Aug 30, 2022
1 parent bf6371f commit 4fc6c37
Show file tree
Hide file tree
Showing 14 changed files with 155 additions and 70 deletions.
6 changes: 5 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@

Azuriom follows the [PSR-12 coding style](https://www.php-fig.org/psr/psr-12/).

You can also run [PHP-CS-Fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer) to automatically fix the code style.
[Laravel Pint](https://github.com/laravel/pint) is included in the Composer dev-dependencies,
and can be used to automatically fix code style issues with this command:
```
./vendor/bin/pint
```

## Manual installation for development

Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@

Azuriom natively supports the following games:
* [Minecraft](https://www.minecraft.net/)
* [Garry's Mod](https://store.steampowered.com/app/4000/Garrys_Mod/)
* [ARK: Survival Evolved](https://store.steampowered.com/app/346110/ARK_Survival_Evolved/)
* [Rust](https://store.steampowered.com/agecheck/app/252490/)
* [Garry's Mod](https://gmod.facepunch.com/)
* [ARK: Survival Evolved](https://playark.com/ark-survival-evolved/)
* [Rust](https://rust.facepunch.com/)
* [FiveM](https://fivem.net/)
* [Counter-Strike: Global Offensive](https://store.steampowered.com/app/730/CounterStrike_Global_Offensive/)
* [Team Fortress 2](https://store.steampowered.com/app/440/Team_Fortress_2/)
* [Counter-Strike: Global Offensive](https://blog.counter-strike.net/)
* [Team Fortress 2](https://www.teamfortress.com/)

You can implement your own game like it was done for [Flyff](https://github.com/AzuriomCommunity/Game-Flyff) or [Dofus 1.29](https://github.com/Javdu10/Game-Dofus129). You can find the how-to in [this documentation](https://azuriom.com/en/docs/games)
## Documentation
Expand Down
2 changes: 1 addition & 1 deletion app/Games/Minecraft/Servers/AzLink.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public function sendCommands(array $commands, User $user, bool $needConnected =
foreach ($commands as $command) {
$this->server->commands()->create([
'command' => $command,
'user_id' => $user?->id,
'user_id' => $user->id,
'need_online' => $needConnected,
]);
}
Expand Down
40 changes: 40 additions & 0 deletions app/Games/Steam/Servers/AzLink.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Azuriom\Games\Steam\Servers;

use Azuriom\Games\ServerBridge;
use Azuriom\Models\User;

class AzLink extends ServerBridge
{
public function getServerData()
{
return null;
}

public function verifyLink()
{
return true;
}

public function sendCommands(array $commands, User $user, bool $needConnected = false)
{
foreach ($commands as $command) {
$this->server->commands()->create([
'command' => $command,
'user_id' => $user->id,
'need_online' => $needConnected,
]);
}
}

public function canExecuteCommand()
{
return true;
}

public function getDefaultPort()
{
return Query::DEFAULT_PORT;
}
}
2 changes: 1 addition & 1 deletion app/Games/Steam/Servers/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

class Query extends ServerBridge
{
protected const DEFAULT_PORT = 27015;
public const DEFAULT_PORT = 27015;

protected $engine = SourceQuery::SOURCE;

Expand Down
31 changes: 15 additions & 16 deletions app/Games/Steam/SteamGame.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Azuriom\Games\Steam;

use Azuriom\Games\Game;
use Azuriom\Games\Steam\Servers\AzLink;
use Azuriom\Games\Steam\Servers\Query;
use Azuriom\Games\Steam\Servers\Rcon;
use Azuriom\Models\User;
Expand All @@ -14,35 +15,29 @@ class SteamGame extends Game
{
protected const USER_INFO_URL = 'https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002';

/**
* The game's name.
*
* @var string
*/
protected $name;
protected string $name;

/**
* The game's id.
*
* @var string
*/
protected $id;
protected string $id;

protected bool $azLinkSupport;

/**
* Create a new game instance.
*
* @param string $id
* @param string $name
* @param bool $azLinkSupport
*/
protected function __construct(string $id, string $name)
protected function __construct(string $id, string $name, bool $azLinkSupport)
{
$this->id = $id;
$this->name = $name;
$this->azLinkSupport = $azLinkSupport;
}

public static function forName(string $id, string $name)
public static function forName(string $id, string $name, bool $azLink = false)
{
return new self($id, $name);
return new self($id, $name, $azLink);
}

public function id()
Expand Down Expand Up @@ -74,10 +69,14 @@ public function getUserName(User $user)

public function getSupportedServers()
{
return [
$games = [
'source-query' => Query::class,
'source-rcon' => Rcon::class,
];

return $this->azLinkSupport
? array_merge($games, ['steam-azlink' => AzLink::class])
: $games;
}

public function loginWithOAuth()
Expand Down
8 changes: 3 additions & 5 deletions app/Http/Controllers/Admin/ThemeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -189,11 +189,9 @@ public function config(Request $request, string $theme)
return response()->json(['message' => 'admin.themes.config_updated']);
}

return redirect()->route('admin.themes.index')->with(
'success',
trans('admin.themes.config_updated')
);
} catch (FileNotFoundException $e) {
return redirect()->route('admin.themes.config', $theme)
->with('success', trans('admin.themes.config_updated'));
} catch (FileNotFoundException) {
return redirect()->back()->with('error', 'Invalid theme configuration.');
}
}
Expand Down
75 changes: 48 additions & 27 deletions app/Http/Controllers/Api/ServerController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Azuriom\Http\Controllers\Api;

use Azuriom\Games\Steam\SteamID;
use Azuriom\Http\Controllers\Controller;
use Azuriom\Models\Role;
use Azuriom\Models\Server;
Expand All @@ -22,48 +23,45 @@ public function status()
public function fetch(Request $request)
{
$server = Server::find($request->input('server-id'));
$players = Arr::pluck($request->json('players', []), 'name', 'uuid');
$cpuUsage = $request->json('system.cpu');
$ramUsage = $request->json('system.ram');
$tps = $request->json('worlds.tps');

$server->updateData([
'players' => count($players),
'max_players' => $request->json('maxPlayers'),
'cpu' => $cpuUsage >= 0 ? $cpuUsage : null,
'ram' => $ramUsage >= 0 ? (int) $ramUsage : null,
'tps' => $tps >= 0 ? round($tps, 2) : null,
'loaded_chunks' => $request->json('worlds.chunks'),
'entities' => $request->json('worlds.entities'),
], $request->json('full', false));

$users = User::whereIn('name', $players)->get();
$uidKey = $request->json('platform.type') === 'GMOD';
$rawPlayers = $request->json('players', []);
$maxPlayers = $request->json('maxPlayers');

$players = $uidKey
? Arr::pluck($rawPlayers, 'name', 'uuid')
: Arr::pluck($rawPlayers, 'uid');

$server->updateData(array_merge(
['players' => count($players), 'max_players' => $maxPlayers],
$request->json('system', []),
$request->json('worlds', []),
), $request->json('full', false));

$users = User::whereIn($uidKey ? 'game_id' : 'name', $players)->get();
$commands = $server->commands()
->with('user')
->whereIn('user_id', $users->modelKeys())
->orWhere('need_online', false)
->limit(100)
->get();
$usersData = $users->map(fn (User $user) => [
'id' => $user->id,
'name' => $user->name,
'uid' => $user->game_id,
'money' => $user->money,
]);

if (! $commands->isEmpty()) {
ServerCommand::whereIn('id', $commands->modelKeys())->delete();

$commands = $commands->groupBy('user.name')
->map(function (Collection $serverCommands) {
return $serverCommands->pluck('command');
});
$commands = $uidKey
? $this->mapCommands($commands)
: $this->mapLegacyCommands($commands);
}

return response()->json([
'commands' => $commands,
'users' => $usersData,
'retry' => $commands->count() > 100,
'users' => $users->map(fn (User $user) => [
'id' => $user->id,
'name' => $user->name,
'uid' => $user->game_id,
'money' => $user->money,
]),
]);
}

Expand Down Expand Up @@ -110,4 +108,27 @@ public function updateEmail(Request $request)

return response()->noContent();
}

protected function mapLegacyCommands(Collection $commands)
{
return $commands->groupBy('user.name')
->map(function (Collection $serverCommands) {
return $serverCommands->pluck('command');
});
}

protected function mapCommands(Collection $commands)
{
return $commands->groupBy('user.name')
->map(function (Collection $serverCommands) {
$user = $serverCommands->first()->user;

return [
'name' => $user->name,
'uid' => $user->game_id,
'steamid_32' => SteamID::convertTo32($user->game_id),
'values' => $serverCommands->pluck('command'),
];
});
}
}
29 changes: 23 additions & 6 deletions app/Models/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,27 @@ public function updateData(array $data = null, bool $full = false)
{
Cache::put('servers.'.$this->id, $data, now()->addMinutes(5));

if ($data !== null && $full && ! $this->stats()->where('created_at', '>=', now()->subMinutes(10))->exists()) {
$stats = Arr::except($data, 'max_players');
$statsData = ['data' => array_filter(Arr::except($stats, ['players', 'cpu', 'ram']))];
if ($data === null || ! $full) {
return;
}

if ($this->stats()->where('created_at', '>=', now()->subMinutes(10))->exists()) {
return;
}

$stats = Arr::except($data, 'max_players');
$basicStats = Arr::only($stats, ['players', 'cpu', 'ram']);
$statsData = array_filter(Arr::except($stats, ['players', 'cpu', 'ram']));

$this->stats()->create(array_merge(Arr::only($stats, ['players', 'cpu', 'ram']), $statsData));
if (Arr::get($basicStats, 'cpu', 0) < 0) {
$basicStats['cpu'] = null;
}

if (is_numeric($tps = Arr::get($statsData, 'tps', 0))) {
$statsData['tps'] = round($tps, 2);
}

$this->stats()->create(array_merge($basicStats, ['data' => $statsData]));
}

public function getData(string $key = null)
Expand Down Expand Up @@ -159,7 +174,9 @@ public function bridge()

public function getLinkCommand()
{
return '/azlink setup '.url('/').' '.$this->token;
return $this->type === 'mc-azlink'
? '/azlink setup '.url('/').' '.$this->token
: 'azlink:setup '.str_replace(':', '!', url('/')).' '.$this->token;
}

public static function types()
Expand Down Expand Up @@ -190,6 +207,6 @@ public function scopeExecutable(Builder $query)
*/
public function scopePingable(Builder $query)
{
return $query->where('type', '<>', 'mc-azlink');
return $query->whereNotIn('type', ['mc-azlink', 'steam-azlink']);
}
}
2 changes: 1 addition & 1 deletion app/Providers/GameServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public function register()
'mc-online' => MinecraftOnlineGame::class,
'mc-offline' => MinecraftOfflineGame::class,
'mc-bedrock' => MinecraftBedrockGame::class,
'gmod' => SteamGame::forName('gmod', 'Garry\'s Mod'),
'gmod' => SteamGame::forName('gmod', 'Garry\'s Mod', true),
'ark' => SteamGame::forName('ark', 'ARK'),
'rust' => RustGame::class,
'fivem' => FiveMGame::class,
Expand Down
1 change: 1 addition & 0 deletions resources/lang/en/admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@
'mc-azlink' => 'AzLink',
'source-query' => 'Source Query',
'source-rcon' => 'Source RCON',
'steam-azlink' => 'AzLink',
'bedrock-ping' => 'Bedrock Ping',
'bedrock-rcon' => 'Bedrock RCON',
'fivem-status' => 'FiveM status',
Expand Down
1 change: 1 addition & 0 deletions resources/lang/fr/admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@
'mc-azlink' => 'AzLink',
'source-query' => 'Source Query',
'source-rcon' => 'RCON Source',
'steam-azlink' => 'AzLink',
'bedrock-ping' => 'Ping Bedrock',
'bedrock-rcon' => 'RCON Bedrock',
'fivem-status' => 'Statut FiveM',
Expand Down
Loading

0 comments on commit 4fc6c37

Please sign in to comment.