Private
Public Access
1
0

chg: usr: make the first working version - the stepping is broken due to the algorythm structure #4

This commit is contained in:
2026-04-09 12:10:37 +02:00
parent dd4b410624
commit fa0fc0743d
51 changed files with 8355 additions and 55172 deletions

View File

@@ -2,6 +2,39 @@ Changelog
=========
(unreleased)
------------
New
~~~
- Add beta logo to the corner #3. [Lang]
- Add mineseeker game to the symfony 4 project #3. [Lang]
- Upgrade to the latest symfony v4 #3. [Lang]
Changes
~~~~~~~
- Change the composer default php minimum environment #3. [Lang]
- Change the default url to wss on frontend #3. [Lang]
- Refactor Rpc and Topic classes #3. [Lang]
- Refactor classes and reformat some layout #3. [Lang]
- Remove deprecated files #3. [Lang]
- Doc in README.md #3. [Lang]
- Gitignore a js.map file #2. [Lang]
Other
~~~~~
- Deploy version 1.1.0 !deploy #11. [Lang]
1.1.0 (2019-10-26)
------------------
Changes
~~~~~~~
- Reinit project - disable redis module and make the project compatible
w/ PHP7.3 #2. [Lang]
0.4.0 (2019-10-26)
------------------
- Change session driver to REDIS. [Lang]

View File

@@ -1,14 +0,0 @@
/*
* Welcome to your app's main JavaScript file!
*
* We recommend including the built version of this JavaScript file
* (and its CSS file) in your base layout (base.html.twig).
*/
// any CSS you require will output into a single css file (app.css in this case)
require('../css/app.css');
// Need jQuery? Install it with "yarn add jquery", then uncomment to require it.
// const $ = require('jquery');
console.log('Hello Webpack Encore! Edit me in assets/js/app.js');

View File

@@ -1,10 +1,12 @@
import React from 'react';
import ReactDOM from 'react-dom';
import MineSeeker from './mine-seeker/app';
import React from "react";
import ReactDOM from "react-dom";
import MineSeeker from "./mine-seeker/app";
ReactDOM.render(
<MineSeeker env={document.getElementById('mine-wrapper').dataset.env}
gameId={document.getElementById('mine-wrapper').dataset.gameId}
ssl={document.getElementById('mine-wrapper').dataset.ssl}/>,
document.getElementById('mine-wrapper')
<MineSeeker
env={document.getElementById("mine-wrapper").dataset.env}
gameId={document.getElementById("mine-wrapper").dataset.gameId}
ssl={document.getElementById("mine-wrapper").dataset.ssl}
/>,
document.getElementById("mine-wrapper"),
);

View File

@@ -391,7 +391,7 @@ class MineSeeker extends React.Component {
this.state.env === 'dev' && console.error("Disconnected for " + error.reason + " with code " + error.code);
error.code === 6 && this.setState({connectionLost: true});
error.code === 3 && setTimeout(this.componentDidMount().bind(this), 500);
error.code === 3 && setTimeout(this.componentDidMount.bind(this), 500);
});
}

View File

