Browse Source

implement basic features

main
ghost 6 months ago
parent
commit
2071796a07
  1. 14
      .env
  2. 5
      .gitignore
  3. 9
      assets/app.js
  4. 5
      assets/bootstrap.js
  5. 15
      assets/controllers.json
  6. 16
      assets/controllers/hello_controller.js
  7. 3
      assets/styles/app.css
  8. 10
      composer.json
  9. 294
      composer.lock
  10. 5
      config/packages/asset_mapper.yaml
  11. 6
      config/packages/twig.yaml
  12. 5
      config/services.yaml
  13. 30
      importmap.php
  14. 124
      public/css/default.css
  15. 86
      src/Controller/MainController.php
  16. 15
      symfony.lock
  17. 17
      templates/base.html.twig
  18. 38
      templates/default/layout.html.twig
  19. 57
      templates/default/main/index.html.twig

14
.env

@ -43,12 +43,14 @@ MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
# HLState # HLState
# Application version, used for API and media cache # Application version, used for API and media cache
APP_VERSION=1.0.0 APP_VERSION="1.0.0"
# Application name # Application name
APP_NAME=HLState APP_NAME="HLState"
# Game server # Application template
APP_SERVER_HOST=localhost APP_THEME="default"
APP_SERVER_PORT=27015
APP_SERVER_TIMEOUT=3 # Servers registry, URL or filepath
# https://github.com/YGGverse/HLServers
APP_HLSERVERS="https://raw.githubusercontent.com/YGGverse/HLServers/main/config.json"

5
.gitignore vendored

@ -17,8 +17,3 @@
.phpunit.result.cache .phpunit.result.cache
/phpunit.xml /phpunit.xml
###< symfony/phpunit-bridge ### ###< symfony/phpunit-bridge ###
###> symfony/asset-mapper ###
/public/assets/
/assets/vendor
###< symfony/asset-mapper ###

9
assets/app.js

@ -1,9 +0,0 @@
/*
* Welcome to your app's main JavaScript file!
*
* This file will be included onto the page via the importmap() Twig function,
* which should already be in your base.html.twig.
*/
import './styles/app.css'
console.log('This log comes from assets/app.js - welcome to AssetMapper! 🎉')

5
assets/bootstrap.js vendored

@ -1,5 +0,0 @@
import { startStimulusApp } from '@symfony/stimulus-bundle';
const app = startStimulusApp();
// register any custom, 3rd party controllers here
// app.register('some_controller_name', SomeImportedController);

15
assets/controllers.json

@ -1,15 +0,0 @@
{
"controllers": {
"@symfony/ux-turbo": {
"turbo-core": {
"enabled": true,
"fetch": "eager"
},
"mercure-turbo-stream": {
"enabled": false,
"fetch": "eager"
}
}
},
"entrypoints": []
}

16
assets/controllers/hello_controller.js

@ -1,16 +0,0 @@
import { Controller } from '@hotwired/stimulus';
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="hello" attribute will cause
* this controller to be executed. The name "hello" comes from the filename:
* hello_controller.js -> "hello"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js';
}
}

3
assets/styles/app.css

@ -1,3 +0,0 @@
body {
background-color: skyblue;
}

10
composer.json

