Lines 95.45% 21 / 22
Functions and Methods 75.00% 3 / 4
Classes and Traits 0.00% 0 / 1
Name Lines Functions and Methods CRAP Classes and Traits
EnterGameScript 95.45% 21 / 22 75.00% 3 / 4 8 0.00% 0 / 1
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 title 0.00% 0 / 1 0.00% 0 / 1 2
 run 100.00% 19 / 19 100.00% 1 / 1 5
 await 100.00% 1 / 1 100.00% 1 / 1 1
1<?php
2
3declare(strict_types=1);
4
5namespace Lorekeeper\Client\Script\Game;
6
7use Generator;
8use Lorekeeper\Client\Character;
9use Lorekeeper\Client\Command\Inventory\LoadPlayerInventoryCommand;
10use Lorekeeper\Client\Command\Map\JoinInitialMapCommand;
11use Lorekeeper\Client\Command\Session\LoginCommand;
12use Lorekeeper\Client\Command\Session\PolicyFileRequestCommand;
13use Lorekeeper\Client\Login\GameLogin;
14use Lorekeeper\Client\Script\Await;
15use Lorekeeper\Client\Script\Script;
16use Lorekeeper\Client\Script\Send;
17use Lorekeeper\Client\Script\TimedOut;
18use Lorekeeper\Server\Event\Event;
19use Lorekeeper\Server\Event\Inventory\PlayerInventoryLoadedEvent;
20use Lorekeeper\Server\Event\Map\MovedToMapEvent;
21use Lorekeeper\Server\Event\Session\ConnectionEstablishedEvent;
22use Lorekeeper\Server\Event\Session\LoginFailedEvent;
23use Lorekeeper\Server\Event\Session\LoginSucceededEvent;
24use Override;
25use Psl\DateTime\Duration;
26
27/** @implements Script<InGame|LoginFailedEvent|TimedOut> */
28final readonly class EnterGameScript implements Script
29{
30    private const int TIMEOUT_SECONDS = 15;
31
32    public function __construct(
33        private GameLogin $login,
34    ) {}
35
36    #[Override]
37    public function title(): string
38    {
39        return 'Enter the game';
40    }
41
42    /** @return Generator<int, Send, null|Event|TimedOut, InGame|LoginFailedEvent|TimedOut> */
43    #[Override]
44    public function run(Character $me): Generator
45    {
46        $policy = yield new Send(new PolicyFileRequestCommand(), self::await(ConnectionEstablishedEvent::class));
47        if ($policy instanceof TimedOut) {
48            return $policy;
49        }
50
51        /** @var LoginSucceededEvent|LoginFailedEvent|TimedOut $login */
52        $login = yield new Send(
53            new LoginCommand($this->login->player, $this->login->token, $this->login->version),
54            self::await(LoginSucceededEvent::class, LoginFailedEvent::class),
55        );
56        if (!$login instanceof LoginSucceededEvent) {
57            return $login;
58        }
59
60        /** @var MovedToMapEvent|TimedOut $map */
61        $map = yield new Send(new JoinInitialMapCommand(), self::await(MovedToMapEvent::class));
62        if (!$map instanceof MovedToMapEvent) {
63            return $map;
64        }
65
66        $inventory = yield new Send(
67            new LoadPlayerInventoryCommand($map->areaId, $login->socketId),
68            self::await(PlayerInventoryLoadedEvent::class),
69        );
70        if ($inventory instanceof TimedOut) {
71            return $inventory;
72        }
73
74        return new InGame($login->socketId, $map);
75    }
76
77    /**
78     * @param class-string<Event> $event
79     * @param class-string<Event> ...$more
80     */
81    private static function await(string $event, string ...$more): Await
82    {
83        return new Await([$event, ...array_values($more)], Duration::seconds(self::TIMEOUT_SECONDS));
84    }
85}