Add mainframe hint system and cron-driven timeout handling
The cron (app:hints:check, every minute) now walks each playing
player through a strict dependency chain - help, communication,
verification, navigation, rapports/decode, endgame urgency - and
sends at most one hint per player per run: the first step that's
both unresolved and old enough to nudge about. Later steps genuinely
depend on earlier ones (e.g. /verify isn't usable until a player has
finished contacting everyone), so a player never gets a hint for
something they can't act on yet.
Two bits of new tracking were needed:
- Help command usage wasn't recorded anywhere, so it's now saved to
a new HelpUsedForPlayer{N} session setting.
- "All messages decoded" needed a reliable session-wide signal, so
the rm right (previously granted alongside sudo when player 1
decodes) now comes from player 3's decode instead, making
sudo+scan+rm together mean "the whole team has decoded".
The cron also now finishes sessions whose countdown has run out:
sets the session to LOST and broadcasts the same game_finished
Mercure event the win path already uses, so every connected player
gets pushed to the lost page within a minute of the game actually
ending - not just whichever player's own client-side timer happens
to notice first.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -136,6 +136,35 @@ class GameResponseService
|
||||
return json_decode($setting->getValue(), true) ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Records that a player has used the help command, so SendMainframeHintsCommand
|
||||
* can stop nudging them towards it. Absence of this setting means "not used yet".
|
||||
*/
|
||||
private function markHelpCommandUsed(Player $player): void
|
||||
{
|
||||
$settingName = SessionSettingType::tryFrom('HelpUsedForPlayer' . $player->getScreen());
|
||||
|
||||
if (!$settingName) {
|
||||
return;
|
||||
}
|
||||
|
||||
$setting = $this->sessionSettingRepository->getSetting($player->getSession(), $settingName, $player);
|
||||
if ($setting && $setting->getValue() === 'true') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$setting) {
|
||||
$setting = new SessionSetting();
|
||||
$setting->setSession($player->getSession());
|
||||
$setting->setPlayer($player);
|
||||
$setting->setName($settingName);
|
||||
}
|
||||
|
||||
$setting->setValue('true');
|
||||
$this->entityManager->persist($setting);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
private function checkGameCommando(string $message, Player $player) : array
|
||||
{
|
||||
$messagePart = explode(' ', $message);
|
||||
@@ -152,7 +181,8 @@ class GameResponseService
|
||||
else
|
||||
return ['result' => ['Error sending']];
|
||||
case '/help':
|
||||
return ['result' => $this->getHelpCommand($rechten)];
|
||||
$this->markHelpCommandUsed($player);
|
||||
return ['result' => $this->getHelpCommand($rechten, $player)];
|
||||
case '/decode':
|
||||
if(!in_array('decode', $rechten))
|
||||
return ['result' => ['Unknown command']];
|
||||
@@ -175,7 +205,8 @@ class GameResponseService
|
||||
$rechten = $this->getRechten($player);
|
||||
switch($messagePart[0]) {
|
||||
case 'help':
|
||||
return ['result' => $this->getHelpCommand($rechten)];
|
||||
$this->markHelpCommandUsed($player);
|
||||
return ['result' => $this->getHelpCommand($rechten, $player)];
|
||||
case 'ls':
|
||||
if(!in_array('ls', $rechten))
|
||||
return ['result' => ['Unknown command']];
|
||||
@@ -281,9 +312,9 @@ class GameResponseService
|
||||
}
|
||||
}
|
||||
|
||||
private function getHelpCommand(mixed $rechten) : array
|
||||
private function getHelpCommand(mixed $rechten, Player $player) : array
|
||||
{
|
||||
$messages = [];
|
||||
$messages = ['Help function for Agent ' . $player->getScreen() . ':'];
|
||||
|
||||
foreach($rechten as $recht) {
|
||||
switch($recht) {
|
||||
@@ -566,13 +597,16 @@ class GameResponseService
|
||||
|
||||
if ($decodeMessage === DecodeMessage::PLAYER_1) {
|
||||
$this->grantRightToAllPlayers($player->getSession(), 'sudo');
|
||||
$this->grantRightToAllPlayers($player->getSession(), 'rm');
|
||||
}
|
||||
|
||||
if ($decodeMessage === DecodeMessage::PLAYER_2) {
|
||||
$this->grantRightToAllPlayers($player->getSession(), 'scan');
|
||||
}
|
||||
|
||||
if ($decodeMessage === DecodeMessage::PLAYER_3) {
|
||||
$this->grantRightToAllPlayers($player->getSession(), 'rm');
|
||||
}
|
||||
|
||||
return $decodeMessage->value;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user