@ -14,8 +14,6 @@
"doctrine/orm": "^2.17", "doctrine/orm": "^2.17",
"phpdocumentor/reflection-docblock": "^5.3", "phpdocumentor/reflection-docblock": "^5.3",
"phpstan/phpdoc-parser": "^1.25", "phpstan/phpdoc-parser": "^1.25",
"symfony/asset": "7.0.*",
"symfony/asset-mapper": "7.0.*",
"symfony/console": "7.0.*", "symfony/console": "7.0.*",
"symfony/doctrine-messenger": "7.0.*", "symfony/doctrine-messenger": "7.0.*",
"symfony/dotenv": "7.0.*", "symfony/dotenv": "7.0.*",
@ -43,8 +41,9 @@
"symfony/validator": "7.0.*", "symfony/validator": "7.0.*",
"symfony/web-link": "7.0.*", "symfony/web-link": "7.0.*",
"symfony/yaml": "7.0.*", "symfony/yaml": "7.0.*",
"twig/extra-bundle": "^2.12|^3.0", "twig/extra-bundle": "^3.8",
"twig/twig": "^2.12|^3.0", "twig/intl-extra": "^3.8",
"twig/twig": "^3.8",
"xpaw/php-source-query-class": "^2.1" "xpaw/php-source-query-class": "^2.1"
}, },
"config": { "config": {
@ -78,8 +77,7 @@
"scripts": { "scripts": {
"auto-scripts": { "auto-scripts": {
"cache:clear": "symfony-cmd", "cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd", "assets:install %PUBLIC_DIR%": "symfony-cmd"
"importmap:install": "symfony-cmd"
}, },
"post-install-cmd": [ "post-install-cmd": [
"@auto-scripts" "@auto-scripts"

294
composer.lock generated

@ -4,89 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "66ab47b04c6a49df812afba2a57a75bc", "content-hash": "b88a8a873f067191119676f1b8833846",
"packages": [ "packages": [
{
"name": "composer/semver",
"version": "3.4.0",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "35e8d0af4486141bc745f23a29cc2091eb624a32"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32",
"reference": "35e8d0af4486141bc745f23a29cc2091eb624a32",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0 || ^8.0"
},
"require-dev": {
"phpstan/phpstan": "^1.4",
"symfony/phpunit-bridge": "^4.2 || ^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Semver\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nils Adermann",
"email": "naderman@naderman.de",
"homepage": "http://www.naderman.de"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
},
{
"name": "Rob Bast",
"email": "rob.bast@gmail.com",
"homepage": "http://robbast.nl"
}
],
"description": "Semver library that offers utilities, version constraint parsing and validation.",
"keywords": [
"semantic",
"semver",
"validation",
"versioning"
],
"support": {
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/semver/issues",
"source": "https://github.com/composer/semver/tree/3.4.0"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2023-08-31T09:50:34+00:00"
},
{ {
"name": "doctrine/cache", "name": "doctrine/cache",
"version": "2.2.0", "version": "2.2.0",
@ -2099,153 +2018,6 @@
}, },
"time": "2021-07-14T16:46:02+00:00" "time": "2021-07-14T16:46:02+00:00"
}, },
{
"name": "symfony/asset",
"version": "v7.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/asset.git",
"reference": "82cd3961bc7fc1b3c3f85e8f2b9a287a1dfd6f2f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/asset/zipball/82cd3961bc7fc1b3c3f85e8f2b9a287a1dfd6f2f",
"reference": "82cd3961bc7fc1b3c3f85e8f2b9a287a1dfd6f2f",
"shasum": ""
},
"require": {
"php": ">=8.2"
},
"conflict": {
"symfony/http-foundation": "<6.4"
},
"require-dev": {
"symfony/http-client": "^6.4|^7.0",
"symfony/http-foundation": "^6.4|^7.0",
"symfony/http-kernel": "^6.4|^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Asset\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/asset/tree/v7.0.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2023-10-31T17:59:56+00:00"
},
{
"name": "symfony/asset-mapper",
"version": "v7.0.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/asset-mapper.git",
"reference": "e4e3a98dc279cb0d266f50c7c73bd42cb9c3a0c3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/asset-mapper/zipball/e4e3a98dc279cb0d266f50c7c73bd42cb9c3a0c3",
"reference": "e4e3a98dc279cb0d266f50c7c73bd42cb9c3a0c3",
"shasum": ""
},
"require": {
"composer/semver": "^3.0",
"php": ">=8.2",
"symfony/filesystem": "^6.4|^7.0",
"symfony/http-client": "^6.4|^7.0"
},
"conflict": {
"symfony/framework-bundle": "<6.4"
},
"require-dev": {
"symfony/asset": "^6.4|^7.0",
"symfony/browser-kit": "^6.4|^7.0",
"symfony/console": "^6.4|^7.0",
"symfony/event-dispatcher-contracts": "^3.0",
"symfony/finder": "^6.4|^7.0",
"symfony/framework-bundle": "^6.4|^7.0",
"symfony/http-foundation": "^6.4|^7.0",
"symfony/http-kernel": "^6.4|^7.0",
"symfony/web-link": "^6.4|^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\AssetMapper\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Maps directories of assets & makes them available in a public directory with versioned filenames.",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/asset-mapper/tree/v7.0.2"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2023-12-27T08:42:13+00:00"
},
{ {
"name": "symfony/cache", "name": "symfony/cache",
"version": "v7.0.2", "version": "v7.0.2",
@ -7417,6 +7189,70 @@
], ],
"time": "2023-11-21T14:02:01+00:00" "time": "2023-11-21T14:02:01+00:00"
}, },
{
"name": "twig/intl-extra",
"version": "v3.8.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/intl-extra.git",
"reference": "7b3db67c700735f473a265a97e1adaeba3e6ca0c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/intl-extra/zipball/7b3db67c700735f473a265a97e1adaeba3e6ca0c",
"reference": "7b3db67c700735f473a265a97e1adaeba3e6ca0c",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/intl": "^5.4|^6.0|^7.0",
"twig/twig": "^3.0"
},
"require-dev": {
"symfony/phpunit-bridge": "^6.4|^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Twig\\Extra\\Intl\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
}
],
"description": "A Twig extension for Intl",
"homepage": "https://twig.symfony.com",
"keywords": [
"intl",
"twig"
],
"support": {
"source": "https://github.com/twigphp/intl-extra/tree/v3.8.0"
},
"funding": [
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/twig/twig",
"type": "tidelift"
}
],
"time": "2023-11-21T17:27:48+00:00"
},
{ {
"name": "twig/twig", "name": "twig/twig",
"version": "v3.8.0", "version": "v3.8.0",

5
config/packages/asset_mapper.yaml

@ -1,5 +0,0 @@
framework:
asset_mapper:
# The paths to make available to the asset mapper.
paths:
- assets/

6
config/packages/twig.yaml

@ -1,6 +1,10 @@
twig: twig:
default_path: '%kernel.project_dir%/templates' default_path: '%kernel.project_dir%/templates'
globals:
app:
version: '%app.version%'
name: '%app.name%'
theme: '%app.theme%'
when@test: when@test:
twig: twig:
strict_variables: true strict_variables: true

5
config/services.yaml

@ -6,9 +6,8 @@
parameters: parameters:
app.version: '%env(APP_VERSION)%' app.version: '%env(APP_VERSION)%'
app.name: '%env(APP_NAME)%' app.name: '%env(APP_NAME)%'
app.server.host: '%env(APP_SERVER_HOST)%' app.theme: '%env(APP_THEME)%'
app.server.port: '%env(APP_SERVER_PORT)%' app.hlservers: '%env(APP_HLSERVERS)%'
app.server.timeout: '%env(APP_SERVER_TIMEOUT)%'
services: services:
# default configuration for services in *this* file # default configuration for services in *this* file

30
importmap.php

@ -1,30 +0,0 @@
<?php
/**
* Returns the importmap for this application.
*
* - "path" is a path inside the asset mapper system. Use the
* "debug:asset-map" command to see the full list of paths.
*
* - "entrypoint" (JavaScript only) set to true for any module that will
* be used as an "entrypoint" (and passed to the importmap() Twig function).
*
* The "importmap:require" command can be used to add new entries to this file.
*
* This file has been auto-generated by the importmap commands.
*/
return [
'app' => [
'path' => './assets/app.js',
'entrypoint' => true,
],
'@hotwired/stimulus' => [
'version' => '3.2.2',
],
'@symfony/stimulus-bundle' => [
'path' => './vendor/symfony/stimulus-bundle/assets/dist/loader.js',
],
'@hotwired/turbo' => [
'version' => '7.3.0',
],
];

124
public/css/default.css

@ -0,0 +1,124 @@
*
{
/* apply defaults */
margin: 0;
padding: 0;
/* allow draw */
font-family: monospace;
/* adaptive */
color-scheme: light dark;
/* vars */
--container-max-width: 768px;
--color-warning: #ee784e;
--color-error: #ff6363;
--color-default: #999;
}
*::placeholder
{
font-size: 12px;
}
hr {
background-color: var(--color-default);
border: none;
color: var(--color-default);
height: 1px;
margin: 8px 0;
}
h1
{
font-size: 16px;
}
h2
{
font-size: 14px;
}
h3
{
font-size: 13px;
}
a, a:active, a:visited
{
color: var(--color-warning);
}
table
{
width: 100%;
border-collapse: collapse;
border: 1px solid var(--color-default);
}
table th,
table td
{
border: 1px solid var(--color-default);
padding: 4px;
}
header
{
display: block;
margin: 16px auto;
max-width: var(--container-max-width);
}
main
{
display: block;
margin: 16px auto;
max-width: var(--container-max-width);
}
footer
{
display: block;
margin: 16px auto;
max-width: var(--container-max-width);
}
/* framework */
.text-align-left
{
text-align: left;
}
.text-align-center
{
text-align: center;
}
.text-align-right
{
text-align: right;
}
.border-default
{
border: 1px var(--color-default) solid;
}
.padding-8-px
{
padding: 8px;
}
.padding-y-8-px
{
padding-bottom: 8px;
padding-top: 8px;
}
.margin-y-8-px
{
margin-bottom: 8px;
margin-top: 8px;
}

86
src/Controller/MainController.php

@ -0,0 +1,86 @@
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
class MainController extends AbstractController
{
#[Route(
'/',
name: 'main_index',
methods:
[
'GET'
]
)]
public function index(
?Request $request
): Response
{
// Get HLServers config
if ($hlservers = file_get_contents($this->getParameter('app.hlservers')))
{
$hlservers = json_decode($hlservers);
}
else
{
$hlservers = [];
}
// Collect servers info
$servers = [];
foreach ($hlservers as $hlserver)
{
try
{
$server = new \xPaw\SourceQuery\SourceQuery();
$server->Connect(
$hlserver->host,
$hlserver->port
);
if ($server->Ping())
{
if ($info = (array) $server->GetInfo())
{
$servers[] = [
'host' => $hlserver->host,
'port' => $hlserver->port,
'alias' => $hlserver->alias,
'info' => $info,
'online' => empty($info['Players']) ? [] : (array) $server->GetPlayers()
];
}
}
}
catch (Exception $error)
{
continue;
}
finally
{
$server->Disconnect();
}
}
return $this->render(
'default/main/index.html.twig',
[
'request' => $request,
'servers' => $servers
]
);
}
}

