Compare commits
12 Commits
v2026.2.5-
...
userlist
| Author | SHA1 | Date | |
|---|---|---|---|
| ae8794f564 | |||
| 2f3062bf33 | |||
| 0e86f7d4aa | |||
| 8851a6d68b | |||
| 94ebe9a428 | |||
| 4a94855be9 | |||
| a8ac13850b | |||
| fe5378f69b | |||
| e8691f29bb | |||
| fcd490ef4e | |||
| a3465f6cf9 | |||
| a91172ef7a |
2
.babelrc
2
.babelrc
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"presets": ["es2015", "react"]
|
"presets": ["es2015", "es2016", "es2017", "react"]
|
||||||
}
|
}
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -35,6 +35,5 @@ phpunit-report/*
|
|||||||
/src/Mine/SeekerBundle/Resources/public/js/src/
|
/src/Mine/SeekerBundle/Resources/public/js/src/
|
||||||
|
|
||||||
nohup.out
|
nohup.out
|
||||||
src/Mine/SeekerBundle/Resources/public/js/index.js
|
src/Mine/SeekerBundle/Resources/public/js/build/
|
||||||
src/Mine/SeekerBundle/Resources/public/js/index.min.js
|
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ This is a Symfony 3 project w/ React JS in standalone mode and w/ WebSocket.
|
|||||||
|
|
||||||
1.) Backend WebSocket server start as daemon - GeniusesOfSymfony/WebSocketBundle
|
1.) Backend WebSocket server start as daemon - GeniusesOfSymfony/WebSocketBundle
|
||||||
|
|
||||||
$ nohup bin/console gos:websocket:server &
|
$ nohup php bin/console gos:websocket:server --env=prod &
|
||||||
|
|
||||||
2.) React JS WebPack watch generator w/ babel presets: es2015, react
|
2.) React JS WebPack watch generator w/ babel presets: es2015, react
|
||||||
|
|
||||||
@@ -32,4 +32,9 @@ This is a Symfony 3 project w/ React JS in standalone mode and w/ WebSocket.
|
|||||||
|
|
||||||
3.) Connect to Prod
|
3.) Connect to Prod
|
||||||
|
|
||||||
ssh xxsvci@laszlolang.com -i ~/.ssh/id_rsa_laszlolang
|
$ ssh xxsvci@laszlolang.com -i ~/.ssh/id_rsa_laszlolang
|
||||||
|
|
||||||
|
4.) Stunnel config
|
||||||
|
|
||||||
|
$ sudo nano /etc/stunnel/stunnel.conf
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class AppKernel extends Kernel
|
|||||||
new Gos\Bundle\PubSubRouterBundle\GosPubSubRouterBundle(),
|
new Gos\Bundle\PubSubRouterBundle\GosPubSubRouterBundle(),
|
||||||
new Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle(),
|
new Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle(),
|
||||||
new Snc\RedisBundle\SncRedisBundle(),
|
new Snc\RedisBundle\SncRedisBundle(),
|
||||||
new CL\Bundle\SlackBundle\CLSlackBundle(),
|
// new CL\Bundle\SlackBundle\CLSlackBundle(),
|
||||||
|
|
||||||
new Jotunheimr\AdminBundle\JotunheimrAdminBundle(),
|
new Jotunheimr\AdminBundle\JotunheimrAdminBundle(),
|
||||||
new Jotunheimr\UserBundle\JotunheimrUserBundle(),
|
new Jotunheimr\UserBundle\JotunheimrUserBundle(),
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ imports:
|
|||||||
# http://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
|
# http://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
|
||||||
parameters:
|
parameters:
|
||||||
locale: en
|
locale: en
|
||||||
|
fos.email: 7system7@gmail.com
|
||||||
|
fos.name: system7
|
||||||
|
|
||||||
framework:
|
framework:
|
||||||
#esi: ~
|
#esi: ~
|
||||||
@@ -41,7 +43,7 @@ twig:
|
|||||||
debug: "%kernel.debug%"
|
debug: "%kernel.debug%"
|
||||||
strict_variables: "%kernel.debug%"
|
strict_variables: "%kernel.debug%"
|
||||||
globals:
|
globals:
|
||||||
version: "0.37.18 (beta7)"
|
version: "0.42.21 (beta8)"
|
||||||
facebook_api: "%facebook.api%"
|
facebook_api: "%facebook.api%"
|
||||||
facebook_scope: "%facebook.scope%"
|
facebook_scope: "%facebook.scope%"
|
||||||
facebook_api_version: "%facebook.version%"
|
facebook_api_version: "%facebook.version%"
|
||||||
@@ -87,6 +89,9 @@ fos_user:
|
|||||||
db_driver: orm # other valid values are 'mongodb', 'couchdb' and 'propel'
|
db_driver: orm # other valid values are 'mongodb', 'couchdb' and 'propel'
|
||||||
firewall_name: secured_area
|
firewall_name: secured_area
|
||||||
user_class: Jotunheimr\UserBundle\Entity\User
|
user_class: Jotunheimr\UserBundle\Entity\User
|
||||||
|
from_email:
|
||||||
|
address: "%fos.email%"
|
||||||
|
sender_name: "%fos.name%"
|
||||||
|
|
||||||
# Facebook OAuth
|
# Facebook OAuth
|
||||||
hwi_oauth:
|
hwi_oauth:
|
||||||
@@ -103,5 +108,5 @@ hwi_oauth:
|
|||||||
csrf: true
|
csrf: true
|
||||||
|
|
||||||
# Slack integration
|
# Slack integration
|
||||||
cl_slack:
|
#cl_slack:
|
||||||
api_token: xoxp-107639806167-107029084564-115427085733-cccaa4f96c89c87ce680c7f22acfd001
|
# api_token: xoxp-107639806167-107029084564-115427085733-cccaa4f96c89c87ce680c7f22acfd001
|
||||||
|
|||||||
@@ -35,7 +35,8 @@
|
|||||||
"predis/predis": "^1.0",
|
"predis/predis": "^1.0",
|
||||||
"snc/redis-bundle": "^2.0",
|
"snc/redis-bundle": "^2.0",
|
||||||
"hwi/oauth-bundle": "^0.5.1",
|
"hwi/oauth-bundle": "^0.5.1",
|
||||||
"cleentfaar/slack-bundle": "^0.20.1"
|
"cleentfaar/slack-bundle": "^0.20.1",
|
||||||
|
"symfony/translation": "^3.2"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"sensio/generator-bundle": "^3.0",
|
"sensio/generator-bundle": "^3.0",
|
||||||
|
|||||||
811
composer.lock
generated
811
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
|||||||
src/Mine/SeekerBundle/Resources/public/js/node
|
|
||||||
@@ -9,6 +9,8 @@
|
|||||||
"babel-core": "^6.14.0",
|
"babel-core": "^6.14.0",
|
||||||
"babel-loader": "^6.2.5",
|
"babel-loader": "^6.2.5",
|
||||||
"babel-preset-es2015": "^6.14.0",
|
"babel-preset-es2015": "^6.14.0",
|
||||||
|
"babel-preset-es2016": "^6.22.0",
|
||||||
|
"babel-preset-es2017": "^6.22.0",
|
||||||
"babel-preset-react": "^6.11.1",
|
"babel-preset-react": "^6.11.1",
|
||||||
"howler": "^2.0.1",
|
"howler": "^2.0.1",
|
||||||
"js-base64": "^2.1.9",
|
"js-base64": "^2.1.9",
|
||||||
@@ -33,6 +35,6 @@
|
|||||||
"multiplayer",
|
"multiplayer",
|
||||||
"websocket"
|
"websocket"
|
||||||
],
|
],
|
||||||
"author": "Laszlo Lang <system7>",
|
"author": "Laszlo Lang <system7> www.laszlolang.com",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ class User extends BaseUser
|
|||||||
*/
|
*/
|
||||||
private $facebookId;
|
private $facebookId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(name="facebook_access_token", type="string", length=255, nullable=true)
|
||||||
|
*/
|
||||||
private $facebookAccessToken;
|
private $facebookAccessToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -251,6 +251,11 @@ main div.txt {
|
|||||||
margin: 50px auto 0 auto;
|
margin: 50px auto 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main .txt h1 {
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
main div.txt h2 {
|
main div.txt h2 {
|
||||||
margin: 0 0 50px 0;
|
margin: 0 0 50px 0;
|
||||||
}
|
}
|
||||||
@@ -276,10 +281,6 @@ main .technologies img {
|
|||||||
margin: 20px;
|
margin: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
main .technologies h1 {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
background: #414040;
|
background: #414040;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -320,7 +321,7 @@ footer nav ul li a:hover {
|
|||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 1100px) {
|
@media screen and (max-width: 1200px) {
|
||||||
header section #id_welcome {
|
header section #id_welcome {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
{% trans_default_domain 'FOSUserBundle' %}
|
{% trans_default_domain 'FOSUserBundle' %}
|
||||||
|
|
||||||
{% block title %} - Sign up{% endblock %}
|
{% block title %} - Registration{% endblock %}
|
||||||
|
|
||||||
{% block fos_user_content %}
|
{% block fos_user_content %}
|
||||||
<section class="header-content">
|
<section class="header-content">
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
border="0"/>
|
border="0"/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<h1> Sign up </h1>
|
<h1> Registration </h1>
|
||||||
<div class="db">
|
<div class="db">
|
||||||
<form action="{{ path('fos_user_registration_register') }}"
|
<form action="{{ path('fos_user_registration_register') }}"
|
||||||
method="post">
|
method="post">
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
{% trans_default_domain 'FOSUserBundle' %}
|
{% trans_default_domain 'FOSUserBundle' %}
|
||||||
|
|
||||||
{% block title %} - Sign in{% endblock %}
|
{% block title %} - Login{% endblock %}
|
||||||
|
|
||||||
{% block fos_user_content %}
|
{% block fos_user_content %}
|
||||||
{% if error %}
|
{% if error %}
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
border="0"/>
|
border="0"/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<h1>Sign in</h1>
|
<h1>Login</h1>
|
||||||
<form action="{{ path("fos_user_security_check") }}" method="post"
|
<form action="{{ path("fos_user_security_check") }}" method="post"
|
||||||
class="ac-custom ac-checkbox ac-boxfill">
|
class="ac-custom ac-checkbox ac-boxfill">
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
<input type="text" id="username" name="_username" value="{{ last_username }}"
|
<input type="text" id="username" name="_username" value="{{ last_username }}"
|
||||||
class="form-input form-username"
|
class="form-input form-username"
|
||||||
placeholder="Username or Email"/>
|
placeholder="Username or Email" autofocus />
|
||||||
|
|
||||||
<input type="password" id="password" name="_password"
|
<input type="password" id="password" name="_password"
|
||||||
class="form-input"
|
class="form-input"
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/JQuery-Snowfall/1.7.4/snowfall.jquery.min.js"
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/JQuery-Snowfall/1.7.4/snowfall.jquery.min.js"
|
||||||
type="text/javascript"></script>
|
type="text/javascript"></script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(function () {
|
$(function () {
|
||||||
$(document).snowfall({deviceorientation: true, round: true, minSize: 5, maxSize: 8});
|
$(document).snowfall({deviceorientation: true, round: true, minSize: 5, maxSize: 8});
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ class MyFOSUBUserProvider extends BaseFOSUBProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
$user->setFacebookId($response->getUsername());
|
$user->setFacebookId($response->getUsername());
|
||||||
|
$user->setFacebookAccessToken($response->getAccessToken());
|
||||||
$user->setEmail($response->getEmail());
|
$user->setEmail($response->getEmail());
|
||||||
$user->setEmailCanonical($response->getEmail());
|
$user->setEmailCanonical($response->getEmail());
|
||||||
$user->setUsername($this->slug($response->getRealName()));
|
$user->setUsername($this->slug($response->getRealName()));
|
||||||
|
|||||||
@@ -2,15 +2,18 @@
|
|||||||
|
|
||||||
namespace Mine\SeekerBundle\Controller;
|
namespace Mine\SeekerBundle\Controller;
|
||||||
|
|
||||||
//use CL\Slack\Payload\ChatPostMessagePayload;
|
|
||||||
//use CL\Slack\Payload\UsersListPayload;
|
|
||||||
//use CL\Slack\Transport\ApiClient;
|
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class GameController
|
||||||
|
*
|
||||||
|
* @package Mine\SeekerBundle\Controller
|
||||||
|
* @author system7 <https://www.laszlolang.com>
|
||||||
|
*/
|
||||||
class GameController extends Controller
|
class GameController extends Controller
|
||||||
{
|
{
|
||||||
public function indexAction()
|
public function indexAction(Request $request)
|
||||||
{
|
{
|
||||||
// $apiClient = new ApiClient('xoxp-107639806167-107029084564-115427085733-cccaa4f96c89c87ce680c7f22acfd001');
|
// $apiClient = new ApiClient('xoxp-107639806167-107029084564-115427085733-cccaa4f96c89c87ce680c7f22acfd001');
|
||||||
//
|
//
|
||||||
@@ -33,14 +36,25 @@ class GameController extends Controller
|
|||||||
// dump($response->getErrorExplanation());
|
// dump($response->getErrorExplanation());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return $this->render('MineSeekerBundle:Game:index.html.twig');
|
return $this->render('MineSeekerBundle:Game:index.html.twig', array(
|
||||||
|
'env' => $this->container->getParameter('kernel.environment'),
|
||||||
|
'ssl' => $request->isSecure() ? 'true' : 'false',
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function playAction(Request $request)
|
public function playAction(Request $request)
|
||||||
{
|
{
|
||||||
return $this->render('MineSeekerBundle:Game:play.html.twig', array(
|
return $this->render('MineSeekerBundle:Game:play.html.twig', array(
|
||||||
'env' => $this->container->getParameter('kernel.environment'),
|
'env' => $this->container->getParameter('kernel.environment'),
|
||||||
'ssl' => $request->isSecure() ? 'true' : 'false'
|
'ssl' => $request->isSecure() ? 'true' : 'false',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rePlayAction(Request $request)
|
||||||
|
{
|
||||||
|
return $this->render('MineSeekerBundle:Game:play.html.twig', array(
|
||||||
|
'env' => $this->container->getParameter('kernel.environment'),
|
||||||
|
'ssl' => $request->isSecure() ? 'true' : 'false',
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ namespace Mine\SeekerBundle\Entity;
|
|||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gamer
|
* Class Gamer
|
||||||
|
*
|
||||||
|
* @package Mine\SeekerBundle\Entity
|
||||||
|
* @author system7 <https://www.laszlolang.com>
|
||||||
*
|
*
|
||||||
* @ORM\Table(name="gamer")
|
* @ORM\Table(name="gamer")
|
||||||
* @ORM\Entity(repositoryClass="Mine\SeekerBundle\Repository\GamerRepository")
|
* @ORM\Entity(repositoryClass="Mine\SeekerBundle\Repository\GamerRepository")
|
||||||
|
|||||||
@@ -7,7 +7,10 @@ use Doctrine\Common\Collections\Collection;
|
|||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Grid
|
* Class Grid
|
||||||
|
*
|
||||||
|
* @package Mine\SeekerBundle\Entity
|
||||||
|
* @author system7 <https://www.laszlolang.com>
|
||||||
*
|
*
|
||||||
* @ORM\Table(name="grid")
|
* @ORM\Table(name="grid")
|
||||||
* @ORM\Entity(repositoryClass="Mine\SeekerBundle\Repository\GridRepository")
|
* @ORM\Entity(repositoryClass="Mine\SeekerBundle\Repository\GridRepository")
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ namespace Mine\SeekerBundle\Entity;
|
|||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GridRow
|
* Class GridRow
|
||||||
|
*
|
||||||
|
* @package Mine\SeekerBundle\Entity
|
||||||
|
* @author system7 <https://www.laszlolang.com>
|
||||||
*
|
*
|
||||||
* @ORM\Table(name="grid_row")
|
* @ORM\Table(name="grid_row")
|
||||||
* @ORM\Entity(repositoryClass="Mine\SeekerBundle\Repository\GridRowRepository")
|
* @ORM\Entity(repositoryClass="Mine\SeekerBundle\Repository\GridRowRepository")
|
||||||
|
|||||||
@@ -8,7 +8,10 @@ use Doctrine\ORM\Mapping as ORM;
|
|||||||
use Jotunheimr\UserBundle\Entity\User;
|
use Jotunheimr\UserBundle\Entity\User;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PlayedGame
|
* Class PlayedGame
|
||||||
|
*
|
||||||
|
* @package Mine\SeekerBundle\Entity
|
||||||
|
* @author system7 <https://www.laszlolang.com>
|
||||||
*
|
*
|
||||||
* @ORM\Table(name="played_game")
|
* @ORM\Table(name="played_game")
|
||||||
* @ORM\Entity(repositoryClass="Mine\SeekerBundle\Repository\PlayedGameRepository")
|
* @ORM\Entity(repositoryClass="Mine\SeekerBundle\Repository\PlayedGameRepository")
|
||||||
|
|||||||
@@ -443,4 +443,52 @@ class PlayedGame
|
|||||||
{
|
{
|
||||||
return $this->resign;
|
return $this->resign;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set created
|
||||||
|
*
|
||||||
|
* @param \DateTime $created
|
||||||
|
*
|
||||||
|
* @return PlayedGame
|
||||||
|
*/
|
||||||
|
public function setCreated($created)
|
||||||
|
{
|
||||||
|
$this->created = $created;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get created
|
||||||
|
*
|
||||||
|
* @return \DateTime
|
||||||
|
*/
|
||||||
|
public function getCreated()
|
||||||
|
{
|
||||||
|
return $this->created;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set updated
|
||||||
|
*
|
||||||
|
* @param \DateTime $updated
|
||||||
|
*
|
||||||
|
* @return PlayedGame
|
||||||
|
*/
|
||||||
|
public function setUpdated($updated)
|
||||||
|
{
|
||||||
|
$this->updated = $updated;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get updated
|
||||||
|
*
|
||||||
|
* @return \DateTime
|
||||||
|
*/
|
||||||
|
public function getUpdated()
|
||||||
|
{
|
||||||
|
return $this->updated;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ namespace Mine\SeekerBundle\Entity;
|
|||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Step
|
* Class Step
|
||||||
|
*
|
||||||
|
* @package Mine\SeekerBundle\Entity
|
||||||
|
* @author system7 <https://www.laszlolang.com>
|
||||||
*
|
*
|
||||||
* @ORM\Table(name="step")
|
* @ORM\Table(name="step")
|
||||||
* @ORM\Entity(repositoryClass="Mine\SeekerBundle\Repository\StepRepository")
|
* @ORM\Entity(repositoryClass="Mine\SeekerBundle\Repository\StepRepository")
|
||||||
|
|||||||
@@ -162,4 +162,28 @@ class Step
|
|||||||
{
|
{
|
||||||
return $this->wBomb;
|
return $this->wBomb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set created
|
||||||
|
*
|
||||||
|
* @param \DateTime $created
|
||||||
|
*
|
||||||
|
* @return Step
|
||||||
|
*/
|
||||||
|
public function setCreated($created)
|
||||||
|
{
|
||||||
|
$this->created = $created;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get created
|
||||||
|
*
|
||||||
|
* @return \DateTime
|
||||||
|
*/
|
||||||
|
public function getCreated()
|
||||||
|
{
|
||||||
|
return $this->created;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,12 @@ use Gos\Bundle\WebSocketBundle\Event\ClientErrorEvent;
|
|||||||
use Gos\Bundle\WebSocketBundle\Event\ServerEvent;
|
use Gos\Bundle\WebSocketBundle\Event\ServerEvent;
|
||||||
use Gos\Bundle\WebSocketBundle\Event\ClientRejectedEvent;
|
use Gos\Bundle\WebSocketBundle\Event\ClientRejectedEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class MineseekerClientEventListener
|
||||||
|
*
|
||||||
|
* @package Mine\SeekerBundle\EventListener
|
||||||
|
* @author system7 <https://www.laszlolang.com>
|
||||||
|
*/
|
||||||
class MineseekerClientEventListener
|
class MineseekerClientEventListener
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,8 +4,13 @@ namespace Mine\SeekerBundle\Periodic;
|
|||||||
|
|
||||||
use Gos\Bundle\WebSocketBundle\Periodic\PdoPeriodicPing;
|
use Gos\Bundle\WebSocketBundle\Periodic\PdoPeriodicPing;
|
||||||
use Gos\Bundle\WebSocketBundle\Periodic\PeriodicInterface;
|
use Gos\Bundle\WebSocketBundle\Periodic\PeriodicInterface;
|
||||||
use PDO;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class MinePeriodic
|
||||||
|
*
|
||||||
|
* @package Mine\SeekerBundle\Periodic
|
||||||
|
* @author system7 <https://www.laszlolang.com>
|
||||||
|
*/
|
||||||
class MinePeriodic implements PeriodicInterface
|
class MinePeriodic implements PeriodicInterface
|
||||||
{
|
{
|
||||||
/** @var PdoPeriodicPing */
|
/** @var PdoPeriodicPing */
|
||||||
@@ -19,7 +24,8 @@ class MinePeriodic implements PeriodicInterface
|
|||||||
/**
|
/**
|
||||||
* This function is executed every 5 seconds.
|
* This function is executed every 5 seconds.
|
||||||
*
|
*
|
||||||
* For more advanced functionality, try injecting a Topic Service to perform actions on your connections every x seconds.
|
* For more advanced functionality, try injecting a Topic Service to perform actions on your connections every x
|
||||||
|
* seconds.
|
||||||
*/
|
*/
|
||||||
public function tick()
|
public function tick()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
namespace Mine\SeekerBundle\Repository;
|
namespace Mine\SeekerBundle\Repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GamerRepository
|
* Class GamerRepository
|
||||||
*
|
*
|
||||||
* This class was generated by the Doctrine ORM. Add your own custom
|
* @package Mine\SeekerBundle\Repository
|
||||||
* repository methods below.
|
* @author system7 <https://www.laszlolang.com>
|
||||||
*/
|
*/
|
||||||
class GamerRepository extends \Doctrine\ORM\EntityRepository
|
class GamerRepository extends \Doctrine\ORM\EntityRepository
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
namespace Mine\SeekerBundle\Repository;
|
namespace Mine\SeekerBundle\Repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GridColRepository
|
* Class GridColRepository
|
||||||
*
|
*
|
||||||
* This class was generated by the Doctrine ORM. Add your own custom
|
* @package Mine\SeekerBundle\Repository
|
||||||
* repository methods below.
|
* @author system7 <https://www.laszlolang.com>
|
||||||
*/
|
*/
|
||||||
class GridColRepository extends \Doctrine\ORM\EntityRepository
|
class GridColRepository extends \Doctrine\ORM\EntityRepository
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
namespace Mine\SeekerBundle\Repository;
|
namespace Mine\SeekerBundle\Repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GridRepository
|
* Class GridRepository
|
||||||
*
|
*
|
||||||
* This class was generated by the Doctrine ORM. Add your own custom
|
* @package Mine\SeekerBundle\Repository
|
||||||
* repository methods below.
|
* @author system7 <https://www.laszlolang.com>
|
||||||
*/
|
*/
|
||||||
class GridRepository extends \Doctrine\ORM\EntityRepository
|
class GridRepository extends \Doctrine\ORM\EntityRepository
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ namespace Mine\SeekerBundle\Repository;
|
|||||||
use Doctrine\ORM\EntityRepository;
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GridRowRepository
|
* Class GridRowRepository
|
||||||
*
|
*
|
||||||
* This class was generated by the Doctrine ORM. Add your own custom
|
* @package Mine\SeekerBundle\Repository
|
||||||
* repository methods below.
|
* @author system7 <https://www.laszlolang.com>
|
||||||
*/
|
*/
|
||||||
class GridRowRepository extends EntityRepository
|
class GridRowRepository extends EntityRepository
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
namespace Mine\SeekerBundle\Repository;
|
namespace Mine\SeekerBundle\Repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PlayedGameRepository
|
* Class PlayedGameRepository
|
||||||
*
|
*
|
||||||
* This class was generated by the Doctrine ORM. Add your own custom
|
* @package Mine\SeekerBundle\Repository
|
||||||
* repository methods below.
|
* @author system7 <https://www.laszlolang.com>
|
||||||
*/
|
*/
|
||||||
class PlayedGameRepository extends \Doctrine\ORM\EntityRepository
|
class PlayedGameRepository extends \Doctrine\ORM\EntityRepository
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
namespace Mine\SeekerBundle\Repository;
|
namespace Mine\SeekerBundle\Repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* StepRepository
|
* Class StepRepository
|
||||||
*
|
*
|
||||||
* This class was generated by the Doctrine ORM. Add your own custom
|
* @package Mine\SeekerBundle\Repository
|
||||||
* repository methods below.
|
* @author system7 <https://www.laszlolang.com>
|
||||||
*/
|
*/
|
||||||
class StepRepository extends \Doctrine\ORM\EntityRepository
|
class StepRepository extends \Doctrine\ORM\EntityRepository
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Topic Configuration
|
# MineSeeker Topic Configuration
|
||||||
mineseeker_topic:
|
mineseeker_topic:
|
||||||
channel: mineseeker/channel/{game}
|
channel: mineseeker/channel/{game}
|
||||||
handler:
|
handler:
|
||||||
@@ -7,6 +7,12 @@ mineseeker_topic:
|
|||||||
# method:
|
# method:
|
||||||
# path: '[a-z1-9A-Z]+'
|
# path: '[a-z1-9A-Z]+'
|
||||||
|
|
||||||
|
# UserList Topic Configuration
|
||||||
|
userList_topic:
|
||||||
|
channel: mineseeker/userList
|
||||||
|
handler:
|
||||||
|
callback: 'userlist.topic'
|
||||||
|
|
||||||
# Remote Procedure Call Configuration
|
# Remote Procedure Call Configuration
|
||||||
mineseeker_rpc:
|
mineseeker_rpc:
|
||||||
channel: mineseeker-rpc/{method}
|
channel: mineseeker-rpc/{method}
|
||||||
|
|||||||
@@ -13,6 +13,11 @@ MineSeekerBundle_gamePlayWId:
|
|||||||
defaults: { _controller: MineSeekerBundle:Game:play }
|
defaults: { _controller: MineSeekerBundle:Game:play }
|
||||||
schemes: [https]
|
schemes: [https]
|
||||||
|
|
||||||
|
MineSeekerBundle_gameReplay:
|
||||||
|
path: /re-play/{gameAssoc}
|
||||||
|
defaults: { _controller: MineSeekerBundle:Game:rePlay }
|
||||||
|
schemes: [https]
|
||||||
|
|
||||||
MineSeekerBundle_slack:
|
MineSeekerBundle_slack:
|
||||||
path: /slack
|
path: /slack
|
||||||
defaults: { _controller: MineSeekerBundle:Game:slack }
|
defaults: { _controller: MineSeekerBundle:Game:slack }
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ services:
|
|||||||
arguments:
|
arguments:
|
||||||
ping: '@gos_web_socket.pdo.periodic_ping'
|
ping: '@gos_web_socket.pdo.periodic_ping'
|
||||||
|
|
||||||
mineseeker.topic_sample_service:
|
mineseeker.game_service:
|
||||||
class: Mine\SeekerBundle\Topic\MineseekerTopic
|
class: Mine\SeekerBundle\Topic\MineseekerTopic
|
||||||
tags:
|
tags:
|
||||||
- { name: gos_web_socket.topic }
|
- { name: gos_web_socket.topic }
|
||||||
@@ -35,7 +35,16 @@ services:
|
|||||||
doctrine: '@doctrine.orm.entity_manager'
|
doctrine: '@doctrine.orm.entity_manager'
|
||||||
requestStack: '@request_stack'
|
requestStack: '@request_stack'
|
||||||
|
|
||||||
mineseeker.rpc_sample_service:
|
mineseeker.user_list_service:
|
||||||
|
class: Mine\SeekerBundle\Topic\UserListTopic
|
||||||
|
tags:
|
||||||
|
- { name: gos_web_socket.topic }
|
||||||
|
arguments:
|
||||||
|
clientManipulator: "@gos_web_socket.websocket.client_manipulator"
|
||||||
|
doctrine: '@doctrine.orm.entity_manager'
|
||||||
|
requestStack: '@request_stack'
|
||||||
|
|
||||||
|
mineseeker.game_rpc_service:
|
||||||
class: Mine\SeekerBundle\Rpc\MineseekerRpc
|
class: Mine\SeekerBundle\Rpc\MineseekerRpc
|
||||||
tags:
|
tags:
|
||||||
- { name: gos_web_socket.rpc }
|
- { name: gos_web_socket.rpc }
|
||||||
|
|||||||
@@ -141,7 +141,162 @@ header section div.buttons > a.small:hover {
|
|||||||
transition: all 250ms ease-in-out;
|
transition: all 250ms ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 1100px) {
|
main .user-list-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .user-list-container .user-friend {
|
||||||
|
background: #ccc;
|
||||||
|
width: 15%;
|
||||||
|
min-width: 145px;
|
||||||
|
text-align: center;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 5px;
|
||||||
|
|
||||||
|
-webkit-border-radius: 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .user-list-container .user-friend h1 {
|
||||||
|
display: block;
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .user-list-container .user-friend .img,
|
||||||
|
main .user-list-container .user-friend .img img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .user-list-container .user-friend button {
|
||||||
|
background: #83aed9;
|
||||||
|
display: inline-block;
|
||||||
|
font: bold 22px 'Rajdhani', sans-serif;
|
||||||
|
border: 1px solid #6890ba;
|
||||||
|
color: #FFFFFF;
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
-webkit-transition: all 250ms ease-in-out;
|
||||||
|
-moz-transition: all 250ms ease-in-out;
|
||||||
|
-o-transition: all 250ms ease-in-out;
|
||||||
|
transition: all 250ms ease-in-out;
|
||||||
|
-webkit-border-radius: 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .user-list-container .user-friend button:hover {
|
||||||
|
background: #86b5e1;
|
||||||
|
border: 1px solid #658fb8;
|
||||||
|
color: #FFFFFF;
|
||||||
|
|
||||||
|
-webkit-transition: all 250ms ease-in-out;
|
||||||
|
-moz-transition: all 250ms ease-in-out;
|
||||||
|
-o-transition: all 250ms ease-in-out;
|
||||||
|
transition: all 250ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .user-list-container .user-friend button.button-offline {
|
||||||
|
background: #a1a1a1;
|
||||||
|
border: 1px solid #929292;
|
||||||
|
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .user-list-container .user-friend button.button-offline:hover {
|
||||||
|
background: #a1a1a1;
|
||||||
|
border: 1px solid #929292;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .user-list-filter form {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .user-list-filter input {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-right: 0;
|
||||||
|
min-width: 300px;
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
-webkit-border-top-left-radius: 3px;
|
||||||
|
border-top-left-radius: 3px;
|
||||||
|
-webkit-border-bottom-left-radius: 3px;
|
||||||
|
border-bottom-left-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .user-list-filter button {
|
||||||
|
background: #ccc;
|
||||||
|
width: 42px;
|
||||||
|
height: 42px;
|
||||||
|
border: 0;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
-webkit-border-top-right-radius: 3px;
|
||||||
|
border-top-right-radius: 3px;
|
||||||
|
-webkit-border-bottom-right-radius: 3px;
|
||||||
|
border-bottom-right-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .user-request-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .user-request-container .user-friend {
|
||||||
|
background: #ff0000;
|
||||||
|
width: 150px;
|
||||||
|
color: #403f3f;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px;
|
||||||
|
|
||||||
|
-webkit-border-radius: 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .user-request-container h1 {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .user-request-container .img,
|
||||||
|
main .user-request-container .img img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .user-request-container button {
|
||||||
|
background: #fff;
|
||||||
|
width: 100%;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ff0000;
|
||||||
|
border: 0;
|
||||||
|
padding: 15px 5px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
-webkit-border-radius: 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
-webkit-transition: all 250ms ease-in-out;
|
||||||
|
-moz-transition: all 250ms ease-in-out;
|
||||||
|
-o-transition: all 250ms ease-in-out;
|
||||||
|
transition: all 250ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
main .user-request-container button:hover {
|
||||||
|
background: #ffc38b;
|
||||||
|
|
||||||
|
-webkit-transition: all 250ms ease-in-out;
|
||||||
|
-moz-transition: all 250ms ease-in-out;
|
||||||
|
-o-transition: all 250ms ease-in-out;
|
||||||
|
transition: all 250ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1200px) {
|
||||||
header section {
|
header section {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -166,11 +321,6 @@ header section div.buttons > a.small:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 500px) {
|
@media screen and (max-width: 500px) {
|
||||||
/*header {*/
|
|
||||||
/*min-height: 100%;*/
|
|
||||||
/*height: auto;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
header section {
|
header section {
|
||||||
width: auto;
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
src/Mine/SeekerBundle/Resources/public/images/avatar/bg-avatar-default-1.png
Executable file
BIN
src/Mine/SeekerBundle/Resources/public/images/avatar/bg-avatar-default-1.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
BIN
src/Mine/SeekerBundle/Resources/public/images/avatar/bg-avatar-default-2.png
Executable file
BIN
src/Mine/SeekerBundle/Resources/public/images/avatar/bg-avatar-default-2.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
BIN
src/Mine/SeekerBundle/Resources/public/images/avatar/bg-avatar-default-3.png
Executable file
BIN
src/Mine/SeekerBundle/Resources/public/images/avatar/bg-avatar-default-3.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
BIN
src/Mine/SeekerBundle/Resources/public/images/avatar/bg-avatar-default-4.png
Executable file
BIN
src/Mine/SeekerBundle/Resources/public/images/avatar/bg-avatar-default-4.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
BIN
src/Mine/SeekerBundle/Resources/public/images/avatar/bg-avatar-default-5.png
Executable file
BIN
src/Mine/SeekerBundle/Resources/public/images/avatar/bg-avatar-default-5.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
@@ -2,9 +2,12 @@ import React from 'react';
|
|||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import MineSeeker from './mine-seeker/app';
|
import MineSeeker from './mine-seeker/app';
|
||||||
|
|
||||||
|
let mineWrapper = document.getElementById('mine-wrapper');
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<MineSeeker env={document.getElementById('mine-wrapper').dataset.env}
|
<MineSeeker env={mineWrapper.dataset.env}
|
||||||
gameId={document.getElementById('mine-wrapper').dataset.gameId}
|
gameId={mineWrapper.dataset.gameId}
|
||||||
ssl={document.getElementById('mine-wrapper').dataset.ssl}/>,
|
webPlayerName={mineWrapper.dataset.webPlayerName}
|
||||||
document.getElementById('mine-wrapper')
|
ssl={mineWrapper.dataset.ssl}/>,
|
||||||
|
mineWrapper
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,49 +1,39 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Grid from './grid/grid';
|
|
||||||
import GridControl from './grid/grid-control';
|
import GridControl from './grid/grid-control';
|
||||||
|
import MineServices from '../mine-system/mine-services';
|
||||||
|
import MineStart from './game/start'
|
||||||
|
import MineEnd from './game/end'
|
||||||
|
import MineWebsocket from './game/websocket'
|
||||||
|
|
||||||
class MineSeeker extends React.Component {
|
class MineSeeker extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
let gameAssoc = props.gameId !== '' ? props.gameId : this.makeGameAssoc(50);
|
let services = new MineServices();
|
||||||
|
let gameAssoc = props.gameId !== '' ? props.gameId : services.randomString(50);
|
||||||
let channel = "mineseeker/channel/" + gameAssoc;
|
let channel = "mineseeker/channel/" + gameAssoc;
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
|
startProcess: new MineStart(),
|
||||||
|
endProcess: new MineEnd(),
|
||||||
|
wsProcess: new MineWebsocket(),
|
||||||
|
services: services,
|
||||||
|
|
||||||
env: props.env,
|
env: props.env,
|
||||||
ssl: props.ssl,
|
ssl: props.ssl,
|
||||||
gameInherited: props.gameId !== '',
|
gameInherited: props.gameId !== '',
|
||||||
|
webPlayerName: props.webPlayerName === '' ? null : props.webPlayerName,
|
||||||
gameAssoc: gameAssoc,
|
gameAssoc: gameAssoc,
|
||||||
channel: channel,
|
channel: channel,
|
||||||
session: null,
|
session: null,
|
||||||
createGrid: false,
|
createGrid: false,
|
||||||
stepCache: [],
|
stepCache: [],
|
||||||
connectionLost: false,
|
connectionLost: false,
|
||||||
end: false
|
end: false,
|
||||||
|
replay: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
makeGameAssoc(len) {
|
|
||||||
let text = "";
|
|
||||||
let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
||||||
for (let i = 0; i < len; i++) {
|
|
||||||
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
currectGridSize() {
|
|
||||||
let $field = $('#mine-wrapper .grid');
|
|
||||||
$field.height($field.width());
|
|
||||||
|
|
||||||
$field = $('#mine-wrapper .grid .field-wrapper');
|
|
||||||
$field.height($field.width());
|
|
||||||
|
|
||||||
$('#mine-wrapper .grid .field-wrapper .field')
|
|
||||||
.height($field.width())
|
|
||||||
.css('line-height', ($field.width() - 2) + 'px');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* STEP
|
* STEP
|
||||||
*
|
*
|
||||||
@@ -71,338 +61,21 @@ class MineSeeker extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* START
|
* Unregistered
|
||||||
|
* http://mine.dev/re-play/I1Bx9UHZP5CWDnTZHpJqGTlkzehblfsbfz4A4xYaH9HFhBK2aN
|
||||||
*
|
*
|
||||||
* @param payload
|
* Registered - Admin -> Lang
|
||||||
|
* http://mine.dev/re-play/bazmegdflgkjndfgkhjn
|
||||||
*/
|
*/
|
||||||
makeGameStart(payload) {
|
|
||||||
/** every time the blue starts */
|
|
||||||
this.refs.gridControl.refs.userControl.setState({activePlayer: 1});
|
|
||||||
|
|
||||||
/** Set up player names w/ server data */
|
|
||||||
this.refs.gridControl.refs.userControl.refs.red.setState({
|
|
||||||
name: payload.users.red !== '' ? payload.users.red : payload.users.redAnon,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.refs.gridControl.refs.userControl.refs.blue.setState({
|
|
||||||
name: payload.users.blue !== '' ? payload.users.blue : payload.users.blueAnon,
|
|
||||||
desc: this.refs.gridControl.state.webPlayer === 'blue'
|
|
||||||
? this.refs.gridControl.state.desc.you
|
|
||||||
: this.refs.gridControl.state.desc.buddy,
|
|
||||||
active: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.refs.gridControl.setState({overlay: false});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* THE END
|
|
||||||
*
|
|
||||||
* @param bluePoints
|
|
||||||
* @param redPoints
|
|
||||||
* @param resign
|
|
||||||
*/
|
|
||||||
makeGameEndIfItEnds(bluePoints, redPoints, resign = false) {
|
|
||||||
let redWins = redPoints > 25,
|
|
||||||
blueWins = bluePoints > 25;
|
|
||||||
|
|
||||||
if (redWins || blueWins || resign) {
|
|
||||||
this.refs.gridControl.state.sound.won.play();
|
|
||||||
|
|
||||||
if (false === resign) {
|
|
||||||
this.refs.gridControl.setState({
|
|
||||||
overlay: true,
|
|
||||||
overlayTitle: (redWins ? 'Red' : 'Blue') + " wins the game!",
|
|
||||||
overlaySubTitle: "Play again!"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.refs.gridControl.showLeftMines();
|
|
||||||
|
|
||||||
this.refs.gridControl.refs.userControl.setState({activePlayer: false});
|
|
||||||
this.refs.gridControl.refs.userControl.refs.red.setState({desc: ""});
|
|
||||||
this.refs.gridControl.refs.userControl.refs.blue.setState({desc: ""});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resignProcess(color) {
|
|
||||||
this.refs.gridControl.setState({
|
|
||||||
overlay: true,
|
|
||||||
overlayTitle: color === this.refs.gridControl.state.webPlayer
|
|
||||||
? "You have been give up"
|
|
||||||
: "Your opponent has been resigned",
|
|
||||||
overlaySubTitle: color === this.refs.gridControl.state.webPlayer
|
|
||||||
? "You LOSE!"
|
|
||||||
: "You WIN!"
|
|
||||||
});
|
|
||||||
|
|
||||||
this.setState({end: true});
|
|
||||||
|
|
||||||
this.makeGameEndIfItEnds(0, 0, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
clickResign() {
|
|
||||||
/** PUBLISH */
|
|
||||||
this.state.session.publish(this.state.channel, {
|
|
||||||
'resign': this.refs.gridControl.refs.userControl.state.activePlayer ? 'blue' : 'red'
|
|
||||||
});
|
|
||||||
this.resignProcess(this.refs.gridControl.state.webPlayer);
|
|
||||||
}
|
|
||||||
|
|
||||||
clickResignCancel() {
|
|
||||||
this.refs.gridControl.setState({
|
|
||||||
overlay: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** RESIGN */
|
|
||||||
resign() {
|
|
||||||
let users = this.refs.gridControl.refs.userControl,
|
|
||||||
activePlayer = users.state.activePlayer ? 'blue' : 'red';
|
|
||||||
|
|
||||||
if (this.refs.gridControl.state.webPlayer === activePlayer) {
|
|
||||||
this.refs.gridControl.setState({
|
|
||||||
overlay: true,
|
|
||||||
overlayTitle: "Are u sure u want to resign?!",
|
|
||||||
overlaySubTitle: <div className="resign">
|
|
||||||
<a onClick={this.clickResign.bind(this)}>Yes</a>
|
|
||||||
<a onClick={this.clickResignCancel.bind(this)}>No!</a>
|
|
||||||
</div>
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus
|
|
||||||
* @see https://developers.facebook.com/docs/sharing/reference/send-dialog
|
|
||||||
* @see https://developers.facebook.com/docs/plugins/share-button/
|
|
||||||
*/
|
|
||||||
clickFBShare() {
|
|
||||||
let display = 'popup';
|
|
||||||
|
|
||||||
FB.getLoginStatus(function (response) {
|
|
||||||
display = response.status === 'connected'
|
|
||||||
? 'dialog'
|
|
||||||
: 'popup';
|
|
||||||
});
|
|
||||||
|
|
||||||
FB.ui({
|
|
||||||
method: 'send',
|
|
||||||
display: display,
|
|
||||||
link: window.location.href + '/' + this.state.gameAssoc,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
wInit(session, gridServer, gridClient) {
|
|
||||||
this.setState({session: session});
|
|
||||||
|
|
||||||
/** save session to GridControl */
|
|
||||||
/** render grid fields - @see #12 */
|
|
||||||
this.refs.gridControl.setState({
|
|
||||||
grid: this.state.gameInherited ? gridServer : gridClient,
|
|
||||||
channel: this.state.channel,
|
|
||||||
desc: {
|
|
||||||
buddy: <div>
|
|
||||||
Your buddy is <br/>
|
|
||||||
making a <br/>
|
|
||||||
move.
|
|
||||||
</div>,
|
|
||||||
you: <div>
|
|
||||||
It is your turn! <br/>
|
|
||||||
Make a move.
|
|
||||||
</div>
|
|
||||||
},
|
|
||||||
overlay: true,
|
|
||||||
overlayTitle: "We are waiting for your opponent...",
|
|
||||||
overlaySubTitle: this.state.gameAssoc
|
|
||||||
?
|
|
||||||
<div>
|
|
||||||
<h3>Share this unique link w/ your opponent</h3>
|
|
||||||
<div className="clippy">
|
|
||||||
<input id="foo"
|
|
||||||
defaultValue={window.location.href + '/' + this.state.gameAssoc}/>
|
|
||||||
</div>
|
|
||||||
{this.state.env !== 'dev' &&
|
|
||||||
<a onClick={this.clickFBShare.bind(this)}>Share in Facebook message</a>
|
|
||||||
}
|
|
||||||
{this.state.env === 'dev' &&
|
|
||||||
<a href={"/play/" + this.state.gameAssoc} target="_blank">Play w/ me!</a>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
: '',
|
|
||||||
renderGridFields: this.state.gameAssoc
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
wSubscribe(payload, rpcUsers = null) {
|
|
||||||
this.state.env === 'dev' && console.info(
|
|
||||||
(typeof payload.user !== 'undefined' ? payload.user : 'user') + " has been subscribed to the channel!"
|
|
||||||
);
|
|
||||||
|
|
||||||
let firstUser = !rpcUsers;
|
|
||||||
|
|
||||||
this.refs.gridControl.state.webPlayer === null && this.refs.gridControl.setState({
|
|
||||||
webPlayer: payload.user === payload.users.blue ||
|
|
||||||
(
|
|
||||||
firstUser && payload.users.blueAnon !== '' ||
|
|
||||||
!firstUser && (rpcUsers.blueAnon === '' && rpcUsers.blue === '')
|
|
||||||
)
|
|
||||||
? 'blue' : 'red'
|
|
||||||
});
|
|
||||||
|
|
||||||
/** rwd */
|
|
||||||
(900 > $(document).width()) && this.currectGridSize();
|
|
||||||
|
|
||||||
/** every user has been came */
|
|
||||||
if (
|
|
||||||
payload.userCnt === 2 &&
|
|
||||||
(
|
|
||||||
!this.state.connectionLost ||
|
|
||||||
this.state.connectionLost && false === this.refs.gridControl.refs.userControl.state.activePlayer && !this.state.end
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
this.makeGameStart(payload);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wUnsubscribe(payload) {
|
|
||||||
this.state.env === 'dev' && console.info(payload.msg);
|
|
||||||
|
|
||||||
this.refs.gridControl.setState({
|
|
||||||
overlay: true,
|
|
||||||
overlayTitle: "The connection has been lost w/ your friend...",
|
|
||||||
overlaySubTitle: "Please, restart the game!"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
wTopic(payload) {
|
|
||||||
/** Auto-Step if this player is not the current user */
|
|
||||||
if (this.refs.gridControl.state.webPlayer !== payload.data.player) {
|
|
||||||
if (null === payload.data.resign) {
|
|
||||||
this.state.env === 'dev' && console.warn(payload.user + " has been stepped to coords: " + payload.data.coords[0] + ', ' + payload.data.coords[1]);
|
|
||||||
this.state.env === 'dev' && console.warn('Opponent stepped: Auto-Step process');
|
|
||||||
|
|
||||||
this.refs.gridControl.refs.userControl.setState({bombSelected: payload.data.bomb});
|
|
||||||
|
|
||||||
/** STEP */
|
|
||||||
let points = this.makePointsCalcAndStep(payload.data.coords);
|
|
||||||
|
|
||||||
/** THE END */
|
|
||||||
this.makeGameEndIfItEnds(points.blue, points.red);
|
|
||||||
} else {
|
|
||||||
/** RESIGN */
|
|
||||||
/** THE END */
|
|
||||||
this.resignProcess(payload.data.resign);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Connect - Subscribe */
|
|
||||||
subscribe(rpcUsers = null) {
|
|
||||||
this.state.session.subscribe(
|
|
||||||
this.state.channel,
|
|
||||||
(uri, payload, log) => {
|
|
||||||
let isTopicEvent = typeof payload.data !== 'undefined',
|
|
||||||
isNotUnsubscribe = typeof payload.msg === 'undefined';
|
|
||||||
|
|
||||||
/** CONNECTION */
|
|
||||||
if (isTopicEvent) {
|
|
||||||
this.wTopic(payload);
|
|
||||||
} else {
|
|
||||||
if (isNotUnsubscribe) {
|
|
||||||
this.wSubscribe(payload, rpcUsers);
|
|
||||||
} else {
|
|
||||||
this.wUnsubscribe(payload);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** RECONNECTION */
|
|
||||||
if (payload.userCnt === 2 && this.state.connectionLost) {
|
|
||||||
this.state.env === 'dev' && console.info('Reconnection process');
|
|
||||||
|
|
||||||
/** PUBLISH */
|
|
||||||
let cache = this.state.stepCache;
|
|
||||||
cache.forEach((item) => this.state.session.publish(this.state.channel, item));
|
|
||||||
this.setState({connectionLost: false, stepCache: []});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
connectWithWebsocket() {
|
|
||||||
/** Create Websocket w/ Bahnhof.js */
|
|
||||||
let websocket = WS.connect(
|
|
||||||
this.state.env === 'dev'
|
|
||||||
? "ws://mine.dev:6450"
|
|
||||||
// : (this.state.ssl === 'true' ? "wss" : "ws") + "://" + window.location.hostname + ":6450/"
|
|
||||||
: (this.state.ssl === 'true' ? "wss" : "ws") + "://www.mineseeker.ninja:6450/"
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connect
|
|
||||||
* Session is an Autobahn JS WAMP session.
|
|
||||||
*/
|
|
||||||
websocket.on("socket/connect", (session) => {
|
|
||||||
this.state.env === 'dev' && console.info("Successfully connected to the Server!");
|
|
||||||
|
|
||||||
if (!this.state.connectionLost) {
|
|
||||||
let gridClient = this.state.gameInherited || new Grid().state.grid;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connect - RPC
|
|
||||||
* Send grid information to the server
|
|
||||||
*/
|
|
||||||
session
|
|
||||||
.call(
|
|
||||||
this.state.gameInherited ? "mineseeker-rpc/connectGame" : "mineseeker-rpc/startGame",
|
|
||||||
this.state.gameInherited ? this.state.gameAssoc : [Base64.encode(JSON.stringify(gridClient)), this.state.gameAssoc]
|
|
||||||
)
|
|
||||||
.then(
|
|
||||||
(data) => {
|
|
||||||
this.state.env === 'dev' && console.info('RPC has been called');
|
|
||||||
|
|
||||||
let serverData = data[0] !== true
|
|
||||||
? JSON.parse(Base64.decode(data))
|
|
||||||
: data;
|
|
||||||
|
|
||||||
/** Check the grid if the user is inherited @see #30 */
|
|
||||||
if ((this.state.gameInherited && null !== serverData.grid) || !this.state.gameInherited) {
|
|
||||||
this.wInit(session, serverData.grid, gridClient);
|
|
||||||
this.subscribe(this.state.gameInherited && serverData.users);
|
|
||||||
} else {
|
|
||||||
this.refs.gridControl.setState({
|
|
||||||
overlay: true,
|
|
||||||
overlayTitle: "This channel does not exists!",
|
|
||||||
overlaySubTitle: <a href={"/play"} target="_self">Restart game!</a>
|
|
||||||
});
|
|
||||||
|
|
||||||
console.error("This channel does not exists!");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(error, desc) => this.state.env === 'dev' && console.error(["RPC Error", error, desc])
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this.setState({session: session});
|
|
||||||
this.subscribe();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DisConnect
|
|
||||||
* Error provides us with some insight into the disconnection: error.reason and error.code
|
|
||||||
*/
|
|
||||||
websocket.on("socket/disconnect", (error) => {
|
|
||||||
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(function () {
|
|
||||||
this.componentDidMount();
|
|
||||||
}.bind(this), 500);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** After rendering */
|
/** After rendering */
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.connectWithWebsocket();
|
/** is it a REPLAY */
|
||||||
|
window.location.pathname.indexOf('re-play') > 0
|
||||||
|
? this.setState({replay: true})
|
||||||
|
: this.setState({replay: false});
|
||||||
|
|
||||||
|
this.state.wsProcess.connectWithWebsocket(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -427,7 +100,7 @@ class MineSeeker extends React.Component {
|
|||||||
let points = this.makePointsCalcAndStep(coords);
|
let points = this.makePointsCalcAndStep(coords);
|
||||||
|
|
||||||
/** THE END */
|
/** THE END */
|
||||||
this.makeGameEndIfItEnds(points.blue, points.red);
|
this.state.endProcess.makeGameEndIfItEnds(this, points.blue, points.red);
|
||||||
|
|
||||||
let dataPack = {
|
let dataPack = {
|
||||||
'coords': coords,
|
'coords': coords,
|
||||||
@@ -452,7 +125,7 @@ class MineSeeker extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<GridControl ref="gridControl"
|
<GridControl ref="gridControl"
|
||||||
env={this.props.env === 'dev'}
|
env={this.props.env === 'dev'}
|
||||||
resign={this.resign.bind(this)}
|
resign={this.state.endProcess.resign.bind(this.state.endProcess, this)}
|
||||||
onClick={this.onClick.bind(this)}/>
|
onClick={this.onClick.bind(this)}/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
class MineEnd extends React.Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
makeGameEndIfItEnds(app, bluePoints, redPoints, resign = false) {
|
||||||
|
let redWins = redPoints > 25,
|
||||||
|
blueWins = bluePoints > 25,
|
||||||
|
gridControl = app.refs.gridControl,
|
||||||
|
userControl = app.refs.gridControl.refs.userControl,
|
||||||
|
bluePlayer = userControl.refs.blue,
|
||||||
|
redPlayer = userControl.refs.red;
|
||||||
|
|
||||||
|
if (redWins || blueWins || resign) {
|
||||||
|
gridControl.state.sound.won.play();
|
||||||
|
|
||||||
|
/** it is NOT a RESIGN */
|
||||||
|
if (false === resign) {
|
||||||
|
gridControl.setState({
|
||||||
|
overlay: true,
|
||||||
|
overlayTitle: (redWins ? 'Red' : 'Blue') + " wins the game!",
|
||||||
|
overlaySubTitle: "Play again!"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
gridControl.showLeftMines();
|
||||||
|
userControl.setState({activePlayer: false});
|
||||||
|
redPlayer.setState({desc: ""});
|
||||||
|
bluePlayer.setState({desc: ""});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resignProcess(app, webPlayer) {
|
||||||
|
let gridControl = app.refs.gridControl;
|
||||||
|
|
||||||
|
gridControl.setState({
|
||||||
|
overlay: true,
|
||||||
|
overlayTitle: webPlayer === gridControl.state.webPlayer
|
||||||
|
? "You have been give up"
|
||||||
|
: "Your opponent has been resigned",
|
||||||
|
overlaySubTitle: webPlayer === gridControl.state.webPlayer
|
||||||
|
? "You LOSE!"
|
||||||
|
: "You WIN!"
|
||||||
|
});
|
||||||
|
|
||||||
|
app.setState({end: true});
|
||||||
|
this.makeGameEndIfItEnds(app, 0, 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
clickResign(app) {
|
||||||
|
let gridControl = app.refs.gridControl,
|
||||||
|
userControl = app.refs.gridControl.refs.userControl;
|
||||||
|
|
||||||
|
/** REMOTE */
|
||||||
|
app.state.session.publish(app.state.channel, {
|
||||||
|
'resign': userControl.state.activePlayer ? 'blue' : 'red'
|
||||||
|
});
|
||||||
|
|
||||||
|
/** LOCAL */
|
||||||
|
this.resignProcess(app, gridControl.state.webPlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
clickResignCancel(gridControl) {
|
||||||
|
gridControl.setState({overlay: false});
|
||||||
|
}
|
||||||
|
|
||||||
|
resign(app) {
|
||||||
|
let gridControl = app.refs.gridControl,
|
||||||
|
userControl = app.refs.gridControl.refs.userControl,
|
||||||
|
activePlayer = userControl.state.activePlayer ? 'blue' : 'red';
|
||||||
|
|
||||||
|
if (gridControl.state.webPlayer === activePlayer) {
|
||||||
|
gridControl.setState({
|
||||||
|
overlay: true,
|
||||||
|
overlayTitle: "Are u sure u want to resign?!",
|
||||||
|
overlaySubTitle: <div className="resign">
|
||||||
|
<a onClick={this.clickResign.bind(this, app)}>Yes</a>
|
||||||
|
<a onClick={this.clickResignCancel.bind(this, gridControl)}>No!</a>
|
||||||
|
</div>
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MineEnd;
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
class MineStart extends React.Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** MAIN */
|
||||||
|
makeGameStart(app, payload, gridControl) {
|
||||||
|
let steps = JSON.parse(Base64.decode(payload.steps)),
|
||||||
|
userControl = gridControl.refs.userControl;
|
||||||
|
|
||||||
|
if (steps.length) {
|
||||||
|
this.takeSteps(app, steps, gridControl);
|
||||||
|
} else {
|
||||||
|
/** every time the blue starts when it is not a continued game */
|
||||||
|
userControl.setState({activePlayer: 1});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setupPlayers(payload, gridControl, userControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take steps if them exists
|
||||||
|
*
|
||||||
|
* @param app
|
||||||
|
* @param steps
|
||||||
|
* @param userControl
|
||||||
|
*/
|
||||||
|
takeSteps(app, steps, userControl) {
|
||||||
|
steps.forEach((item) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
userControl.setState({bombSelected: item.wBomb});
|
||||||
|
app.makePointsCalcAndStep([item.row, item.col]);
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up player names w/ server data
|
||||||
|
*
|
||||||
|
* @param payload
|
||||||
|
* @param gridControl
|
||||||
|
* @param userControl
|
||||||
|
*/
|
||||||
|
setupPlayers(payload, gridControl, userControl) {
|
||||||
|
let redPlayer = userControl.refs.red,
|
||||||
|
bluePlayer = userControl.refs.blue;
|
||||||
|
|
||||||
|
redPlayer.setState({
|
||||||
|
name: payload.users.red !== '' ? payload.users.red : payload.users.redAnon,
|
||||||
|
});
|
||||||
|
|
||||||
|
bluePlayer.setState({
|
||||||
|
name: payload.users.blue !== '' ? payload.users.blue : payload.users.blueAnon,
|
||||||
|
desc: gridControl.state.webPlayer === 'blue'
|
||||||
|
? gridControl.state.desc.you
|
||||||
|
: gridControl.state.desc.buddy,
|
||||||
|
active: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
gridControl.setState({overlay: false});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MineStart;
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
class MineStep extends React.Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MineStep;
|
||||||
@@ -0,0 +1,266 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Grid from '../grid/grid';
|
||||||
|
|
||||||
|
class MineWebsocket extends React.Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleUnsubscribe(app, payload) {
|
||||||
|
let gridControl = app.refs.gridControl;
|
||||||
|
|
||||||
|
app.state.env === 'dev' && console.info(payload.msg);
|
||||||
|
|
||||||
|
gridControl.setState({
|
||||||
|
overlay: true,
|
||||||
|
overlayTitle: "The connection has been lost w/ your friend...",
|
||||||
|
overlaySubTitle: "Please, restart the game!"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
nbrUsersWasInGame(users) {
|
||||||
|
let nbr = 0;
|
||||||
|
|
||||||
|
nbr += users.blueAnon === "" ? 0 : 1;
|
||||||
|
nbr += users.redAnon === "" ? 0 : 1;
|
||||||
|
nbr += users.blue === "" ? 0 : 1;
|
||||||
|
nbr += users.red === "" ? 0 : 1;
|
||||||
|
|
||||||
|
return nbr;
|
||||||
|
}
|
||||||
|
|
||||||
|
wereYouInTheParty(users, user) {
|
||||||
|
return users.blueAnon === user ||
|
||||||
|
users.redAnon === user ||
|
||||||
|
users.blue === user ||
|
||||||
|
users.red === user;
|
||||||
|
}
|
||||||
|
|
||||||
|
whichWereYouInTheParty(users, user) {
|
||||||
|
return users.blue === user ? 'blue' : 'red';
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSubscribe(app, payload) {
|
||||||
|
let gridControl = app.refs.gridControl,
|
||||||
|
user = payload.user,
|
||||||
|
usersInTheParty = payload.users,
|
||||||
|
webPlayerName = app.state.webPlayerName;
|
||||||
|
|
||||||
|
app.state.env === 'dev' && console.info(
|
||||||
|
(typeof payload.user !== 'undefined' ? payload.user : 'user') + " has been subscribed to the channel!"
|
||||||
|
);
|
||||||
|
|
||||||
|
/** set up webPlayer */
|
||||||
|
if (gridControl.state.webPlayer === null) {
|
||||||
|
if (app.state.replay) {
|
||||||
|
if (this.wereYouInTheParty(usersInTheParty, webPlayerName)) {
|
||||||
|
let opponent = user === webPlayerName && webPlayerName === payload.users.red
|
||||||
|
? payload.users.blue
|
||||||
|
: payload.users.red;
|
||||||
|
|
||||||
|
gridControl.setState({
|
||||||
|
webPlayer: this.whichWereYouInTheParty(usersInTheParty, webPlayerName),
|
||||||
|
overlayTitle: "We are waitin' for " + opponent + "!",
|
||||||
|
overlaySubTitle: ""
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
gridControl.setState({
|
||||||
|
overlayTitle: "It was not your party!",
|
||||||
|
overlaySubTitle: ""
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gridControl.setState({
|
||||||
|
webPlayer: payload.user === payload.users.blue || payload.user === payload.users.blueAnon
|
||||||
|
? 'blue' : 'red',
|
||||||
|
overlaySubTitle: app.state.gameAssoc
|
||||||
|
?
|
||||||
|
<div>
|
||||||
|
<h3>Share this unique link w/ your opponent</h3>
|
||||||
|
<div className="clippy">
|
||||||
|
<input id="foo"
|
||||||
|
defaultValue={window.location.href + '/' + app.state.gameAssoc}/>
|
||||||
|
</div>
|
||||||
|
{app.state.env !== 'dev' &&
|
||||||
|
<a onClick={this.clickFBShare.bind(this, app)}>Share in Facebook message</a>
|
||||||
|
}
|
||||||
|
{app.state.env === 'dev' &&
|
||||||
|
<a href={"/play/" + app.state.gameAssoc} target="_blank">Play w/ me!</a>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
: ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload.userCnt === 2 && !app.state.end) {
|
||||||
|
app.state.startProcess.makeGameStart(app, payload, gridControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** rwd */
|
||||||
|
(900 > $(document).width()) && app.state.services.currectGridSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTopic(app, payload) {
|
||||||
|
let gridControl = app.refs.gridControl,
|
||||||
|
userControl = gridControl.refs.userControl;
|
||||||
|
|
||||||
|
/** Auto-Step if this player is not the current user */
|
||||||
|
if (gridControl.state.webPlayer !== payload.data.player) {
|
||||||
|
if (null === payload.data.resign) {
|
||||||
|
app.state.env === 'dev' && console.warn(payload.user + " has been stepped to coords: " + payload.data.coords[0] + ', ' + payload.data.coords[1]);
|
||||||
|
app.state.env === 'dev' && console.warn('Opponent stepped: Auto-Step process');
|
||||||
|
|
||||||
|
userControl.setState({bombSelected: payload.data.bomb});
|
||||||
|
|
||||||
|
/** STEP */
|
||||||
|
let points = app.makePointsCalcAndStep(payload.data.coords);
|
||||||
|
/** THE END? */
|
||||||
|
app.state.endProcess.makeGameEndIfItEnds(app, points.blue, points.red);
|
||||||
|
} else {
|
||||||
|
/** RESIGN */
|
||||||
|
/** THE END */
|
||||||
|
app.state.endProcess.resignProcess(app, payload.data.resign);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Connect - Subscribe */
|
||||||
|
subscribe(app) {
|
||||||
|
app.state.session.subscribe(
|
||||||
|
app.state.channel,
|
||||||
|
(uri, payload, log) => {
|
||||||
|
let isTopicEvent = typeof payload.data !== 'undefined',
|
||||||
|
isNotUnsubscribe = typeof payload.msg === 'undefined';
|
||||||
|
|
||||||
|
/** CONNECTION */
|
||||||
|
if (isTopicEvent) {
|
||||||
|
this.handleTopic(app, payload);
|
||||||
|
} else {
|
||||||
|
if (isNotUnsubscribe) {
|
||||||
|
this.handleSubscribe(app, payload);
|
||||||
|
} else {
|
||||||
|
this.handleUnsubscribe(app, payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** RECONNECTION */
|
||||||
|
if (payload.userCnt === 2 && app.state.connectionLost) {
|
||||||
|
app.state.env === 'dev' && console.info('Reconnection process');
|
||||||
|
|
||||||
|
let cache = app.state.stepCache;
|
||||||
|
cache.forEach((item) => app.state.session.publish(app.state.channel, item));
|
||||||
|
app.setState({connectionLost: false, stepCache: []});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
connectWithWebsocket(app) {
|
||||||
|
/** Create Websocket w/ Bahnhof.js */
|
||||||
|
let websocket = WS.connect(
|
||||||
|
app.state.env === 'dev'
|
||||||
|
? "ws://mine.dev:6450"
|
||||||
|
: (app.state.ssl === 'true' ? "wss" : "ws") + "://www.mineseeker.ninja:6450/"
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect
|
||||||
|
* Session is an Autobahn JS WAMP session.
|
||||||
|
*/
|
||||||
|
websocket.on("socket/connect", (session) => {
|
||||||
|
app.state.env === 'dev' && console.info("Successfully connected to the Server!");
|
||||||
|
|
||||||
|
if (!app.state.connectionLost) {
|
||||||
|
let gridClient = new Grid().state.grid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect - RPC
|
||||||
|
* Send grid information to the server
|
||||||
|
*/
|
||||||
|
session
|
||||||
|
.call(
|
||||||
|
"mineseeker-rpc/connectGame",
|
||||||
|
[Base64.encode(JSON.stringify(gridClient)), app.state.gameAssoc]
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
(data) => {
|
||||||
|
app.state.env === 'dev' && console.info('RPC has been called');
|
||||||
|
|
||||||
|
let grid = JSON.parse(Base64.decode(data));
|
||||||
|
|
||||||
|
this.init(app, session, grid);
|
||||||
|
this.subscribe(app);
|
||||||
|
},
|
||||||
|
(error, desc) => app.state.env === 'dev' && console.error(["RPC Error", error, desc])
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
app.setState({session: session});
|
||||||
|
this.subscribe(app);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DisConnect
|
||||||
|
* Error provides us with some insight into the disconnection: error.reason and error.code
|
||||||
|
*/
|
||||||
|
websocket.on("socket/disconnect", (error) => {
|
||||||
|
app.state.env === 'dev' && console.error("Disconnected for " + error.reason + " with code " + error.code);
|
||||||
|
|
||||||
|
error.code === 6 && app.setState({connectionLost: true});
|
||||||
|
error.code === 3 && setTimeout(function () {
|
||||||
|
app.componentDidMount();
|
||||||
|
}.bind(this), 500);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
init(app, session, grid) {
|
||||||
|
let gridControl = app.refs.gridControl;
|
||||||
|
|
||||||
|
app.setState({session: session});
|
||||||
|
|
||||||
|
/** save session to GridControl */
|
||||||
|
/** render grid fields - @see #12 */
|
||||||
|
gridControl.setState({
|
||||||
|
grid: grid,
|
||||||
|
channel: app.state.channel,
|
||||||
|
desc: {
|
||||||
|
buddy: <div>
|
||||||
|
Your buddy is <br/>
|
||||||
|
making a <br/>
|
||||||
|
move.
|
||||||
|
</div>,
|
||||||
|
you: <div>
|
||||||
|
It is your turn! <br/>
|
||||||
|
Make a move.
|
||||||
|
</div>
|
||||||
|
},
|
||||||
|
overlay: true,
|
||||||
|
overlayTitle: "We are waiting for your opponent...",
|
||||||
|
overlaySubTitle: "",
|
||||||
|
renderGridFields: app.state.gameAssoc
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus
|
||||||
|
* @see https://developers.facebook.com/docs/sharing/reference/send-dialog
|
||||||
|
* @see https://developers.facebook.com/docs/plugins/share-button/
|
||||||
|
*/
|
||||||
|
clickFBShare(app) {
|
||||||
|
let display = 'popup';
|
||||||
|
|
||||||
|
FB.getLoginStatus(function (response) {
|
||||||
|
display = response.status === 'connected'
|
||||||
|
? 'dialog'
|
||||||
|
: 'popup';
|
||||||
|
});
|
||||||
|
|
||||||
|
FB.ui({
|
||||||
|
method: 'send',
|
||||||
|
display: display,
|
||||||
|
link: window.location.href + '/' + app.state.gameAssoc,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MineWebsocket;
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
class MineServices extends React.Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
randomString(len) {
|
||||||
|
let text = "";
|
||||||
|
let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RWD
|
||||||
|
*/
|
||||||
|
currectGridSize() {
|
||||||
|
let $field = $('#mine-wrapper .grid');
|
||||||
|
$field.height($field.width());
|
||||||
|
|
||||||
|
$field = $('#mine-wrapper .grid .field-wrapper');
|
||||||
|
$field.height($field.width());
|
||||||
|
|
||||||
|
$('#mine-wrapper .grid .field-wrapper .field')
|
||||||
|
.height($field.width())
|
||||||
|
.css('line-height', ($field.width() - 2) + 'px');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MineServices;
|
||||||
12
src/Mine/SeekerBundle/Resources/public/js/mine-user-list.js
Normal file
12
src/Mine/SeekerBundle/Resources/public/js/mine-user-list.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import MineUserList from './mine-user-list/app';
|
||||||
|
|
||||||
|
let mineUserList = document.getElementById('mine-user-list');
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<MineUserList env={mineUserList.dataset.env}
|
||||||
|
ssl={mineUserList.dataset.ssl}
|
||||||
|
webPlayerName={mineUserList.dataset.webPlayerName}/>,
|
||||||
|
mineUserList
|
||||||
|
);
|
||||||
194
src/Mine/SeekerBundle/Resources/public/js/mine-user-list/app.js
Normal file
194
src/Mine/SeekerBundle/Resources/public/js/mine-user-list/app.js
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import MineServices from '../mine-system/mine-services';
|
||||||
|
|
||||||
|
class MineUserList extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
let services = new MineServices();
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
env: props.env,
|
||||||
|
ssl: props.ssl,
|
||||||
|
webPlayerName: props.webPlayerName,
|
||||||
|
services: services,
|
||||||
|
session: null,
|
||||||
|
users: [],
|
||||||
|
requests: new Map(),
|
||||||
|
search: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshUserList(payload) {
|
||||||
|
let webUsers = JSON.parse(Base64.decode(payload.users)),
|
||||||
|
users = new Map();
|
||||||
|
|
||||||
|
webUsers.forEach((item) => {
|
||||||
|
if (!users.has(item.email) && item.username !== this.state.webPlayerName) {
|
||||||
|
users.set(item.email, item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setState({users: users});
|
||||||
|
}
|
||||||
|
|
||||||
|
connectWithWebsocket() {
|
||||||
|
let websocket = WS.connect(
|
||||||
|
this.state.env === 'dev'
|
||||||
|
? "ws://mine.dev:6450"
|
||||||
|
: (this.state.ssl === 'true' ? "wss" : "ws") + "://www.mineseeker.ninja:6450/"
|
||||||
|
);
|
||||||
|
|
||||||
|
websocket.on("socket/connect", (session) => {
|
||||||
|
this.state.env === 'dev' && console.info("Successfully connected to the Server!");
|
||||||
|
this.state.session = session;
|
||||||
|
|
||||||
|
session.subscribe(
|
||||||
|
'mineseeker/userList',
|
||||||
|
(uri, payload, log) => {
|
||||||
|
/** refresh list */
|
||||||
|
if (typeof payload.users !== 'undefined') {
|
||||||
|
this.refreshUserList(payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** communication */
|
||||||
|
if (typeof payload.gameAssoc !== 'undefined') {
|
||||||
|
switch (payload.type) {
|
||||||
|
case 'REQ':
|
||||||
|
let req = this.state.requests,
|
||||||
|
user = JSON.parse(Base64.decode(payload.user));
|
||||||
|
|
||||||
|
if (!req.has(user.username)) {
|
||||||
|
req.set(user.username, {
|
||||||
|
'gameAssoc': payload.gameAssoc,
|
||||||
|
'user': user,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({reqests: req});
|
||||||
|
break;
|
||||||
|
case 'RESP':
|
||||||
|
window.location.href = window.location.origin + '/re-play/' + payload.gameAssoc;
|
||||||
|
break;
|
||||||
|
case 'SEARCH':
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
websocket.on("socket/disconnect", (error) => {
|
||||||
|
this.state.env === 'dev' && console.error("Disconnected for " + error.reason + " with code " + error.code);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.connectWithWebsocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
getProfilePicture(id) {
|
||||||
|
let avatarNbr = 5;
|
||||||
|
|
||||||
|
if (id !== null) {
|
||||||
|
avatarNbr = id.substr(-1) > 5 ? 5 : id.substr(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return id !== null ?
|
||||||
|
<img src={"http://graph.facebook.com/" + id + "/picture?type=square&width=130&height=130"}
|
||||||
|
alt="Facebook profile"/> :
|
||||||
|
<img src={"/bundles/mineseeker/images/avatar/bg-avatar-default-" + avatarNbr + ".png"}
|
||||||
|
alt="Default avatar picture"/>;
|
||||||
|
}
|
||||||
|
|
||||||
|
clickChallengeFriend(isOnline, username) {
|
||||||
|
if (isOnline) {
|
||||||
|
this.state.session.publish('mineseeker/userList', {
|
||||||
|
'type': 'REQ',
|
||||||
|
'username': username,
|
||||||
|
'gameAssoc': this.state.services.randomString(50)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
clickChallengeAccepted(username, gameAssoc) {
|
||||||
|
this.state.session.publish('mineseeker/userList', {
|
||||||
|
'type': 'RESP',
|
||||||
|
'username': username,
|
||||||
|
'gameAssoc': gameAssoc
|
||||||
|
});
|
||||||
|
|
||||||
|
window.location.href = window.location.origin + '/re-play/' + gameAssoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
onChangeSearch(event) {
|
||||||
|
this.setState({search: event.target.value});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSubmit(event) {
|
||||||
|
this.state.session.publish('mineseeker/userList', {
|
||||||
|
'type': 'SEARCH',
|
||||||
|
'username': this.state.search
|
||||||
|
});
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let users = [];
|
||||||
|
let req = [];
|
||||||
|
|
||||||
|
this.state.users.size > 0
|
||||||
|
? this.state.users.forEach((item) => {
|
||||||
|
users.push(<div key={this.state.services.randomString(50)} className="user-friend">
|
||||||
|
<div className="img">
|
||||||
|
{this.getProfilePicture(item.id)}
|
||||||
|
</div>
|
||||||
|
<h1>{item.name}</h1>
|
||||||
|
<button className={item.online ? 'button-online' : 'button-offline'}
|
||||||
|
onClick={this.clickChallengeFriend.bind(this, item.online, item.username)}>
|
||||||
|
{item.online ? 'Challenge' : 'Offline'}
|
||||||
|
</button>
|
||||||
|
</div>)
|
||||||
|
})
|
||||||
|
: '';
|
||||||
|
|
||||||
|
this.state.requests.size > 0
|
||||||
|
? this.state.requests.forEach((item) => {
|
||||||
|
req.push(<div key={this.state.services.randomString(50)} className="user-friend">
|
||||||
|
<div className="img">
|
||||||
|
{this.getProfilePicture(item.user.id)}
|
||||||
|
</div>
|
||||||
|
<h1>{item.user.name} <br/><strong>challenged you</strong>!</h1>
|
||||||
|
<button onClick={this.clickChallengeAccepted.bind(this, item.user.username, item.gameAssoc)}>
|
||||||
|
Accept
|
||||||
|
</button>
|
||||||
|
</div>)
|
||||||
|
})
|
||||||
|
: '';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="user-request-container">
|
||||||
|
{req}
|
||||||
|
</div>
|
||||||
|
<div className="user-list-filter">
|
||||||
|
<form onSubmit={this.handleSubmit.bind(this)}>
|
||||||
|
<input type="text"
|
||||||
|
onChange={this.onChangeSearch.bind(this)}
|
||||||
|
value={this.state.search}
|
||||||
|
autoFocus="autoFocus"
|
||||||
|
placeholder="Search users..."/>
|
||||||
|
<button type="submit"><i className="fa fa-search"></i></button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div className="user-list-container">
|
||||||
|
{users.length ? users : 'There is no users w/ this search results..'}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MineUserList;
|
||||||
@@ -48,8 +48,8 @@
|
|||||||
{{ 'layout.logout'|trans({}, 'FOSUserBundle') }}
|
{{ 'layout.logout'|trans({}, 'FOSUserBundle') }}
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ path('fos_user_registration_register') }}" class="small">Sign up</a> ·
|
<a href="{{ path('fos_user_registration_register') }}" class="small">Registration</a> ·
|
||||||
<a href="{{ path('fos_user_security_login') }}" class="small">Sign in</a>
|
<a href="{{ path('fos_user_security_login') }}" class="small">Login</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<h3>
|
<h3>
|
||||||
@@ -63,6 +63,14 @@
|
|||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="txt">
|
<div class="txt">
|
||||||
|
{% if is_granted("IS_AUTHENTICATED_REMEMBERED") %}
|
||||||
|
<h1>Users</h1>
|
||||||
|
<div id="mine-user-list"
|
||||||
|
data-env="{{ env }}"
|
||||||
|
data-ssl="{{ ssl }}"
|
||||||
|
data-web-player-name="{{ app.user.username is defined ? app.user.username : '' }}">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
<div class="technologies">
|
<div class="technologies">
|
||||||
<h1>Used technologies</h1>
|
<h1>Used technologies</h1>
|
||||||
<img src="{{ asset('bundles/mineseeker/images/technologies/websocket.png') }}" alt="Used Websocket"
|
<img src="{{ asset('bundles/mineseeker/images/technologies/websocket.png') }}" alt="Used Websocket"
|
||||||
@@ -93,6 +101,7 @@
|
|||||||
{% block stylesheets %}
|
{% block stylesheets %}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||||
<link href="https://fonts.googleapis.com/css?family=Rajdhani:300,400,500,600,700&subset=latin-ext"
|
<link href="https://fonts.googleapis.com/css?family=Rajdhani:300,400,500,600,700&subset=latin-ext"
|
||||||
rel="stylesheet">
|
rel="stylesheet">
|
||||||
|
|
||||||
@@ -107,6 +116,24 @@
|
|||||||
{% block javascripts %}
|
{% block javascripts %}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
|
|
||||||
|
{% if is_granted("IS_AUTHENTICATED_REMEMBERED") and app.user.facebookAccessToken is defined %}
|
||||||
|
{% if env == 'dev' %}
|
||||||
|
{% javascripts filter='?uglifyjs2'
|
||||||
|
'@GosWebSocketBundle/Resources/public/js/vendor/autobahn.min.js'
|
||||||
|
'@GosWebSocketBundle/Resources/public/js/gos_web_socket_client.js'
|
||||||
|
'@MineSeekerBundle/Resources/public/js/node/js-base64/base64.min.js'
|
||||||
|
'@MineSeekerBundle/Resources/public/js/build/mine-user-list/index.js' %}
|
||||||
|
<script type="text/javascript" src="{{ asset_url }}"></script>
|
||||||
|
{% endjavascripts %}
|
||||||
|
{% else %}
|
||||||
|
{% javascripts filter='?uglifyjs2'
|
||||||
|
'@GosWebSocketBundle/Resources/public/js/vendor/autobahn.min.js'
|
||||||
|
'@GosWebSocketBundle/Resources/public/js/gos_web_socket_client.js'
|
||||||
|
'@MineSeekerBundle/Resources/public/js/node/js-base64/base64.min.js'
|
||||||
|
'@MineSeekerBundle/Resources/public/js/build/mine-user-list/index.min.js' %}
|
||||||
|
<script type="text/javascript" src="{{ asset_url }}"></script>
|
||||||
|
{% endjavascripts %}
|
||||||
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/JQuery-Snowfall/1.7.4/snowfall.jquery.min.js"
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/JQuery-Snowfall/1.7.4/snowfall.jquery.min.js"
|
||||||
type="text/javascript"></script>
|
type="text/javascript"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
@@ -114,4 +141,6 @@
|
|||||||
$(document).snowfall({deviceorientation: true, round: true, minSize: 5, maxSize: 8});
|
$(document).snowfall({deviceorientation: true, round: true, minSize: 5, maxSize: 8});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
<div id="mine-wrapper"
|
<div id="mine-wrapper"
|
||||||
data-env="{{ env }}"
|
data-env="{{ env }}"
|
||||||
data-ssl="{{ ssl }}"
|
data-ssl="{{ ssl }}"
|
||||||
data-game-id="{{ app.request.get('gameAssoc') }}">
|
data-game-id="{{ app.request.get('gameAssoc') }}"
|
||||||
|
data-web-player-name="{{ app.user.username is defined ? app.user.username : '' }}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -20,7 +21,8 @@
|
|||||||
<meta property="og:type" content="website"/>
|
<meta property="og:type" content="website"/>
|
||||||
<meta property="og:title" content="Your friend challenges YOU!"/>
|
<meta property="og:title" content="Your friend challenges YOU!"/>
|
||||||
<meta property="og:description" content="Do you accept the challenge?"/>
|
<meta property="og:description" content="Do you accept the challenge?"/>
|
||||||
<meta property="og:image" content="{{ app.request.getSchemeAndHttpHost() }}{{ asset('bundles/mineseeker/images/mine-1600x627.png') }}"/>
|
<meta property="og:image"
|
||||||
|
content="{{ app.request.getSchemeAndHttpHost() }}{{ asset('bundles/mineseeker/images/mine-1600x627.png') }}"/>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block stylesheets %}
|
{% block stylesheets %}
|
||||||
@@ -46,7 +48,7 @@
|
|||||||
'@GosWebSocketBundle/Resources/public/js/gos_web_socket_client.js'
|
'@GosWebSocketBundle/Resources/public/js/gos_web_socket_client.js'
|
||||||
'@MineSeekerBundle/Resources/public/js/node/howler/dist/howler.min.js'
|
'@MineSeekerBundle/Resources/public/js/node/howler/dist/howler.min.js'
|
||||||
'@MineSeekerBundle/Resources/public/js/node/js-base64/base64.min.js'
|
'@MineSeekerBundle/Resources/public/js/node/js-base64/base64.min.js'
|
||||||
'@MineSeekerBundle/Resources/public/js/index.js' %}
|
'@MineSeekerBundle/Resources/public/js/build/mine-seeker/index.js' %}
|
||||||
<script type="text/javascript" src="{{ asset_url }}"></script>
|
<script type="text/javascript" src="{{ asset_url }}"></script>
|
||||||
{% endjavascripts %}
|
{% endjavascripts %}
|
||||||
{% else %}
|
{% else %}
|
||||||
@@ -55,7 +57,7 @@
|
|||||||
'@GosWebSocketBundle/Resources/public/js/gos_web_socket_client.js'
|
'@GosWebSocketBundle/Resources/public/js/gos_web_socket_client.js'
|
||||||
'@MineSeekerBundle/Resources/public/js/node/howler/dist/howler.min.js'
|
'@MineSeekerBundle/Resources/public/js/node/howler/dist/howler.min.js'
|
||||||
'@MineSeekerBundle/Resources/public/js/node/js-base64/base64.min.js'
|
'@MineSeekerBundle/Resources/public/js/node/js-base64/base64.min.js'
|
||||||
'@MineSeekerBundle/Resources/public/js/index.min.js' %}
|
'@MineSeekerBundle/Resources/public/js/build/mine-seeker/index.min.js' %}
|
||||||
<script type="text/javascript" src="{{ asset_url }}"></script>
|
<script type="text/javascript" src="{{ asset_url }}"></script>
|
||||||
{% endjavascripts %}
|
{% endjavascripts %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -1,14 +1,21 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
$(function () {
|
||||||
window.fbAsyncInit = function () {
|
window.fbAsyncInit = function () {
|
||||||
FB.init({
|
FB.init({
|
||||||
appId: '{{ facebook_api }}',
|
appId: '{{ facebook_api }}',
|
||||||
xfbml: true,
|
xfbml: true,
|
||||||
cookie: true,
|
cookie: true,
|
||||||
status: true,
|
status: true,
|
||||||
oauth: true,
|
version: '{{ facebook_api_version }}',
|
||||||
version: '{{ facebook_api_version }}'
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/** trigger jQuery when Facebook SKD loads */
|
||||||
|
// $(document).trigger('fb-load');
|
||||||
|
// $(document).bind('fb-load', function () {
|
||||||
|
// TODO
|
||||||
|
// });
|
||||||
};
|
};
|
||||||
|
});
|
||||||
|
|
||||||
(function (d, s, id) {
|
(function (d, s, id) {
|
||||||
var js, fjs = d.getElementsByTagName(s)[0];
|
var js, fjs = d.getElementsByTagName(s)[0];
|
||||||
|
|||||||
@@ -4,22 +4,30 @@ namespace Mine\SeekerBundle\Rpc;
|
|||||||
|
|
||||||
use Doctrine\DBAL\Driver\PDOException;
|
use Doctrine\DBAL\Driver\PDOException;
|
||||||
use Doctrine\ORM\EntityManager;
|
use Doctrine\ORM\EntityManager;
|
||||||
|
use Doctrine\ORM\OptimisticLockException;
|
||||||
use Mine\SeekerBundle\Entity\Grid;
|
use Mine\SeekerBundle\Entity\Grid;
|
||||||
use Mine\SeekerBundle\Entity\GridRow;
|
use Mine\SeekerBundle\Entity\GridRow;
|
||||||
use Mine\SeekerBundle\Entity\PlayedGame;
|
use Mine\SeekerBundle\Entity\PlayedGame;
|
||||||
use Ratchet\ConnectionInterface;
|
use Ratchet\ConnectionInterface;
|
||||||
use Gos\Bundle\WebSocketBundle\RPC\RpcInterface;
|
use Gos\Bundle\WebSocketBundle\RPC\RpcInterface;
|
||||||
use Gos\Bundle\WebSocketBundle\Router\WampRequest;
|
use Gos\Bundle\WebSocketBundle\Router\WampRequest;
|
||||||
|
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class MineseekerRpc
|
||||||
|
*
|
||||||
|
* @package Mine\SeekerBundle\Rpc
|
||||||
|
* @author system7 <https://www.laszlolang.com>
|
||||||
|
*/
|
||||||
class MineseekerRpc implements RpcInterface
|
class MineseekerRpc implements RpcInterface
|
||||||
{
|
{
|
||||||
/** @var EntityManager */
|
/** @var EntityManager */
|
||||||
protected $em;
|
protected $em;
|
||||||
|
|
||||||
protected $grid;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MineseekerRpc constructor.
|
* MineseekerRpc constructor.
|
||||||
|
*
|
||||||
* @param EntityManager $entityManager
|
* @param EntityManager $entityManager
|
||||||
*/
|
*/
|
||||||
public function __construct(EntityManager $entityManager)
|
public function __construct(EntityManager $entityManager)
|
||||||
@@ -41,91 +49,51 @@ class MineseekerRpc implements RpcInterface
|
|||||||
* @param ConnectionInterface $connection
|
* @param ConnectionInterface $connection
|
||||||
* @param WampRequest $request
|
* @param WampRequest $request
|
||||||
* @param array $params
|
* @param array $params
|
||||||
* @return boolean
|
*
|
||||||
*/
|
|
||||||
public function startGame(ConnectionInterface $connection, WampRequest $request, array $params)
|
|
||||||
{
|
|
||||||
return $this->saveGrid($params);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ConnectionInterface $connection
|
|
||||||
* @param WampRequest $request
|
|
||||||
* @param array $params
|
|
||||||
* @return string Json string for frontend w/ numbering consideration. (=> a number is not string)
|
* @return string Json string for frontend w/ numbering consideration. (=> a number is not string)
|
||||||
|
* @throws OptimisticLockException
|
||||||
*/
|
*/
|
||||||
public function connectGame(ConnectionInterface $connection, WampRequest $request, array $params)
|
public function connectGame(ConnectionInterface $connection, WampRequest $request, array $params)
|
||||||
{
|
{
|
||||||
$grid = $this->getGrid($params);
|
$grid = $this->getGrid($params);
|
||||||
$users = null !== $grid ? $this->getUsers($params) : null;
|
return base64_encode(json_encode($grid));
|
||||||
|
|
||||||
return base64_encode(json_encode(
|
|
||||||
array(
|
|
||||||
'grid' => $grid,
|
|
||||||
'users' => $users
|
|
||||||
)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $gameAssoc
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function getGrid($gameAssoc)
|
|
||||||
{
|
|
||||||
$this->reConnect();
|
|
||||||
$getsee = array();
|
|
||||||
|
|
||||||
$this->em->clear();
|
|
||||||
|
|
||||||
$grid = $this->em
|
|
||||||
->getRepository('MineSeekerBundle:PlayedGame')
|
|
||||||
->findOneByGameAssoc($gameAssoc);
|
|
||||||
|
|
||||||
if (null !== $grid) {
|
|
||||||
foreach ($grid->getGrid()->getGridRow()->toArray() as $row) {
|
|
||||||
$getsee[] = $row->getGridCol();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $getsee;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $gameAssoc
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function getUsers($gameAssoc)
|
|
||||||
{
|
|
||||||
$this->reConnect();
|
|
||||||
return $this->getUserCollection(
|
|
||||||
$this->em
|
|
||||||
->getRepository('MineSeekerBundle:PlayedGame')
|
|
||||||
->findOneByGameAssoc($gameAssoc)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get user collection from PlayedGame entity
|
|
||||||
*
|
|
||||||
* @param $playedGame
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function getUserCollection($playedGame)
|
|
||||||
{
|
|
||||||
return array(
|
|
||||||
'red' => null !== $playedGame->getRed() ? $playedGame->getRed()->getUsername() : '',
|
|
||||||
'blue' => null !== $playedGame->getBlue() ? $playedGame->getBlue()->getUsername() : '',
|
|
||||||
'redAnon' => null !== $playedGame->getRedAnon() ? $playedGame->getRedAnon()->getUserName() : '',
|
|
||||||
'blueAnon' => null !== $playedGame->getBlueAnon() ? $playedGame->getBlueAnon()->getUserName() : ''
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $data
|
* @param $data
|
||||||
|
*
|
||||||
|
* @return array|bool
|
||||||
|
* @throws OptimisticLockException
|
||||||
|
*/
|
||||||
|
private function getGrid($data)
|
||||||
|
{
|
||||||
|
$this->reConnect();
|
||||||
|
$this->em->clear();
|
||||||
|
|
||||||
|
$grid = array();
|
||||||
|
/** @var PlayedGame $game */
|
||||||
|
$game = $this->em
|
||||||
|
->getRepository('MineSeekerBundle:PlayedGame')
|
||||||
|
->findOneByGameAssoc($data[1]);
|
||||||
|
|
||||||
|
if (null !== $game) {
|
||||||
|
/** @var GridRow $row */
|
||||||
|
foreach ($game->getGrid()->getGridRow()->toArray() as $row) {
|
||||||
|
$grid[] = $row->getGridCol();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $grid;
|
||||||
|
} else {
|
||||||
|
$this->saveGrid($data);
|
||||||
|
return $this->getGrid($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $data
|
||||||
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
|
* @throws OptimisticLockException
|
||||||
*/
|
*/
|
||||||
private function saveGrid($data)
|
private function saveGrid($data)
|
||||||
{
|
{
|
||||||
@@ -169,8 +137,8 @@ class MineseekerRpc implements RpcInterface
|
|||||||
$connection->close();
|
$connection->close();
|
||||||
$connection->connect();
|
$connection->connect();
|
||||||
}
|
}
|
||||||
} catch(PDOException $ex) {
|
} catch (PDOException $ex) {
|
||||||
throw PDOException::class;
|
throw new NotFoundHttpException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,15 +4,25 @@ namespace Mine\SeekerBundle\Topic;
|
|||||||
|
|
||||||
use Doctrine\DBAL\Driver\PDOException;
|
use Doctrine\DBAL\Driver\PDOException;
|
||||||
use Doctrine\ORM\EntityManager;
|
use Doctrine\ORM\EntityManager;
|
||||||
|
use Doctrine\ORM\OptimisticLockException;
|
||||||
use Gos\Bundle\WebSocketBundle\Client\ClientManipulatorInterface;
|
use Gos\Bundle\WebSocketBundle\Client\ClientManipulatorInterface;
|
||||||
use Gos\Bundle\WebSocketBundle\Topic\TopicInterface;
|
use Gos\Bundle\WebSocketBundle\Topic\TopicInterface;
|
||||||
use Gos\Bundle\WebSocketBundle\Router\WampRequest;
|
use Gos\Bundle\WebSocketBundle\Router\WampRequest;
|
||||||
|
use HWI\Bundle\OAuthBundle\Tests\Fixtures\FOSUser;
|
||||||
use Mine\SeekerBundle\Entity\Gamer;
|
use Mine\SeekerBundle\Entity\Gamer;
|
||||||
|
use Mine\SeekerBundle\Entity\PlayedGame;
|
||||||
use Mine\SeekerBundle\Entity\Step;
|
use Mine\SeekerBundle\Entity\Step;
|
||||||
use Ratchet\ConnectionInterface;
|
use Ratchet\ConnectionInterface;
|
||||||
use Ratchet\Wamp\Topic;
|
use Ratchet\Wamp\Topic;
|
||||||
use Symfony\Component\HttpFoundation\RequestStack;
|
use Symfony\Component\HttpFoundation\RequestStack;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class MineseekerTopic
|
||||||
|
*
|
||||||
|
* @package Mine\SeekerBundle\Topic
|
||||||
|
* @author system7 <https://www.laszlolang.com>
|
||||||
|
*/
|
||||||
class MineseekerTopic implements TopicInterface
|
class MineseekerTopic implements TopicInterface
|
||||||
{
|
{
|
||||||
/** @var ClientManipulatorInterface */
|
/** @var ClientManipulatorInterface */
|
||||||
@@ -44,7 +54,9 @@ class MineseekerTopic implements TopicInterface
|
|||||||
* @param ConnectionInterface $connection
|
* @param ConnectionInterface $connection
|
||||||
* @param Topic $topic
|
* @param Topic $topic
|
||||||
* @param WampRequest $request
|
* @param WampRequest $request
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws OptimisticLockException
|
||||||
*/
|
*/
|
||||||
public function onSubscribe(ConnectionInterface $connection, Topic $topic, WampRequest $request)
|
public function onSubscribe(ConnectionInterface $connection, Topic $topic, WampRequest $request)
|
||||||
{
|
{
|
||||||
@@ -58,13 +70,14 @@ class MineseekerTopic implements TopicInterface
|
|||||||
} else {
|
} else {
|
||||||
$users = $this->controlUsers($topic, $userName, $user);
|
$users = $this->controlUsers($topic, $userName, $user);
|
||||||
|
|
||||||
$topic->broadcast([
|
$topic->broadcast(array(
|
||||||
'userTopicId' => $connection->resourceId,
|
'userTopicId' => $connection->resourceId,
|
||||||
'channel' => $topic->getId(),
|
'channel' => $topic->getId(),
|
||||||
'user' => $userName,
|
'user' => $userName,
|
||||||
'userCnt' => $topic->count(),
|
'userCnt' => $topic->count(),
|
||||||
'users' => $users
|
'users' => $users,
|
||||||
]);
|
'steps' => $this->getSteps($topic),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +87,7 @@ class MineseekerTopic implements TopicInterface
|
|||||||
* @param ConnectionInterface $connection
|
* @param ConnectionInterface $connection
|
||||||
* @param Topic $topic
|
* @param Topic $topic
|
||||||
* @param WampRequest $request
|
* @param WampRequest $request
|
||||||
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function onUnSubscribe(ConnectionInterface $connection, Topic $topic, WampRequest $request)
|
public function onUnSubscribe(ConnectionInterface $connection, Topic $topic, WampRequest $request)
|
||||||
@@ -91,9 +105,11 @@ class MineseekerTopic implements TopicInterface
|
|||||||
* @param $event
|
* @param $event
|
||||||
* @param array $exclude
|
* @param array $exclude
|
||||||
* @param array $eligible
|
* @param array $eligible
|
||||||
|
*
|
||||||
* @return mixed|void
|
* @return mixed|void
|
||||||
* @internal param Topic $Topic
|
* @internal param Topic $Topic
|
||||||
* @internal param array $eligibles
|
* @internal param array $eligibles
|
||||||
|
* @throws OptimisticLockException
|
||||||
*/
|
*/
|
||||||
public function onPublish(ConnectionInterface $connection, Topic $topic, WampRequest $request, $event, array $exclude, array $eligible)
|
public function onPublish(ConnectionInterface $connection, Topic $topic, WampRequest $request, $event, array $exclude, array $eligible)
|
||||||
{
|
{
|
||||||
@@ -131,12 +147,15 @@ class MineseekerTopic implements TopicInterface
|
|||||||
*
|
*
|
||||||
* @param $topic
|
* @param $topic
|
||||||
* @param $color
|
* @param $color
|
||||||
|
*
|
||||||
|
* @throws OptimisticLockException
|
||||||
*/
|
*/
|
||||||
private function saveResignToDb($topic, $color)
|
private function saveResignToDb($topic, $color)
|
||||||
{
|
{
|
||||||
$this->reConnect();
|
$this->reConnect();
|
||||||
$gameAssoc = explode('/', $topic->getId())[2];
|
$gameAssoc = explode('/', $topic->getId())[2];
|
||||||
|
|
||||||
|
/** @var PlayedGame $playedGame */
|
||||||
$playedGame = $this->em
|
$playedGame = $this->em
|
||||||
->getRepository('MineSeekerBundle:PlayedGame')
|
->getRepository('MineSeekerBundle:PlayedGame')
|
||||||
->findOneByGameAssoc($gameAssoc);
|
->findOneByGameAssoc($gameAssoc);
|
||||||
@@ -149,14 +168,17 @@ class MineseekerTopic implements TopicInterface
|
|||||||
/**
|
/**
|
||||||
* Save steps and point information to database
|
* Save steps and point information to database
|
||||||
*
|
*
|
||||||
* @param $topic
|
* @param Topic $topic
|
||||||
* @param $event
|
* @param $event
|
||||||
|
*
|
||||||
|
* @throws OptimisticLockException
|
||||||
*/
|
*/
|
||||||
private function saveStepToDb($topic, $event)
|
private function saveStepToDb($topic, $event)
|
||||||
{
|
{
|
||||||
$this->reConnect();
|
$this->reConnect();
|
||||||
$gameAssoc = explode('/', $topic->getId())[2];
|
$gameAssoc = explode('/', $topic->getId())[2];
|
||||||
|
|
||||||
|
/** @var PlayedGame $playedGame */
|
||||||
$playedGame = $this->em
|
$playedGame = $this->em
|
||||||
->getRepository('MineSeekerBundle:PlayedGame')
|
->getRepository('MineSeekerBundle:PlayedGame')
|
||||||
->findOneByGameAssoc($gameAssoc);
|
->findOneByGameAssoc($gameAssoc);
|
||||||
@@ -180,19 +202,44 @@ class MineseekerTopic implements TopicInterface
|
|||||||
$this->em->flush();
|
$this->em->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getSteps($topic)
|
||||||
|
{
|
||||||
|
$this->reConnect();
|
||||||
|
$gameAssoc = explode('/', $topic->getId())[2];
|
||||||
|
|
||||||
|
$playedGame = $this->em
|
||||||
|
->getRepository('MineSeekerBundle:PlayedGame')
|
||||||
|
->findOneByGameAssoc($gameAssoc);
|
||||||
|
|
||||||
|
$steps = array();
|
||||||
|
|
||||||
|
foreach ($playedGame->getStep()->toArray() as $item) {
|
||||||
|
$steps[] = array(
|
||||||
|
'row' => $item->getRow(),
|
||||||
|
'col' => $item->getCol(),
|
||||||
|
'wBomb' => $item->getWBomb(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return base64_encode(json_encode($steps));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Control all users in a channel
|
* Control all users in a channel
|
||||||
*
|
*
|
||||||
* @param $topic
|
* @param $topic
|
||||||
* @param $userName
|
* @param $userName
|
||||||
* @param $user
|
* @param $user
|
||||||
|
*
|
||||||
* @return array
|
* @return array
|
||||||
|
* @throws OptimisticLockException
|
||||||
*/
|
*/
|
||||||
private function controlUsers($topic, $userName, $user)
|
private function controlUsers($topic, $userName, $user)
|
||||||
{
|
{
|
||||||
$this->reConnect();
|
$this->reConnect();
|
||||||
$gameAssoc = explode('/', $topic->getId())[2];
|
$gameAssoc = explode('/', $topic->getId())[2];
|
||||||
|
|
||||||
|
/** @var PlayedGame $playedGame */
|
||||||
$playedGame = $this->em
|
$playedGame = $this->em
|
||||||
->getRepository('MineSeekerBundle:PlayedGame')
|
->getRepository('MineSeekerBundle:PlayedGame')
|
||||||
->findOneByGameAssoc($gameAssoc);
|
->findOneByGameAssoc($gameAssoc);
|
||||||
@@ -208,7 +255,7 @@ class MineseekerTopic implements TopicInterface
|
|||||||
/** This checks it is a reconnection */
|
/** This checks it is a reconnection */
|
||||||
if (($one && ($red + $blue === 0)) || ($two && ($red + $blue === 1))) {
|
if (($one && ($red + $blue === 0)) || ($two && ($red + $blue === 1))) {
|
||||||
/** @var $users {array} w/ save users to database */
|
/** @var $users {array} w/ save users to database */
|
||||||
$users = $this->saveUserToDb($topic, $userName, $user, $topic->count());
|
$users = $this->saveUserToDb($playedGame, $userName, $user, $topic->count());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $users;
|
return $users;
|
||||||
@@ -217,20 +264,17 @@ class MineseekerTopic implements TopicInterface
|
|||||||
/**
|
/**
|
||||||
* Save user data to database
|
* Save user data to database
|
||||||
*
|
*
|
||||||
* @param $topic
|
* @param PlayedGame $playedGame
|
||||||
* @param $userName
|
* @param FOSUser $userName
|
||||||
* @param $user
|
* @param $user
|
||||||
* @param $count
|
* @param $count
|
||||||
|
*
|
||||||
* @return array
|
* @return array
|
||||||
|
* @throws OptimisticLockException
|
||||||
*/
|
*/
|
||||||
private function saveUserToDb($topic, $userName, $user, $count)
|
private function saveUserToDb($playedGame, $userName, $user, $count)
|
||||||
{
|
{
|
||||||
$this->reConnect();
|
$this->reConnect();
|
||||||
$gameAssoc = explode('/', $topic->getId())[2];
|
|
||||||
|
|
||||||
$playedGame = $this->em
|
|
||||||
->getRepository('MineSeekerBundle:PlayedGame')
|
|
||||||
->findOneByGameAssoc($gameAssoc);
|
|
||||||
|
|
||||||
/** the user is not anonym */
|
/** the user is not anonym */
|
||||||
if (!is_string($user)) {
|
if (!is_string($user)) {
|
||||||
@@ -275,7 +319,8 @@ class MineseekerTopic implements TopicInterface
|
|||||||
/**
|
/**
|
||||||
* Get user collection from PlayedGame entity
|
* Get user collection from PlayedGame entity
|
||||||
*
|
*
|
||||||
* @param $playedGame
|
* @param PlayedGame $playedGame
|
||||||
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function getUserCollection($playedGame)
|
private function getUserCollection($playedGame)
|
||||||
@@ -300,8 +345,8 @@ class MineseekerTopic implements TopicInterface
|
|||||||
$connection->close();
|
$connection->close();
|
||||||
$connection->connect();
|
$connection->connect();
|
||||||
}
|
}
|
||||||
} catch(PDOException $ex) {
|
} catch (PDOException $ex) {
|
||||||
throw PDOException::class;
|
throw new NotFoundHttpException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
283
src/Mine/SeekerBundle/Topic/UserListTopic.php
Normal file
283
src/Mine/SeekerBundle/Topic/UserListTopic.php
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Mine\SeekerBundle\Topic;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Driver\PDOException;
|
||||||
|
use Doctrine\ORM\EntityManager;
|
||||||
|
use Gos\Bundle\WebSocketBundle\Client\ClientManipulatorInterface;
|
||||||
|
use Gos\Bundle\WebSocketBundle\Topic\TopicInterface;
|
||||||
|
use Gos\Bundle\WebSocketBundle\Router\WampRequest;
|
||||||
|
use Ratchet\ConnectionInterface;
|
||||||
|
use Ratchet\Wamp\Topic;
|
||||||
|
use Symfony\Component\HttpFoundation\RequestStack;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class UserListTopic
|
||||||
|
*
|
||||||
|
* @package Mine\SeekerBundle\Topic
|
||||||
|
* @author system7 <https://www.laszlolang.com>
|
||||||
|
*/
|
||||||
|
class UserListTopic implements TopicInterface
|
||||||
|
{
|
||||||
|
/** @var ClientManipulatorInterface */
|
||||||
|
protected $clientManipulator;
|
||||||
|
|
||||||
|
/** @var EntityManager */
|
||||||
|
protected $em;
|
||||||
|
|
||||||
|
/** @var RequestStack */
|
||||||
|
protected $requestStack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MineseekerTopic constructor.
|
||||||
|
*
|
||||||
|
* @param $clientManipulator ClientManipulatorInterface
|
||||||
|
* @param EntityManager $entityManager
|
||||||
|
* @param RequestStack $requestStack
|
||||||
|
*/
|
||||||
|
public function __construct(ClientManipulatorInterface $clientManipulator, EntityManager $entityManager, RequestStack $requestStack)
|
||||||
|
{
|
||||||
|
$this->clientManipulator = $clientManipulator;
|
||||||
|
$this->em = $entityManager;
|
||||||
|
$this->requestStack = $requestStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will receive any Subscription requests for this topic.
|
||||||
|
*
|
||||||
|
* @param ConnectionInterface $connection
|
||||||
|
* @param Topic $topic
|
||||||
|
* @param WampRequest $request
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function onSubscribe(ConnectionInterface $connection, Topic $topic, WampRequest $request)
|
||||||
|
{
|
||||||
|
/** this will broadcast the message to ALL subscribers of this topic. */
|
||||||
|
$user = $this->clientManipulator->getClient($connection);
|
||||||
|
$userName = is_string($user) ? $user : $user->getUsername();
|
||||||
|
|
||||||
|
/** @var array Find all users online and offline $users */
|
||||||
|
$users = $this->findAllUsers($topic);
|
||||||
|
|
||||||
|
$topic->broadcast([
|
||||||
|
'userTopicId' => $connection->resourceId,
|
||||||
|
'channel' => $topic->getId(),
|
||||||
|
'user' => $userName,
|
||||||
|
'userCnt' => $topic->count(),
|
||||||
|
'users' => base64_encode(json_encode($users))
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will receive any UnSubscription requests for this topic.
|
||||||
|
*
|
||||||
|
* @param ConnectionInterface $connection
|
||||||
|
* @param Topic $topic
|
||||||
|
* @param WampRequest $request
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function onUnSubscribe(ConnectionInterface $connection, Topic $topic, WampRequest $request)
|
||||||
|
{
|
||||||
|
/** this will broadcast the message to ALL subscribers of this topic. */
|
||||||
|
$topic->broadcast(['msg' => $connection->resourceId . " has left " . $topic->getId()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will receive any Publish requests for this topic.
|
||||||
|
*
|
||||||
|
* @param ConnectionInterface $connection
|
||||||
|
* @param Topic $topic
|
||||||
|
* @param WampRequest $request
|
||||||
|
* @param $event
|
||||||
|
* @param array $exclude
|
||||||
|
* @param array $eligible
|
||||||
|
*
|
||||||
|
* @return mixed|void
|
||||||
|
* @internal param Topic $Topic
|
||||||
|
* @internal param array $eligibles
|
||||||
|
*/
|
||||||
|
public function onPublish(ConnectionInterface $connection, Topic $topic, WampRequest $request, $event, array $exclude, array $eligible)
|
||||||
|
{
|
||||||
|
$user = $this->clientManipulator->getClient($connection);
|
||||||
|
$userName = is_string($user) ? $user : $user->getUsername();
|
||||||
|
|
||||||
|
if ($event['type'] === 'REQ' || $event['type'] === 'RESP') {
|
||||||
|
$reqUser = $this->clientManipulator->findByUsername($topic, $event['username']);
|
||||||
|
|
||||||
|
/** user is still online */
|
||||||
|
if (false !== $reqUser) {
|
||||||
|
$topic->broadcast(
|
||||||
|
array(
|
||||||
|
'type' => $event['type'],
|
||||||
|
'user' => $this->findUser($topic, $userName),
|
||||||
|
'gameAssoc' => $event['gameAssoc'],
|
||||||
|
),
|
||||||
|
array(),
|
||||||
|
array(
|
||||||
|
$reqUser['connection']->WAMP->sessionId
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($event['type'] === 'SEARCH') {
|
||||||
|
$reqUser = $this->clientManipulator->findByUsername($topic, $userName);
|
||||||
|
|
||||||
|
/** user is still online */
|
||||||
|
if (false !== $reqUser) {
|
||||||
|
$topic->broadcast(
|
||||||
|
array(
|
||||||
|
'type' => $event['type'],
|
||||||
|
'users' => $this->findUsersForSearch($topic, $event['username']),
|
||||||
|
'gameAssoc' => true,
|
||||||
|
),
|
||||||
|
array(),
|
||||||
|
array(
|
||||||
|
$reqUser['connection']->WAMP->sessionId,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like RPC is will use to prefix the channel
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return 'userlist.topic';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $topic
|
||||||
|
* @param $username
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function findUser($topic, $username)
|
||||||
|
{
|
||||||
|
$this->reConnect();
|
||||||
|
$userRepo = $this->em->getRepository('JotunheimrUserBundle:User');
|
||||||
|
$user = $userRepo->findOneByUsername($username);
|
||||||
|
$currentOnline = $this->clientManipulator->findByUsername($topic, $username)['client'];
|
||||||
|
|
||||||
|
return base64_encode(json_encode(array(
|
||||||
|
'id' => $user->getFacebookId(),
|
||||||
|
'name' => $user->getRealName(),
|
||||||
|
'email' => $user->getEmail(),
|
||||||
|
'username' => $user->getUsername(),
|
||||||
|
'online' => $currentOnline !== null
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $topic
|
||||||
|
* @param $username
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function findUsersForSearch($topic, $username)
|
||||||
|
{
|
||||||
|
$this->reConnect();
|
||||||
|
$userRepo = $this->em->getRepository('JotunheimrUserBundle:User');
|
||||||
|
$users = $userRepo
|
||||||
|
->createQueryBuilder('o')
|
||||||
|
->where('o.username LIKE :username')
|
||||||
|
->andWhere('o.realName LIKE :realname')
|
||||||
|
->setParameter('username', "%{$username}%")
|
||||||
|
->setParameter('realname', "%{$username}%")
|
||||||
|
->setMaxResults(10)
|
||||||
|
->getQuery()
|
||||||
|
->getResult();
|
||||||
|
$usersAvailable = array();
|
||||||
|
|
||||||
|
foreach ($users as $item) {
|
||||||
|
$usersAvailable[] = array(
|
||||||
|
'id' => $item->getFacebookId(),
|
||||||
|
'name' => $item->getRealName(),
|
||||||
|
'email' => $item->getEmail(),
|
||||||
|
'username' => $item->getUsername(),
|
||||||
|
'online' => $this->clientManipulator->findByUsername($topic, $item->getUsername())['client'] !== null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return base64_encode(json_encode(
|
||||||
|
$usersAvailable
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all users online/offline
|
||||||
|
*
|
||||||
|
* @param $topic
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function findAllUsers($topic)
|
||||||
|
{
|
||||||
|
$usersOnline = array();
|
||||||
|
$usersOffline = array();
|
||||||
|
|
||||||
|
$this->reConnect();
|
||||||
|
$userRepo = $this->em->getRepository('JotunheimrUserBundle:User');
|
||||||
|
|
||||||
|
$usersMax = 10;
|
||||||
|
foreach ($this->clientManipulator->getAll($topic) as $item) {
|
||||||
|
if (!$usersMax) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = $userRepo->findOneByEmail(
|
||||||
|
$item['client']->getEmail()
|
||||||
|
);
|
||||||
|
|
||||||
|
$usersOnline[] = array(
|
||||||
|
'id' => $user->getFacebookId(),
|
||||||
|
'name' => $user->getRealName(),
|
||||||
|
'email' => $user->getEmail(),
|
||||||
|
'username' => $user->getUsername(),
|
||||||
|
'online' => true
|
||||||
|
);
|
||||||
|
|
||||||
|
$usersMax--;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($userRepo->findBy(array(), array(), 20) as $item) {
|
||||||
|
$exists = is_numeric(array_search($item->getEmail(), array_column($usersOnline, 'email')));
|
||||||
|
|
||||||
|
if (!$exists) {
|
||||||
|
$usersOffline[] = array(
|
||||||
|
'id' => $item->getFacebookId(),
|
||||||
|
'name' => $item->getRealName(),
|
||||||
|
'email' => $item->getEmail(),
|
||||||
|
'username' => $item->getUsername(),
|
||||||
|
'online' => false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_merge($usersOnline, $usersOffline);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle prod MySQL timeout
|
||||||
|
*/
|
||||||
|
private function reConnect()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$connection = $this->em->getConnection();
|
||||||
|
|
||||||
|
if (false === $connection->ping()) {
|
||||||
|
$connection->close();
|
||||||
|
$connection->connect();
|
||||||
|
}
|
||||||
|
} catch (PDOException $ex) {
|
||||||
|
throw new NotFoundHttpException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -780,7 +780,11 @@ class SymfonyRequirements extends RequirementCollection
|
|||||||
{
|
{
|
||||||
$size = ini_get('realpath_cache_size');
|
$size = ini_get('realpath_cache_size');
|
||||||
$size = trim($size);
|
$size = trim($size);
|
||||||
|
$unit = '';
|
||||||
|
if (!ctype_digit($size)) {
|
||||||
$unit = strtolower(substr($size, -1, 1));
|
$unit = strtolower(substr($size, -1, 1));
|
||||||
|
$size = (int) substr($size, 0, -1);
|
||||||
|
}
|
||||||
switch ($unit) {
|
switch ($unit) {
|
||||||
case 'g':
|
case 'g':
|
||||||
return $size * 1024 * 1024 * 1024;
|
return $size * 1024 * 1024 * 1024;
|
||||||
|
|||||||
@@ -270,7 +270,7 @@ $hasMinorProblems = (bool) count($minorProblems);
|
|||||||
}
|
}
|
||||||
.sf-reset ul a,
|
.sf-reset ul a,
|
||||||
.sf-reset ul a:hover {
|
.sf-reset ul a:hover {
|
||||||
background: url(../images/blue-arrow.png) no-repeat right 6px;
|
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAICAYAAAAx8TU7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFdJREFUeNpiYACBjjOhDEiACSggCKTLgXQ5TJARqhIkcReIKxgqTGYxwvV0nDEGkmeAOIwJySiQ4HsgvseIpGo3ELsCtZ9lRDIvDCiwhwHJPEFkJwEEGACq6hdnax8y1AAAAABJRU5ErkJggg==) no-repeat right 7px;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
.sf-reset ul, ol {
|
.sf-reset ul, ol {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var webpack = require("webpack");
|
let webpack = require("webpack");
|
||||||
process.env.NODE_ENV = 'production';
|
process.env.NODE_ENV = 'production';
|
||||||
var isProd = (process.env.NODE_ENV === 'production');
|
let isProd = (process.env.NODE_ENV === 'production');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conditionally return a list of plugins to use based on the current environment.
|
* Conditionally return a list of plugins to use based on the current environment.
|
||||||
@@ -10,7 +10,7 @@ var isProd = (process.env.NODE_ENV === 'production');
|
|||||||
* @returns {Array}
|
* @returns {Array}
|
||||||
*/
|
*/
|
||||||
function getPlugins() {
|
function getPlugins() {
|
||||||
var plugins = [];
|
let plugins = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Always expose NODE_ENV to webpack, you can now use `process.env.NODE_ENV`
|
* Always expose NODE_ENV to webpack, you can now use `process.env.NODE_ENV`
|
||||||
@@ -33,10 +33,14 @@ function getPlugins() {
|
|||||||
return plugins;
|
return plugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
const config = module.exports = {
|
const config = {
|
||||||
|
module: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mineSeekerConfig = Object.assign({}, config, {
|
||||||
entry: './web/bundles/mineseeker/js/mine-seeker.js',
|
entry: './web/bundles/mineseeker/js/mine-seeker.js',
|
||||||
output: {
|
output: {
|
||||||
path: './src/Mine/SeekerBundle/Resources/public/js',
|
path: './src/Mine/SeekerBundle/Resources/public/js/build/mine-seeker/',
|
||||||
filename: 'index.min.js'
|
filename: 'index.min.js'
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
@@ -46,12 +50,34 @@ const config = module.exports = {
|
|||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
loader: 'babel',
|
loader: 'babel',
|
||||||
query: {
|
query: {
|
||||||
presets: ['es2015', 'react']
|
presets: ['es2015', 'es2016', 'es2017', 'react']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
}
|
||||||
plugins: getPlugins()
|
});
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = config;
|
let mineUserListConfig = Object.assign({}, config, {
|
||||||
|
entry: './web/bundles/mineseeker/js/mine-user-list.js',
|
||||||
|
output: {
|
||||||
|
path: './src/Mine/SeekerBundle/Resources/public/js/build/mine-user-list/',
|
||||||
|
filename: 'index.min.js'
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
loaders: [
|
||||||
|
{
|
||||||
|
test: /\.js$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
loader: 'babel',
|
||||||
|
query: {
|
||||||
|
presets: ['es2015', 'es2016', 'es2017', 'react']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
mineSeekerConfig,
|
||||||
|
mineUserListConfig,
|
||||||
|
];
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const config = module.exports = {
|
const config = {
|
||||||
|
module: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mineSeekerConfig = Object.assign({}, config, {
|
||||||
entry: './web/bundles/mineseeker/js/mine-seeker.js',
|
entry: './web/bundles/mineseeker/js/mine-seeker.js',
|
||||||
output: {
|
output: {
|
||||||
path: './src/Mine/SeekerBundle/Resources/public/js',
|
path: './src/Mine/SeekerBundle/Resources/public/js/build/mine-seeker/',
|
||||||
filename: 'index.js'
|
filename: 'index.js'
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
@@ -13,11 +17,34 @@ const config = module.exports = {
|
|||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
loader: 'babel',
|
loader: 'babel',
|
||||||
query: {
|
query: {
|
||||||
presets: ['es2015', 'react']
|
presets: ['es2015', 'es2016', 'es2017', 'react']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
module.exports = config;
|
let mineUserListConfig = Object.assign({}, config, {
|
||||||
|
entry: './web/bundles/mineseeker/js/mine-user-list.js',
|
||||||
|
output: {
|
||||||
|
path: './src/Mine/SeekerBundle/Resources/public/js/build/mine-user-list/',
|
||||||
|
filename: 'index.js'
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
loaders: [
|
||||||
|
{
|
||||||
|
test: /\.js$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
loader: 'babel',
|
||||||
|
query: {
|
||||||
|
presets: ['es2015', 'es2016', 'es2017', 'react']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
mineSeekerConfig,
|
||||||
|
mineUserListConfig,
|
||||||
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user