From af13be21966e331d9d25356f44786f273d33fcac Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 5 Jan 2026 15:27:37 +0100 Subject: [PATCH] Messages handling voor spel 1 --- config/packages/messenger.yaml | 2 +- migrations/Version20260105113139.php | 41 ++++ migrations/Version20260105121159.php | 31 +++ src/Game/Entity/Game.php | 67 ++++++ src/Game/Entity/Player.php | 84 ++++++++ src/Game/Entity/Session.php | 89 ++++++++ src/Game/Enum/DecodeMessage.php | 10 + src/Game/Enum/GameStatus.php | 10 + src/Game/Enum/SessionStatus.php | 12 ++ src/Game/Repository/GameRepository.php | 18 ++ src/Game/Repository/PlayerRepository.php | 18 ++ src/Game/Repository/SessionRepository.php | 18 ++ src/Game/Service/GameResponseService.php | 200 ++++++++++++++++++ src/Game/Service/PlayerService.php | 35 +++ src/Tech/Message/ProcessTaskMessage.php | 22 ++ .../ProcessTaskMessageHandler.php | 25 +++ 16 files changed, 681 insertions(+), 1 deletion(-) create mode 100644 migrations/Version20260105113139.php create mode 100644 migrations/Version20260105121159.php create mode 100644 src/Game/Entity/Game.php create mode 100644 src/Game/Entity/Player.php create mode 100644 src/Game/Entity/Session.php create mode 100644 src/Game/Enum/DecodeMessage.php create mode 100644 src/Game/Enum/GameStatus.php create mode 100644 src/Game/Enum/SessionStatus.php create mode 100644 src/Game/Repository/GameRepository.php create mode 100644 src/Game/Repository/PlayerRepository.php create mode 100644 src/Game/Repository/SessionRepository.php create mode 100644 src/Game/Service/PlayerService.php create mode 100644 src/Tech/Message/ProcessTaskMessage.php create mode 100644 src/Tech/MessageHandler/ProcessTaskMessageHandler.php diff --git a/config/packages/messenger.yaml b/config/packages/messenger.yaml index 270f3c7..55a9745 100644 --- a/config/packages/messenger.yaml +++ b/config/packages/messenger.yaml @@ -26,4 +26,4 @@ framework: Symfony\Component\Notifier\Message\SmsMessage: async # Route your messages to the transports - # 'App\Message\YourMessage': async + 'App\Tech\Message\ProcessTaskMessage': async diff --git a/migrations/Version20260105113139.php b/migrations/Version20260105113139.php new file mode 100644 index 0000000..f440d21 --- /dev/null +++ b/migrations/Version20260105113139.php @@ -0,0 +1,41 @@ +addSql('CREATE TABLE game (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, number_of_players INT NOT NULL, status VARCHAR(20) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE player (id INT AUTO_INCREMENT NOT NULL, session_id INT NOT NULL, user_id INT NOT NULL, screen INT NOT NULL, INDEX IDX_98197A65613FECDF (session_id), INDEX IDX_98197A65A76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE session (id INT AUTO_INCREMENT NOT NULL, game_id INT NOT NULL, status VARCHAR(20) NOT NULL, timer INT NOT NULL, created DATETIME NOT NULL, INDEX IDX_D044D5D4E48FD905 (game_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE player ADD CONSTRAINT FK_98197A65613FECDF FOREIGN KEY (session_id) REFERENCES session (id)'); + $this->addSql('ALTER TABLE player ADD CONSTRAINT FK_98197A65A76ED395 FOREIGN KEY (user_id) REFERENCES `user` (id)'); + $this->addSql('ALTER TABLE session ADD CONSTRAINT FK_D044D5D4E48FD905 FOREIGN KEY (game_id) REFERENCES game (id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE player DROP FOREIGN KEY FK_98197A65613FECDF'); + $this->addSql('ALTER TABLE player DROP FOREIGN KEY FK_98197A65A76ED395'); + $this->addSql('ALTER TABLE session DROP FOREIGN KEY FK_D044D5D4E48FD905'); + $this->addSql('DROP TABLE game'); + $this->addSql('DROP TABLE player'); + $this->addSql('DROP TABLE session'); + } +} diff --git a/migrations/Version20260105121159.php b/migrations/Version20260105121159.php new file mode 100644 index 0000000..1b80de2 --- /dev/null +++ b/migrations/Version20260105121159.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE player ADD level JSON DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE player DROP level'); + } +} diff --git a/src/Game/Entity/Game.php b/src/Game/Entity/Game.php new file mode 100644 index 0000000..19d5b72 --- /dev/null +++ b/src/Game/Entity/Game.php @@ -0,0 +1,67 @@ +id; + } + + public function getName(): ?string + { + return $this->name; + } + + public function setName(string $name): static + { + $this->name = $name; + + return $this; + } + + public function getNumberOfPlayers(): ?int + { + return $this->numberOfPlayers; + } + + public function setNumberOfPlayers(int $numberOfPlayers): static + { + $this->numberOfPlayers = $numberOfPlayers; + + return $this; + } + + public function getStatus(): ?GameStatus + { + return $this->status; + } + + public function setStatus(GameStatus $status): static + { + $this->status = $status; + + return $this; + } +} diff --git a/src/Game/Entity/Player.php b/src/Game/Entity/Player.php new file mode 100644 index 0000000..21e857e --- /dev/null +++ b/src/Game/Entity/Player.php @@ -0,0 +1,84 @@ +id; + } + + public function getSession(): ?Session + { + return $this->session; + } + + public function setSession(?Session $session): static + { + $this->session = $session; + + return $this; + } + + public function getUser(): ?User + { + return $this->user; + } + + public function setUser(?User $user): static + { + $this->user = $user; + + return $this; + } + + public function getScreen(): ?int + { + return $this->screen; + } + + public function setScreen(int $screen): static + { + $this->screen = $screen; + + return $this; + } + + public function getLevel(): ?array + { + return $this->level; + } + + public function setLevel(?array $level): static + { + $this->level = $level; + + return $this; + } +} diff --git a/src/Game/Entity/Session.php b/src/Game/Entity/Session.php new file mode 100644 index 0000000..a2afc58 --- /dev/null +++ b/src/Game/Entity/Session.php @@ -0,0 +1,89 @@ +created = new \DateTime(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getGame(): ?Game + { + return $this->game; + } + + public function setGame(?Game $game): static + { + $this->game = $game; + + return $this; + } + + public function getStatus(): ?SessionStatus + { + return $this->status; + } + + public function setStatus(SessionStatus $status): static + { + $this->status = $status; + + return $this; + } + + public function getTimer(): ?int + { + return $this->timer; + } + + public function setTimer(int $timer): static + { + $this->timer = $timer; + + return $this; + } + + public function getCreated(): ?\DateTimeInterface + { + return $this->created; + } + + public function setCreated(\DateTimeInterface $created): static + { + $this->created = $created; + + return $this; + } +} diff --git a/src/Game/Enum/DecodeMessage.php b/src/Game/Enum/DecodeMessage.php new file mode 100644 index 0000000..40f8546 --- /dev/null +++ b/src/Game/Enum/DecodeMessage.php @@ -0,0 +1,10 @@ + + */ +class GameRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Game::class); + } +} diff --git a/src/Game/Repository/PlayerRepository.php b/src/Game/Repository/PlayerRepository.php new file mode 100644 index 0000000..a5add6c --- /dev/null +++ b/src/Game/Repository/PlayerRepository.php @@ -0,0 +1,18 @@ + + */ +class PlayerRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Player::class); + } +} diff --git a/src/Game/Repository/SessionRepository.php b/src/Game/Repository/SessionRepository.php new file mode 100644 index 0000000..6669a61 --- /dev/null +++ b/src/Game/Repository/SessionRepository.php @@ -0,0 +1,18 @@ + + */ +class SessionRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Session::class); + } +} diff --git a/src/Game/Service/GameResponseService.php b/src/Game/Service/GameResponseService.php index d60bdf1..be03411 100644 --- a/src/Game/Service/GameResponseService.php +++ b/src/Game/Service/GameResponseService.php @@ -2,8 +2,19 @@ namespace App\Game\Service; +use App\Game\Enum\DecodeMessage; +use App\Game\Entity\Player; +use App\Tech\Entity\User; +use Symfony\Bundle\SecurityBundle\Security; + class GameResponseService { + public function __construct( + private Security $security, + private PlayerService $playerService, + ) { + } + public function getGameResponse(string $raw) { $info = json_decode($raw, true); @@ -11,10 +22,199 @@ class GameResponseService $message = $info['message'] ?? ''; $ts = $info['ts'] ?? ''; + if(!is_string($message)) + return ['error' => 'Invalid message.']; + $user = $this->security->getUser(); + + if(!$user instanceof User) + return ['error' => 'You are not logged in.']; + + $player = $this->playerService->GetCurrentlyActiveAsPlayer($user); + + if(!$player) + return ['error' => 'You are not in a game.']; + + // TODO: Here i need to add a message handler to save the message in a big log. $data = []; + if(str_starts_with($message, '/')) { + $data = $this->checkGameCommando($message, $player); + } else { + $data = $this->checkConsoleCommando($message, $player); + } + return $data; } + + private function checkGameCommando(string $message, Player $player) : array + { + $messagePart = explode(' ', $message); + + $rechten = json_decode($player->getLevel()); + + switch($messagePart[0]) { + case '/chat': + if(!in_array('chat', $rechten)) + return ['result' => ['Unknown command.']]; + + $this->handleChatMessage($message); + break; + case '/help': + return ['result' => $this->getHelpCommand($rechten)]; + case '/decode': + if(!in_array('decode', $rechten)) + return ['result' => ['Unknown command.']]; + + return ['result' => [$this->handleDecodeMessage($messagePart[1], $player)]]; + case '/verify': + if(!in_array('verify', $rechten)) + return ['result' => ['Unknown command.']]; + + $this->handleVerifyMessage($message); + break; + default: + return ['result' => ['Unknown command.']]; + } + return []; + } + + private function checkConsoleCommando(string $message, Player $player) : array + { + $messagePart = explode(' ', $message); + $rechten = json_decode($player->getLevel()); + switch($messagePart[0]) { + case 'help': + return ['result' => $this->getHelpCommand($rechten)]; + case 'ls': + break; + case 'cd': + break; + case 'rm': + break; + case 'sudo': + break; + default: + return ['result' => ['Unknown command.']]; + } + return []; + } + + private function getHelpCommand(mixed $rechten) : array + { + $messages = []; + + foreach($rechten as $recht) { + switch($recht) { + case 'chat': + $messages[] = '/chat'; + $messages[] = ' Use /chat {message} to send the message to the other agents.'; + $messages[] = ' If you want to send a message specifically to one other agent, use the id of the agent after /chat, like /chat 6 {message}'; + $messages[] = ' This will send the message only to agent with id 6.'; + $messages[] = ' USAGE: /chat {message}'; + $messages[] = ''; + break; + case 'help': + $messages[] = '/help'; + $messages[] = ' This shows this help.'; + $messages[] = ' USAGE: /help'; + $messages[] = ''; + break; + case 'decode': + $messages[] = '/decode'; + $messages[] = ' This message will decode the message followed by it.'; + $messages[] = ' Every agent has a different way to decode messages. This is a security measure. The AI Virus has no access to all decoders.'; + $messages[] = ' USAGE: /decode {message}'; + $messages[] = ''; + break; + case 'cat': + $messages[] = 'cat'; + $messages[] = ' To read a file, use cat {filename}.'; + $messages[] = ' This will print the full content of the file on the screen.'; + $messages[] = ' USAGE: cat {filename}'; + $messages[] = ''; + break; + case 'ls': + $messages[] = 'ls'; + $messages[] = ' To show all the files in the current directory, use ls.'; + $messages[] = ' This will print the full list of directories and files of the current location on your screen.'; + $messages[] = ' USAGE: ls'; + $messages[] = ''; + break; + case 'rm': + $messages[] = 'rm'; + $messages[] = ' Use rm to delete a file.'; + $messages[] = ' Be careful with this command. It can not be undone and we do not want to lose any valuable data.'; + $messages[] = ' USAGE: rm {filename}'; + $messages[] = ''; + break; + case 'cd': + $messages[] = 'cd'; + $messages[] = ' Use cd to move to a different directory.'; + $messages[] = ' You can go into a folder by using cd {foldername}, or a folder up by using "cd ..".'; + $messages[] = ' Using cd / moves you to the root directory.'; + $messages[] = ' USAGE: cd {directory}'; + $messages[] = ''; + break; + case 'sudo': + $messages[] = 'sudo'; + $messages[] = ' If you do not have enough rights to execute a command, you can use sudo to execute it as root.'; + $messages[] = ' This is only possible for verified users. To verify yourself, use the /verify command.'; + $messages[] = ' USAGE: sudo {command}'; + $messages[] = ''; + break; + case 'verify': + $messages[] = '/verify'; + $messages[] = ' You can verify yourself by using this command.'; + $messages[] = ' Use this command and follow instructions to verify yourself.'; + $messages[] = ' USAGE: /verify'; + $messages[] = ''; + break; + } + } + + return $messages; + } + + private function handleChatMessage(string $message) + { + + } + + private function handleDecodeMessage(string $message, Player $player) + { + $userNumber = $player->getScreen(); + + preg_match('/\d+/', $message, $matches); + $num = $matches[0] ?? null; + $randomString = $this->generateRandomString(250, 500); + + if(is_null($num) || $num != $userNumber) + return $randomString; + + foreach (DecodeMessage::cases() as $decodeMessage) { + if ($decodeMessage->name === $message) { + return $decodeMessage->value; + } + } + + return $randomString; + } + + private function generateRandomString(int $min, int $max): string + { + $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ '; + $charactersLength = strlen($characters); + $randomString = ''; + $length = random_int($min, $max); + for ($i = 0; $i < $length; $i++) { + $randomString .= $characters[random_int(0, $charactersLength - 1)]; + } + return $randomString; + } + + private function handleVerifyMessage(string $message) + { + } } diff --git a/src/Game/Service/PlayerService.php b/src/Game/Service/PlayerService.php new file mode 100644 index 0000000..e691d8b --- /dev/null +++ b/src/Game/Service/PlayerService.php @@ -0,0 +1,35 @@ +playerRepository->createQueryBuilder('p') + ->join('p.session', 's') + ->where('p.user = :user') + ->andWhere('s.status IN (:statuses)') + ->setParameter('user', $user) + ->setParameter('statuses', [ + SessionStatus::READY, + SessionStatus::PLAYING, + ]) + ->setMaxResults(1) + ->getQuery() + ->getOneOrNullResult(); + + return $player; + } +} diff --git a/src/Tech/Message/ProcessTaskMessage.php b/src/Tech/Message/ProcessTaskMessage.php new file mode 100644 index 0000000..a37e1c3 --- /dev/null +++ b/src/Tech/Message/ProcessTaskMessage.php @@ -0,0 +1,22 @@ +taskName; + } + + public function getPayload(): array + { + return $this->payload; + } +} diff --git a/src/Tech/MessageHandler/ProcessTaskMessageHandler.php b/src/Tech/MessageHandler/ProcessTaskMessageHandler.php new file mode 100644 index 0000000..5e528f6 --- /dev/null +++ b/src/Tech/MessageHandler/ProcessTaskMessageHandler.php @@ -0,0 +1,25 @@ +logger->info('Processing task: ' . $message->getTaskName(), [ + 'payload' => $message->getPayload(), + ]); + + // Implement logic based on taskName here + } +}