15
symfony.lock

@ -40,21 +40,6 @@
"tests/bootstrap.php" "tests/bootstrap.php"
] ]
}, },
"symfony/asset-mapper": {
"version": "7.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.4",
"ref": "8a0d17c04c791b3d7bdd083e1e2b2a53439dc3b0"
},
"files": [
"assets/app.js",
"assets/styles/app.css",
"config/packages/asset_mapper.yaml",
"importmap.php"
]
},
"symfony/console": { "symfony/console": {
"version": "7.0", "version": "7.0",
"recipe": { "recipe": {

17
templates/base.html.twig

@ -1,17 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫</text></svg>">
{% block stylesheets %}
{% endblock %}
{% block javascripts %}
{% block importmap %}{{ importmap('app') }}{% endblock %}
{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>

38
templates/default/layout.html.twig

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block head_title_content %}{{ app.name }}{% endblock %}</title>
<link rel="stylesheet" type="text/css" href="{{ url('main_index') }}css/default.css?{{ app.version }}"/>
</head>
<body>
{% block header_container %}
<header>
{% block header_content %}
<div class="text-align-right">
<strong>
{{ app.name }}
</strong>
</div>
{% endblock %}
</header>
{% endblock %}
{% block main_container %}
<main>
{% block main_content %}{% endblock %}
</main>
{% endblock %}
{% block footer_container %}
<footer>
{% block footer_content %}
<div class="text-align-right">
<small>
{{ 'Powered by' | trans }}
<a href="https://github.com/YGGverse/HLState" target="_blank">HLState</a>
</small>
</div>
{% endblock %}
</footer>
{% endblock %}
</body>
</html>

57
templates/default/main/index.html.twig

@ -0,0 +1,57 @@
{% extends 'default/layout.html.twig' %}
{% block main_content %}
{% for server in servers %}
<div class="border-default padding-8-px margin-y-8-px">
<h2>{{ server.info.HostName }}</h2>
<hr />
<h3 class="padding-y-8-px text-align-right">{{ 'Address' | trans }}</h3>
<div>
{{ server.host }}:{{ server.port }}
</div>
{% if server.alias %}
<h3 class="padding-y-8-px text-align-right">{{ 'Aliases' | trans }}</h3>
{% for alias in server.alias %}
<div>
{{ alias.host }}:{{ alias.port }}
</div>
{% endfor %}
{% endif %}
{% if server.info %}
<h3 class="padding-y-8-px text-align-right">{{ 'Info' | trans }}</h3>
<table>
{% for key, value in server.info %}
<tr>
<td class="text-align-left">{{ key }}</td>
<td class="text-align-left">{{ value }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
{% if server.online %}
<h3 class="padding-y-8-px text-align-right">{{ 'Online' | trans }}</h3>
<table>
<tr>
<th class="text-align-left">{{ 'Name' | trans }}</th>
<th class="text-align-center">{{ 'Frags' | trans }}</th>
<th class="text-align-center">{{ 'Time' | trans }}</th>
</tr>
{% for player in server.online %}
<tr>
<td class="text-align-left">{{ player.Name }}</td>
<td class="text-align-center">{{ player.Frags }}</td>
<td class="text-align-center">
{% if player.TimeF == '59:59' %}
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="currentColor" viewBox="0 0 16 16">
<path d="M5.68 5.792 7.345 7.75 5.681 9.708a2.75 2.75 0 1 1 0-3.916ZM8 6.978 6.416 5.113l-.014-.015a3.75 3.75 0 1 0 0 5.304l.014-.015L8 8.522l1.584 1.865.014.015a3.75 3.75 0 1 0 0-5.304l-.014.015zm.656.772 1.663-1.958a2.75 2.75 0 1 1 0 3.916z"/>
</svg>
{% else %}
{{ player.TimeF }}
{% endif %}
</td>
</tr>
{% endfor %}
</table>
{% endif %}
</div>
{% endfor %}
{% endblock %}
Loading…
Cancel
Save