@@ -398,10 +398,6 @@ class GridControl extends React.Component {
}
}
overlayClass() {
return 'game-overlay' + (this.state.overlay ? '' : ' hide');
}
renderGridFields() {
for (let i = 0, j = this.state.grid.length; i < j; i++) {
for (let k = 0, l = this.state.grid[i].length; k < l; k++) {
@@ -409,7 +405,7 @@ class GridControl extends React.Component {
<GridField row={i}
col={k}
ref={this.refString(i, k)}
key={window.btoa((Math.random() * 0.5).toString())}
key={this.refString(i, k)}
handleHoverOn={this.onHoverGridField.bind(this, [i, k])}
onClick={this.props.onClick.bind(null, [i, k])}/>
);
@@ -424,7 +420,7 @@ class GridControl extends React.Component {
return (
<div className="game-wrapper">
<div className={this.overlayClass()}>
<div className={`game-overlay ${this.state.overlay ? '' : ' hide'}`}>
<div className="game-overlay-window">
<h1>{this.state.overlayTitle}</h1>
<h2>{this.state.overlaySubTitle}</h2>

View File

@@ -1,42 +0,0 @@
/**
* ReactDOMServer v15.3.2
*
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
// Based off https://github.com/ForbesLindesay/umd/blob/master/template.js
;(function(f) {
// CommonJS
if (typeof exports === "object" && typeof module !== "undefined") {
module.exports = f(require('react'));
// RequireJS
} else if (typeof define === "function" && define.amd) {
define(['react'], f);
// <script>
} else {
var g;
if (typeof window !== "undefined") {
g = window;
} else if (typeof global !== "undefined") {
g = global;
} else if (typeof self !== "undefined") {
g = self;
} else {
// works providing we're not in "use strict";
// needed for Java 8 Nashorn
// see https://github.com/facebook/react/issues/3037
g = this;
}
g.ReactDOMServer = f(g.React);
}
})(function(React) {
return React.__SECRET_DOM_SERVER_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
});

View File

@@ -1,12 +0,0 @@
/**
* ReactDOMServer v15.3.2
*
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e(require("react"));else if("function"==typeof define&&define.amd)define(["react"],e);else{var f;f="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,f.ReactDOMServer=e(f.React)}}(function(e){return e.__SECRET_DOM_SERVER_DO_NOT_USE_OR_YOU_WILL_BE_FIRED});

View File

@@ -1,42 +0,0 @@
/**
* ReactDOM v15.3.2
*
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
// Based off https://github.com/ForbesLindesay/umd/blob/master/template.js
;(function(f) {
// CommonJS
if (typeof exports === "object" && typeof module !== "undefined") {
module.exports = f(require('react'));
// RequireJS
} else if (typeof define === "function" && define.amd) {
define(['react'], f);
// <script>
} else {
var g;
if (typeof window !== "undefined") {
g = window;
} else if (typeof global !== "undefined") {
g = global;
} else if (typeof self !== "undefined") {
g = self;
} else {
// works providing we're not in "use strict";
// needed for Java 8 Nashorn
// see https://github.com/facebook/react/issues/3037
g = this;
}
g.ReactDOM = f(g.React);
}
})(function(React) {
return React.__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
});

View File

@@ -1,12 +0,0 @@
/**
* ReactDOM v15.3.2
*
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e(require("react"));else if("function"==typeof define&&define.amd)define(["react"],e);else{var f;f="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,f.ReactDOM=e(f.React)}}(function(e){return e.__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED});

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

1437
bun.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2,30 +2,29 @@
"type": "project",
"license": "proprietary",
"require": {
"php": "^7.2",
"php": ">=8.1",
"ext-iconv": "*",
"ext-json": "*",
"doctrine/doctrine-migrations-bundle": "^2.0",
"doctrine/orm": "^2.6",
"gos/web-socket-bundle": "^1.8",
"sensio/framework-extra-bundle": "^5.5",
"sonata-project/admin-bundle": "^3.0",
"sonata-project/doctrine-orm-admin-bundle": "^3.0",
"sonata-project/user-bundle": "^4.0",
"symfony/console": "^4.0",
"symfony/flex": "^1.0",
"symfony/framework-bundle": "^4.0",
"symfony/mailer": "^4.0",
"symfony/monolog-bundle": "^3.4",
"symfony/orm-pack": "^1.0",
"symfony/polyfill-apcu": "^1.0",
"symfony/twig-bundle": "^4.0",
"symfony/webpack-encore-bundle": "^1.7",
"symfony/yaml": "^4.0"
"gos/web-socket-bundle": "^3.0",
"sensio/framework-extra-bundle": "^6.0",
"sonata-project/admin-bundle": "^4.0",
"sonata-project/doctrine-orm-admin-bundle": "^4.0",
"sonata-project/user-bundle": "^5.0",
"symfony/console": "5.4.*",
"symfony/flex": "^2.10.0",
"symfony/framework-bundle": "5.4.*",
"symfony/mailer": "5.4.*",
"symfony/monolog-bundle": "^3.8",
"symfony/orm-pack": "^2.0",
"symfony/twig-bundle": "5.4.*",
"symfony/webpack-encore-bundle": "^1.0",
"symfony/yaml": "5.4.*"
},
"require-dev": {
"roave/security-advisories": "dev-master",
"symfony/dotenv": "^4.0",
"symfony/dotenv": "5.4.*",
"symfony/profiler-pack": "^1.0",
"symfony/maker-bundle": "^1.5"
},
@@ -33,7 +32,10 @@
"preferred-install": {
"*": "dist"
},
"sort-packages": true
"sort-packages": true,
"allow-plugins": {
"symfony/flex": true
}
},
"autoload": {
"psr-4": {
@@ -47,6 +49,7 @@
},
"replace": {
"symfony/polyfill-iconv": "*",
"symfony/polyfill-ctype": "*",
"symfony/polyfill-php73": "*",
"symfony/polyfill-php72": "*",
"symfony/polyfill-php71": "*",
@@ -66,11 +69,13 @@
]
},
"conflict": {
"symfony/symfony": "*"
"symfony/symfony": "*",
"doctrine/persistence": "<1.3"
},
"extra": {
"symfony": {
"allow-contrib": false
"allow-contrib": false,
"require": "5.4.*"
}
}
}

10110
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,17 +5,16 @@ return [
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle::class => ['all' => true],
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
Sonata\DatagridBundle\SonataDatagridBundle::class => ['all' => true],
Sonata\CoreBundle\SonataCoreBundle::class => ['all' => true],
Sonata\BlockBundle\SonataBlockBundle::class => ['all' => true],
Knp\Bundle\MenuBundle\KnpMenuBundle::class => ['all' => true],
Sonata\Doctrine\Bridge\Symfony\SonataDoctrineBundle::class => ['all' => true],
Sonata\Exporter\Bridge\Symfony\SonataExporterBundle::class => ['all' => true],
Sonata\Form\Bridge\Symfony\Bundle\SonataFormBundle::class => ['all' => true],
Sonata\Twig\Bridge\Symfony\SonataTwigBundle::class => ['all' => true],
Sonata\BlockBundle\SonataBlockBundle::class => ['all' => true],
Sonata\AdminBundle\SonataAdminBundle::class => ['all' => true],
Sonata\EasyExtendsBundle\SonataEasyExtendsBundle::class => ['all' => true],
FOS\UserBundle\FOSUserBundle::class => ['all' => true],
Sonata\UserBundle\SonataUserBundle::class => ['all' => true],
App\Application\Sonata\UserBundle\ApplicationSonataUserBundle::class => ['all' => true],
Sonata\DoctrineORMAdminBundle\SonataDoctrineORMAdminBundle::class => ['all' => true],

View File

@@ -30,5 +30,4 @@ doctrine:
prefix: 'App\Entity'
alias: App
SonataUserBundle: ~
FOSUserBundle: ~
ApplicationSonataUserBundle: ~

View File

@@ -1,5 +1,4 @@
doctrine_migrations:
dir_name: '%kernel.project_dir%/src/Migrations'
# namespace is arbitrary but should be different from App\Migrations
# as migrations classes should NOT be autoloaded
namespace: DoctrineMigrations
migrations_paths:
'App\Migrations': '%kernel.project_dir%/src/Migrations'
organize_migrations: BY_YEAR_AND_MONTH

View File

@@ -1,13 +0,0 @@
fos_user:
db_driver: orm # can be orm or odm
firewall_name: main
user_class: App\Application\Sonata\UserBundle\Entity\User
group:
group_class: App\Application\Sonata\UserBundle\Entity\Group
group_manager: sonata.user.orm.group_manager # If you're using doctrine orm (use sonata.user.mongodb.group_manager for mongodb)
service:
user_manager: sonata.user.orm.user_manager
mailer: 'fos_user.mailer.noop'
from_email:
address: '%env(MAILER_USER_ADDRESS)%'
sender_name: '%env(MAILER_USER_NAME)%'

View File

@@ -3,9 +3,6 @@ framework:
#default_locale: en
#csrf_protection: true
#http_method_override: true
templating:
engines: ['twig']
# Enables session support. Note that the session will ONLY be started if you read or write from it.
# Remove or comment this section to explicitly disable session support.
session:

View File

@@ -23,5 +23,6 @@ gos_web_socket:
# driver: "@gos_web_socket.client_storage.driver.predis"
# ttl: 28800 #(optionally) time to live if you use redis driver
# prefix: client #(optionally) prefix if you use redis driver, create key "client:1" instead key "1"
periodic:
- '@mineseeker.periodic'
ping:
services:
- { name: doctrine.dbal.default_connection, type: doctrine, interval: 300 }

View File

@@ -7,7 +7,7 @@ security:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: true
lazy: true
# activate different ways to authenticate

View File

@@ -1,4 +0,0 @@
sonata_core:
form:
mapping:
enabled: false

View File

@@ -1,6 +1,3 @@
sonata_user:
security_acl: false
manager_type: orm # can be orm or mongodb
class:
user: App\Application\Sonata\UserBundle\Entity\User
group: App\Application\Sonata\UserBundle\Entity\Group

View File

@@ -1,8 +1,7 @@
## Topic Configuration
mineseeker_topic:
channel: mineseeker/channel/{game}
handler:
callback: 'mineseeker.topic' #related to the getName() of your topic
callback: 'mineseeker.topic'
# requirements:
# method:
# path: '[a-z1-9A-Z]+'
@@ -10,8 +9,6 @@ mineseeker_topic:
# Remote Procedure Call Configuration
mineseeker_rpc:
channel: mineseeker-rpc/{method}
handler:
callback: 'mineseeker.rpc' #related to the getName() or your RPC service
callback: 'mineseeker.rpc'
requirements:
method:
path: "[a-z_]+"
method: "[a-zA-Z_]+"

View File

@@ -1,3 +1,3 @@
_errors:
resource: '@TwigBundle/Resources/config/routing/errors.xml'
resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
prefix: /_error

View File

@@ -1,27 +1,27 @@
MineSeekerBundle_homepage:
path: /
controller: App\Controller\GameController:index
controller: App\Controller\GameController::index
MineSeekerBundle_gamePlay:
path: /play
controller: App\Controller\GameController:play
controller: App\Controller\GameController::play
MineSeekerBundle_gamePlayWId:
path: /play/{gameAssoc}
controller: App\Controller\GameController:play
controller: App\Controller\GameController::play
MineSeekerBundle_terms:
path: /terms-of-service
controller: App\Controller\GameController:terms
controller: App\Controller\GameController::terms
MineSeekerBundle_privacy:
path: /privacy-policy
controller: App\Controller\GameController:privacy
controller: App\Controller\GameController::privacy
MineSeekerBundle_contact:
path: /contact
controller: App\Controller\GameController:contact
controller: App\Controller\GameController::contact
MineSeekerBundle_landing:
path: /landing-page
controller: App\Controller\GameController:landing
controller: App\Controller\GameController::landing

View File

@@ -22,7 +22,7 @@ services:
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{Entity,Migrations,Tests,Kernel.php}'
exclude: '../src/{Entity,Migrations,Tests,Kernel.php,Periodic}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
@@ -33,13 +33,6 @@ services:
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones
mineseeker.periodic:
class: App\Periodic\MinePeriodic
tags:
- { name: gos_web_socket.periodic }
arguments:
- '@gos_web_socket.pdo.periodic_ping'
mineseeker.topic_sample_service:
class: App\Topic\MineseekerTopic
tags:

View File

@@ -27,15 +27,17 @@
"uglifycss": "0.0.25"
},
"devDependencies": {
"@babel/preset-env": "^7.23.0",
"@babel/preset-react": "^7.6.3",
"@symfony/webpack-encore": "^0.28.0",
"autoprefixer": "^7.2.2",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.7.0",
"@symfony/webpack-encore": "^4.0",
"autoprefixer": "^10.0.0",
"babel-loader": "^9.0",
"core-js": "^3.0.0",
"node-sass": "^4.12.0",
"sass-loader": "^7.1.0",
"webpack-notifier": "^1.6.0"
"sass": "^1.77.0",
"sass-loader": "^13.0",
"webpack": "^5.72",
"webpack-cli": "^5.0",
"webpack-notifier": "^1.15.0"
},
"scripts": {
"dev-server": "encore dev-server",

View File

@@ -1,7 +1,7 @@
<?php
use App\Kernel;
use Symfony\Component\Debug\Debug;
use Symfony\Component\ErrorHandler\Debug;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\HttpFoundation\Request;

View File

@@ -1,31 +0,0 @@
<?php
namespace App\Application\Sonata\UserBundle\Document;
use Sonata\UserBundle\Document\BaseGroup as BaseGroup;
/**
* This file has been generated by the SonataEasyExtendsBundle.
*
* @link https://sonata-project.org/easy-extends
*
* References:
* @link http://www.doctrine-project.org/docs/mongodb_odm/1.0/en/reference/working-with-objects.html
*/
class Group extends BaseGroup
{
/**
* @var int $id
*/
protected $id;
/**
* Get id.
*
* @return int $id
*/
public function getId()
{
return $this->id;
}
}

View File

@@ -1,31 +0,0 @@
<?php
namespace App\Application\Sonata\UserBundle\Entity;
use Sonata\UserBundle\Entity\BaseGroup as BaseGroup;
/**
* This file has been generated by the SonataEasyExtendsBundle.
*
* @link https://sonata-project.org/easy-extends
*
* References:
* @link http://www.doctrine-project.org/projects/orm/2.0/docs/reference/working-with-objects/en
*/
class Group extends BaseGroup
{
/**
* @var int $id
*/
protected $id;
/**
* Get id.
*
* @return int $id
*/
public function getId()
{
return $this->id;
}
}

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mongo-mapping xmlns="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping
http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd">
<document name="App\Application\Sonata\UserBundle\Document\Group" collection="fos_user_group">
<field fieldName="id" id="true" strategy="INCREMENT" />
</document>
</doctrine-mongo-mapping>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="App\Application\Sonata\UserBundle\Entity\Group" table="fos_user_group">
<id name="id" column="id" type="integer">
<generator strategy="AUTO" />
</id>
</entity>
</doctrine-mapping>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<serializer>
<!-- This file has been generated by the SonataEasyExtendsBundle: https://sonata-project.org/bundles/easy-extends -->
<class name="App\Application\Sonata\UserBundle\Document\Group" exclusion-policy="all" xml-root-name="_group">
<property xml-attribute-map="true" name="id" type="integer" expose="true" since-version="1.0" groups="sonata_api_read,sonata_api_write,sonata_search"/>
</class>
</serializer>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<serializer>
<!-- This file has been generated by the SonataEasyExtendsBundle: https://sonata-project.org/bundles/easy-extends -->
<class name="App\Application\Sonata\UserBundle\Entity\Group" exclusion-policy="all" xml-root-name="_group">
<property xml-attribute-map="true" name="id" type="integer" expose="true" since-version="1.0" groups="sonata_api_read,sonata_api_write,sonata_search"/>
</class>
</serializer>

View File

@@ -10,10 +10,11 @@
namespace App\EventListener;
use Gos\Bundle\WebSocketBundle\Event\ClientEvent;
use Gos\Bundle\WebSocketBundle\Event\ClientConnectedEvent;
use Gos\Bundle\WebSocketBundle\Event\ClientDisconnectedEvent;
use Gos\Bundle\WebSocketBundle\Event\ClientErrorEvent;
use Gos\Bundle\WebSocketBundle\Event\ServerEvent;
use Gos\Bundle\WebSocketBundle\Event\ClientRejectedEvent;
use Gos\Bundle\WebSocketBundle\Event\ServerLaunchedEvent;
/**
* Class MineseekerClientEventListener
@@ -23,35 +24,20 @@ use Gos\Bundle\WebSocketBundle\Event\ClientRejectedEvent;
*/
class MineseekerClientEventListener
{
/**
* Called whenever a client connects
*
* @param ClientEvent $event
*/
public function onClientConnect(ClientEvent $event): void
public function onClientConnect(ClientConnectedEvent $event): void
{
$conn = $event->getConnection();
echo $conn->resourceId . ' connected' . PHP_EOL;
}
/**
* Called whenever a client disconnects
*
* @param ClientEvent $event
*/
public function onClientDisconnect(ClientEvent $event): void
public function onClientDisconnect(ClientDisconnectedEvent $event): void
{
$conn = $event->getConnection();
echo $conn->resourceId . ' disconnected' . PHP_EOL;
}
/**
* Called whenever a client errors
*
* @param ClientErrorEvent $event
*/
public function onClientError(ClientErrorEvent $event): void
{
$conn = $event->getConnection();
@@ -60,26 +46,14 @@ class MineseekerClientEventListener
echo 'connection error occurred: ' . $e->getMessage() . PHP_EOL;
}
/**
* Called whenever server start
*
* @param ServerEvent $event
*/
public function onServerStart(ServerEvent $event): void
public function onServerStart(ServerLaunchedEvent $event): void
{
$event = $event->getEventLoop();
echo 'Server was successfully started !' . PHP_EOL;
}
/**
* Called whenever client is rejected by application
*
* @param ClientRejectedEvent $event
*/
public function onClientRejected(ClientRejectedEvent $event): void
{
$origin = $event->getOrigin;
$origin = $event->getOrigin();
echo 'connection rejected from ' . $origin . PHP_EOL;
}

View File

@@ -3,59 +3,19 @@
namespace App;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
use Symfony\Component\Routing\RouteCollectionBuilder;
class Kernel extends BaseKernel
{
use MicroKernelTrait;
const CONFIG_EXTS = '.{php,xml,yaml,yml}';
public function getCacheDir()
public function getCacheDir(): string
{
return $this->getProjectDir().'/var/cache/'.$this->environment;
}
public function getLogDir()
public function getLogDir(): string
{
return $this->getProjectDir().'/var/log';
}
public function registerBundles()
{
$contents = require $this->getProjectDir().'/config/bundles.php';
foreach ($contents as $class => $envs) {
if (isset($envs['all']) || isset($envs[$this->environment])) {
yield new $class();
}
}
}
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader)
{
$container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php'));
// Feel free to remove the "container.autowiring.strict_mode" parameter
// if you are using symfony/dependency-injection 4.0+ as it's the default behavior
$container->setParameter('container.autowiring.strict_mode', true);
$container->setParameter('container.dumper.inline_class_loader', true);
$confDir = $this->getProjectDir().'/config';
$loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/{packages}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob');
$loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob');
}
protected function configureRoutes(RouteCollectionBuilder $routes)
{
$confDir = $this->getProjectDir().'/config';
$routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob');
$routes->import($confDir.'/{routes}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob');
$routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob');
}
}

View File

@@ -0,0 +1,84 @@
<?php
declare(strict_types=1);
namespace App\Migrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20260409081936 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('CREATE SEQUENCE fos_user_user_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE SEQUENCE gamer_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE SEQUENCE grid_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE SEQUENCE grid_row_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE SEQUENCE played_game_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE SEQUENCE step_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE TABLE fos_user_user (id INT NOT NULL, username VARCHAR(180) NOT NULL, username_canonical VARCHAR(180) NOT NULL, email VARCHAR(180) NOT NULL, email_canonical VARCHAR(180) NOT NULL, enabled BOOLEAN NOT NULL, salt VARCHAR(255) DEFAULT NULL, password VARCHAR(255) NOT NULL, last_login TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, confirmation_token VARCHAR(180) DEFAULT NULL, password_requested_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, roles TEXT NOT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updated_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE UNIQUE INDEX UNIQ_C560D76192FC23A8 ON fos_user_user (username_canonical)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_C560D761A0D96FBF ON fos_user_user (email_canonical)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_C560D761C05FB297 ON fos_user_user (confirmation_token)');
$this->addSql('COMMENT ON COLUMN fos_user_user.roles IS \'(DC2Type:array)\'');
$this->addSql('CREATE TABLE gamer (id INT NOT NULL, user_name VARCHAR(100) NOT NULL, ip VARCHAR(20) DEFAULT NULL, country VARCHAR(100) DEFAULT NULL, user_agent VARCHAR(255) DEFAULT NULL, conn_timestamp TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE TABLE grid (id INT NOT NULL, played_game_id INT DEFAULT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE UNIQUE INDEX UNIQ_2E20D9375AA11DBB ON grid (played_game_id)');
$this->addSql('CREATE TABLE grid_row (id INT NOT NULL, grid INT DEFAULT NULL, grid_col JSON NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE INDEX IDX_6FAD08EB2E20D937 ON grid_row (grid)');
$this->addSql('COMMENT ON COLUMN grid_row.grid_col IS \'(DC2Type:json_array)\'');
$this->addSql('CREATE TABLE played_game (id INT NOT NULL, red_id INT DEFAULT NULL, red_anon INT DEFAULT NULL, blue_id INT DEFAULT NULL, blue_anon INT DEFAULT NULL, game_assoc VARCHAR(50) NOT NULL, red_points INT DEFAULT NULL, blue_points INT DEFAULT NULL, red_exploded_bomb BOOLEAN DEFAULT NULL, blue_exploded_bomb BOOLEAN DEFAULT NULL, resign VARCHAR(7) DEFAULT NULL, created TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, updated TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE INDEX IDX_54BE80398BBE8922 ON played_game (red_id)');
$this->addSql('CREATE INDEX IDX_54BE8039F24372EB ON played_game (red_anon)');
$this->addSql('CREATE INDEX IDX_54BE80395AB9393F ON played_game (blue_id)');
$this->addSql('CREATE INDEX IDX_54BE8039C64E7C7C ON played_game (blue_anon)');
$this->addSql('CREATE TABLE step (id INT NOT NULL, played_game_id INT DEFAULT NULL, row INT NOT NULL, col INT NOT NULL, wbomb BOOLEAN DEFAULT NULL, created TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE INDEX IDX_43B9FE3C5AA11DBB ON step (played_game_id)');
$this->addSql('ALTER TABLE grid ADD CONSTRAINT FK_2E20D9375AA11DBB FOREIGN KEY (played_game_id) REFERENCES played_game (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE grid_row ADD CONSTRAINT FK_6FAD08EB2E20D937 FOREIGN KEY (grid) REFERENCES grid (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE played_game ADD CONSTRAINT FK_54BE80398BBE8922 FOREIGN KEY (red_id) REFERENCES fos_user_user (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE played_game ADD CONSTRAINT FK_54BE8039F24372EB FOREIGN KEY (red_anon) REFERENCES gamer (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE played_game ADD CONSTRAINT FK_54BE80395AB9393F FOREIGN KEY (blue_id) REFERENCES fos_user_user (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE played_game ADD CONSTRAINT FK_54BE8039C64E7C7C FOREIGN KEY (blue_anon) REFERENCES gamer (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE step ADD CONSTRAINT FK_43B9FE3C5AA11DBB FOREIGN KEY (played_game_id) REFERENCES played_game (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('CREATE SCHEMA public');
$this->addSql('ALTER TABLE played_game DROP CONSTRAINT FK_54BE80398BBE8922');
$this->addSql('ALTER TABLE played_game DROP CONSTRAINT FK_54BE80395AB9393F');
$this->addSql('ALTER TABLE played_game DROP CONSTRAINT FK_54BE8039F24372EB');
$this->addSql('ALTER TABLE played_game DROP CONSTRAINT FK_54BE8039C64E7C7C');
$this->addSql('ALTER TABLE grid_row DROP CONSTRAINT FK_6FAD08EB2E20D937');
$this->addSql('ALTER TABLE grid DROP CONSTRAINT FK_2E20D9375AA11DBB');
$this->addSql('ALTER TABLE step DROP CONSTRAINT FK_43B9FE3C5AA11DBB');
$this->addSql('DROP SEQUENCE fos_user_user_id_seq CASCADE');
$this->addSql('DROP SEQUENCE gamer_id_seq CASCADE');
$this->addSql('DROP SEQUENCE grid_id_seq CASCADE');
$this->addSql('DROP SEQUENCE grid_row_id_seq CASCADE');
$this->addSql('DROP SEQUENCE played_game_id_seq CASCADE');
$this->addSql('DROP SEQUENCE step_id_seq CASCADE');
$this->addSql('DROP TABLE fos_user_user');
$this->addSql('DROP TABLE gamer');
$this->addSql('DROP TABLE grid');
$this->addSql('DROP TABLE grid_row');
$this->addSql('DROP TABLE played_game');
$this->addSql('DROP TABLE step');
}
}

View File

@@ -39,7 +39,7 @@ class MinePeriodic implements PeriodicInterface
*
* For more advanced functionality, try injecting a Topic Service to perform actions on your connections every x seconds.
*/
public function tick()
public function tick(): void
{
$this->ping->tick();
}
@@ -47,7 +47,7 @@ class MinePeriodic implements PeriodicInterface
/**
* {@inheritdoc}
*/
public function getTimeout()
public function getTimeout(): int
{
return 300;
}

View File

@@ -12,7 +12,7 @@ namespace App\Repository;
use App\Entity\Gamer;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\Persistence\ManagerRegistry;
/**
* Class GamerRepository

View File

@@ -12,7 +12,7 @@ namespace App\Repository;
use App\Entity\Grid;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\Persistence\ManagerRegistry;
/**
* Class GridRepository

View File

@@ -12,7 +12,7 @@ namespace App\Repository;
use App\Entity\GridRow;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\Persistence\ManagerRegistry;
/**
* Class GridRowRepository

View File

@@ -12,7 +12,7 @@ namespace App\Repository;
use App\Entity\PlayedGame;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\Persistence\ManagerRegistry;
/**
* Class PlayedGameRepository

View File

@@ -12,7 +12,7 @@ namespace App\Repository;
use App\Entity\Step;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\Persistence\ManagerRegistry;
/**
* Class StepRepository

View File

@@ -54,8 +54,9 @@ class RpcManager extends WebsocketManager implements RpcManagerInterface
*/
public function getConnectInformation($params): string
{
$grid = $this->getGrid($params);
$users = null !== $grid ? $this->getUsers($params) : null;
$gameAssoc = is_array($params) ? $params[0] : $params;
$grid = $this->getGrid($gameAssoc);
$users = null !== $grid ? $this->getUsers($gameAssoc) : null;
return base64_encode(json_encode(array(
'grid' => $grid,

View File

@@ -23,6 +23,7 @@ use Psr\Log\LoggerInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Wamp\Topic;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
* Class TopicManager
@@ -74,7 +75,7 @@ class TopicManager extends WebsocketManager implements TopicManagerInterface
{
/** this will broadcast the message to ALL subscribers of this topic. */
$user = $this->clientManipulator->getClient($connection);
$userName = is_string($user) ? $user : $user->getUsername();
$userName = $user->getUserIdentifier();
/** if more user wants to connect than 2 to one channel */
if ($topic->count() > 2) {
@@ -107,7 +108,7 @@ class TopicManager extends WebsocketManager implements TopicManagerInterface
public function publish(Topic $topic, ConnectionInterface $connection, $event): void
{
$user = $this->clientManipulator->getClient($connection);
$userName = is_string($user) ? $user : $user->getUsername();
$userName = $user->getUserIdentifier();
/** Save every step by user to db */
null === $event['resign']
@@ -193,7 +194,7 @@ class TopicManager extends WebsocketManager implements TopicManagerInterface
*
* @return array
*/
private function controlUsers(Topic $topic, string $userName, $user): array
private function controlUsers(Topic $topic, string $userName, TokenInterface $user): array
{
$gameAssoc = explode('/', $topic->getId())[2];
@@ -229,7 +230,7 @@ class TopicManager extends WebsocketManager implements TopicManagerInterface
*
* @return array
*/
private function saveUserToDb(Topic $topic, string $userName, $user, $count)
private function saveUserToDb(Topic $topic, string $userName, TokenInterface $user, $count)
{
$gameAssoc = explode('/', $topic->getId())[2];
@@ -239,7 +240,7 @@ class TopicManager extends WebsocketManager implements TopicManagerInterface
->findOneByGameAssoc($gameAssoc);
/** when the user is not anonym */
!is_string($user)
null !== $user->getUser()
? $this->saveRegisteredUser($userName, $count, $playedGame)
: $this->saveAnonUser($userName, $count, $playedGame);

View File

@@ -38,7 +38,7 @@
{{ parent() }}
<script type="text/javascript" src="{{ asset('bundles/goswebsocket/js/vendor/autobahn.min.js') }}"></script>
<script type="text/javascript" src="{{ asset('bundles/goswebsocket/js/gos_web_socket_client.js') }}"></script>
<script type="text/javascript" src="{{ asset('bundles/goswebsocket/js/websocket.js') }}"></script>
{{ encore_entry_script_tags('mineseeker') }}
{% endblock %}

View File

@@ -1,4 +1,5 @@
var Encore = require('@symfony/webpack-encore');
var webpack = require('webpack');
// Manually configure the runtime environment if not already configured yet by the "encore" command.
// It's useful when you use tools that rely on webpack.config.js file.
@@ -32,10 +33,21 @@ Encore
.addEntry('homeStyle', './assets/css/style.layout.scss')
// uncomment if you use Sass/SCSS files
.enableSassLoader()
.enableSassLoader(options => {
options.api = 'modern';
options.sassOptions = { silenceDeprecations: ['import'] };
})
.configureCssLoader(options => {
// don't process absolute URLs (e.g. /images/...) — served by the web server
options.url = { filter: url => !url.startsWith('/') };
})
// uncomment for legacy applications that require $/jQuery as a global variable
.autoProvidejQuery()
// provide $/jQuery as global variables for Bootstrap 3 and legacy code
.addPlugin(new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
}))
// .configureBabel(function (babelConfig) {
// babelConfig.presets.push('env');

7788
yarn.lock

File diff suppressed because it is too large Load Diff