Lines 100.00% 46 / 46
Methods 100.00% 4 / 4
Classes 100.00% 1 / 1
Name Lines Methods CRAP
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 from 100.00% 37 / 37 100.00% 1 / 1 5
 summary 100.00% 2 / 2 100.00% 1 / 1 1
 [Lorekeeper\Server\Event\NamedAfterClass] name 100.00% 6 / 6 100.00% 1 / 1 1
29final readonly class PlayerDataLoadedEvent implements Event
30{
31    use NamedAfterClass;
32
33    /** @param non-empty-list<PlayerData> $players */
34    public function __construct(
35        public array $players,
36    ) {}
37
38    /** @return Option\Option<static> */
39    #[Override]
40    public static function from(Message $message): Option\Option
41    {
42        if (!$message instanceof JsonMessage || ($message->data['cmd'] ?? null) !== 'initUserDatas') {
43            return Option\none();
44        }
45
46        try {
47            $entries = Type\non_empty_vec(Type\shape([
48                'uid' => Type\positive_int(),
49                'data' => Type\shape([
50                    'strUsername' => Type\non_empty_string(),
51                    'intLevel' => Type\int_range(min: 1, max: 100),
52                    'intExp' => Type\uint(),
53                    'intExpToLevel' => Type\uint(),
54                    'intGold' => Type\uint(),
55                    'intCoins' => Type\uint(),
56                    'iUpg' => Type\int(),
57                    'iBagSlots' => Type\positive_int(),
58                ], allowUnknownFields: true),
59            ], allowUnknownFields: true))
60                ->coerce($message->data['a'] ?? null);
61
62            $players = [];
63            foreach ($entries as $entry) {
64                $data = $entry['data'];
65                $players[] = new PlayerData(
66                    new SocketId($entry['uid']),
67                    new PlayerName($data['strUsername']),
68                    new PlayerLevelProgress(
69                        new PlayerLevel($data['intLevel']),
70                        new Gauge(
71                            new Experience($data['intExp']),
72                            new Experience(max($data['intExp'], $data['intExpToLevel'])),
73                        ),
74                    ),
75                    new Wallet(new Gold($data['intGold']), new AdventureCoins($data['intCoins'])),
76                    $data['iUpg'] > 0,
77                    new Quantity($data['iBagSlots']),
78                    new PlayerQuestMarks(QuestMarks::held($data)),
79                );
80            }
81        } catch (CoercionException $exception) {
82            throw new MalformedEventException(static::class, 'player data is missing or invalid', $exception);
83        }
84
85        return Option\some(new static($players));
86    }
87
88    #[Override]
89    public function summary(): string
90    {
91        return 'Data of '
92        . implode(', ', array_map(static fn(PlayerData $player): string => $player->name->value, $this->players));
93    }
94}

From Lorekeeper\Server\Event\NamedAfterClass

7trait NamedAfterClass
8{
9    public function name(): string
10    {
11        $class = static::class;
12
13        return (string) preg_replace(
14            '/Event$/',
15            replacement: '',
16            subject: substr($class, (int) strrpos($class, needle: '\\') + 1),
17        );
18    }
19}