Trying to add waiting pages

This commit is contained in:
Frank
2026-01-08 19:32:13 +01:00
parent 37507bd169
commit c4c989db4c
7 changed files with 505 additions and 15 deletions

View File

@@ -15,6 +15,9 @@ use App\Game\Repository\SessionRepository;
use App\Tech\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Mercure\HubInterface;
use Symfony\Component\Mercure\Update;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
final class GameDashboardService
{
@@ -22,6 +25,9 @@ final class GameDashboardService
private readonly GameRepository $gameRepository,
private readonly SessionRepository $sessionRepository,
private readonly EntityManagerInterface $entityManager,
private readonly HubInterface $hub,
#[Autowire('%env(MERCURE_TOPIC_BASE)%')]
private readonly string $mercureTopicBase,
) {
}
@@ -66,13 +72,17 @@ final class GameDashboardService
$player = new Player();
$player->setUser($user);
$player->setSession($session);
$session->addPlayer($player);
$this->entityManager->persist($session);
$this->entityManager->persist($player);
$this->entityManager->flush();
if (count($session->getPlayers()) === $session->getGame()->getNumberOfPlayers()) {
$this->startSession($session);
}
return $session;
}
@@ -107,12 +117,16 @@ final class GameDashboardService
$player = new Player();
$player->setUser($user);
$player->setSession($session);
$session->addPlayer($player);
$this->entityManager->persist($player);
$this->entityManager->flush();
if (count($session->getPlayers()) === $session->getGame()->getNumberOfPlayers()) {
$this->startSession($session);
}
return true;
}
@@ -122,7 +136,7 @@ final class GameDashboardService
return false;
}
if ($session->getStatus() !== SessionStatus::CREATED || $session->getTimer() > 0) {
if (!in_array($session->getStatus(), [SessionStatus::CREATED, SessionStatus::READY]) || $session->getTimer() > 0) {
return false;
}
@@ -138,6 +152,14 @@ final class GameDashboardService
return false;
}
if ($session->getStatus() === SessionStatus::READY) {
$session->setStatus(SessionStatus::CREATED);
// Clear assignments for all remaining players since the game needs to be "started" again
foreach ($session->getPlayers() as $player) {
$player->setScreen(null);
}
}
// Remove player specific settings (like rights)
foreach ($session->getSettings() as $setting) {
if ($setting->getPlayer() === $playerToDelete) {
@@ -240,6 +262,14 @@ final class GameDashboardService
return false;
}
// Clean up any existing assignments (e.g. if we reverted from READY to CREATED)
foreach ($session->getSettings() as $setting) {
if ($setting->getPlayer() !== null) {
$session->removeSetting($setting);
$this->entityManager->remove($setting);
}
}
// Shuffle players to assign random screens
shuffle($players);
@@ -257,6 +287,113 @@ final class GameDashboardService
return true;
}
public function toggleReady(Session $session, User $user): bool
{
if ($session->getStatus() !== SessionStatus::READY) {
return false;
}
$player = null;
foreach ($session->getPlayers() as $p) {
if ($p->getUser() === $user) {
$player = $p;
break;
}
}
if (!$player) {
return false;
}
$settingName = SessionSettingType::tryFrom('ReadyAtForPlayer' . $player->getScreen());
if (!$settingName) {
return false;
}
/** @var \App\Game\Repository\SessionSettingRepository $settingRepo */
$settingRepo = $this->entityManager->getRepository(SessionSetting::class);
$setting = $settingRepo->getSetting($session, $settingName, $player);
if ($setting) {
$session->removeSetting($setting);
$this->entityManager->remove($setting);
} else {
$setting = new SessionSetting();
$setting->setSession($session);
$setting->setPlayer($player);
$setting->setName($settingName);
$setting->setValue((string)(new \DateTime())->getTimestamp());
$this->entityManager->persist($setting);
}
$this->checkAllPlayersReady($session);
$this->entityManager->flush();
$topic = $this->mercureTopicBase . '/game/hub-' . $session->getId();
$this->hub->publish(new Update($topic, json_encode(['type' => 'player_ready', 'player' => $player->getScreen(), 'ready' => !$setting])));
return true;
}
public function checkAllPlayersReady(Session $session): void
{
if ($session->getStatus() !== SessionStatus::READY) {
return;
}
$players = $session->getPlayers();
$numPlayers = $session->getGame()->getNumberOfPlayers();
if (count($players) < $numPlayers) {
return;
}
$readyPlayersCount = 0;
$now = new \DateTime();
/** @var \App\Game\Repository\SessionSettingRepository $settingRepo */
$settingRepo = $this->entityManager->getRepository(SessionSetting::class);
foreach ($players as $player) {
$settingName = SessionSettingType::tryFrom('ReadyAtForPlayer' . $player->getScreen());
if (!$settingName) {
continue;
}
$setting = $settingRepo->getSetting($session, $settingName, $player);
if ($setting) {
$readyAtTimestamp = (int)$setting->getValue();
// Check timeout: 1 minute = 60 seconds
if (($now->getTimestamp() - $readyAtTimestamp) > 60) {
$session->removeSetting($setting);
$this->entityManager->remove($setting);
} else {
$readyPlayersCount++;
}
}
}
if ($readyPlayersCount === $numPlayers) {
$session->setStatus(SessionStatus::PLAYING);
$this->entityManager->persist($session);
// Clean up ready settings
foreach ($players as $player) {
$settingName = SessionSettingType::tryFrom('ReadyAtForPlayer' . $player->getScreen());
if ($settingName) {
$setting = $settingRepo->getSetting($session, $settingName, $player);
if ($setting) {
$session->removeSetting($setting);
$this->entityManager->remove($setting);
}
}
}
$topic = $this->mercureTopicBase . '/game/hub-' . $session->getId();
$this->hub->publish(new Update($topic, json_encode(['type' => 'all_ready'])));
}
}
public function generateInviteCode(Session $session, UserInterface $user, bool $isAdmin): ?string
{
// Security check: is user part of this session?