163 lines
6.4 KiB
PHP
163 lines
6.4 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Game\Controller;
|
|
|
|
use App\Game\Entity\Session;
|
|
use App\Game\Entity\SessionSetting;
|
|
use App\Game\Enum\SessionSettingType;
|
|
use App\Game\Enum\SessionStatus;
|
|
use App\Game\Repository\GameRepository;
|
|
use App\Game\Repository\PlayerRepository;
|
|
use App\Game\Repository\SessionRepository;
|
|
use App\Game\Service\GameDashboardService;
|
|
use App\Tech\Entity\User;
|
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
use Symfony\Bundle\SecurityBundle\Security;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\Routing\Annotation\Route;
|
|
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
|
use Symfony\Component\ExpressionLanguage\Expression;
|
|
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
|
|
|
final class GameController extends AbstractController
|
|
{
|
|
public function __construct(
|
|
#[Autowire('%env(MERCURE_PUBLIC_URL)%')]
|
|
private string $mercurePublicUrl
|
|
) {
|
|
}
|
|
|
|
#[Route(path: '', name: 'game_dashboard', methods: ['GET', 'POST'])]
|
|
#[IsGranted(new Expression("is_granted('ROLE_PLAYER') or is_granted('ROLE_ADMIN')"))]
|
|
public function dashboard(
|
|
Request $request,
|
|
GameRepository $gameRepository,
|
|
SessionRepository $sessionRepository,
|
|
GameDashboardService $dashboardService,
|
|
Security $security
|
|
): Response {
|
|
$user = $security->getUser();
|
|
$isAdmin = $this->isGranted('ROLE_ADMIN');
|
|
|
|
if ($request->isMethod('POST')) {
|
|
if ($request->request->has('create_session')) {
|
|
$gameId = $request->request->get('game_id');
|
|
$game = $gameRepository->find($gameId);
|
|
|
|
if ($game) {
|
|
if ($dashboardService->createSession($game, $user, $isAdmin)) {
|
|
$this->addFlash('success', 'New session created!');
|
|
}
|
|
}
|
|
} elseif ($request->request->has('join_session')) {
|
|
$inviteCode = $request->request->get('invite_code');
|
|
if ($dashboardService->joinSession($inviteCode, $user)) {
|
|
$this->addFlash('success', 'Joined session successfully!');
|
|
} else {
|
|
$this->addFlash('error', 'Invalid invite code or session full.');
|
|
}
|
|
} elseif ($request->request->has('create_invite')) {
|
|
$sessionId = $request->request->get('session_id');
|
|
$session = $sessionRepository->find($sessionId);
|
|
|
|
if (!$session) {
|
|
$this->addFlash('error', 'Session not found.');
|
|
return $this->redirectToRoute('game_dashboard');
|
|
}
|
|
|
|
$inviteCode = $dashboardService->generateInviteCode($session, $user, $isAdmin);
|
|
if ($inviteCode) {
|
|
$this->addFlash('success', 'Invite link created: ' . $inviteCode);
|
|
}
|
|
} elseif ($request->request->has('leave_session')) {
|
|
$sessionId = $request->request->get('session_id');
|
|
$session = $sessionRepository->find($sessionId);
|
|
|
|
if ($session) {
|
|
if ($dashboardService->leaveSession($session, $user)) {
|
|
$this->addFlash('success', 'Left session successfully.');
|
|
} else {
|
|
$this->addFlash('error', 'Could not leave session (game might have started).');
|
|
}
|
|
}
|
|
} elseif ($request->request->has('start_session')) {
|
|
$sessionId = $request->request->get('session_id');
|
|
$session = $sessionRepository->find($sessionId);
|
|
|
|
if ($session) {
|
|
if ($dashboardService->startSession($session)) {
|
|
$this->addFlash('success', 'Session started! Screens have been assigned.');
|
|
} else {
|
|
$this->addFlash('error', 'Could not start session. Make sure all players have joined.');
|
|
}
|
|
}
|
|
}
|
|
|
|
return $this->redirectToRoute('game_dashboard');
|
|
}
|
|
|
|
return $this->render('game/dashboard.html.twig', [
|
|
'sessions' => $dashboardService->getSessionsForUser($user),
|
|
'availableGames' => $dashboardService->getAvailableGames($isAdmin),
|
|
]);
|
|
}
|
|
|
|
#[Route(path: '/{session}', name: 'game', methods: ['GET', 'POST'])]
|
|
#[IsGranted(new Expression("is_granted('ROLE_PLAYER') or is_granted('ROLE_ADMIN')"))]
|
|
#[IsGranted('SESSION_VIEW', subject: 'session')]
|
|
public function index(
|
|
Session $session,
|
|
Request $request,
|
|
Security $security,
|
|
PlayerRepository $playerRepository,
|
|
GameDashboardService $dashboardService
|
|
): Response
|
|
{
|
|
$user = $security->getUser();
|
|
if (!$user instanceof User) {
|
|
throw $this->createAccessDeniedException();
|
|
}
|
|
|
|
$player = $playerRepository->findOneBy(['session' => $session, 'user' => $user]);
|
|
|
|
if ($request->isMethod('POST') && $request->request->has('toggle_ready')) {
|
|
$dashboardService->toggleReady($session, $user);
|
|
return $this->redirectToRoute('game', ['session' => $session->getId()]);
|
|
}
|
|
|
|
// Periodically check readiness timeout
|
|
$dashboardService->checkAllPlayersReady($session);
|
|
|
|
if ($session->getStatus() === SessionStatus::READY) {
|
|
$isReady = false;
|
|
$readyAt = null;
|
|
if ($player) {
|
|
$settingName = SessionSettingType::tryFrom('ReadyAtForPlayer' . $player->getScreen());
|
|
if ($settingName) {
|
|
$setting = $session->getSettings()->filter(fn(SessionSetting $s) => $s->getName() === $settingName && $s->getPlayer() === $player)->first();
|
|
if ($setting) {
|
|
$isReady = true;
|
|
$readyAt = (int)$setting->getValue();
|
|
}
|
|
}
|
|
}
|
|
|
|
return $this->render('game/waiting.html.twig', [
|
|
'session' => $session,
|
|
'isReady' => $isReady,
|
|
'readyAt' => $readyAt,
|
|
'mercure_public_url' => $this->mercurePublicUrl,
|
|
]);
|
|
}
|
|
|
|
$screen = $player ? $player->getScreen() : 0;
|
|
|
|
return $this->render('game/index.html.twig', [
|
|
'session' => $session,
|
|
'screen' => $screen,
|
|
]);
|
|
}
|
|
}
|