Lines 76.59% 36 / 47
Functions and Methods 40.00% 2 / 5
Classes and Traits 0.00% 0 / 1
Name Lines Functions and Methods CRAP Classes and Traits
PlayersSeenEvent 76.59% 36 / 47 40.00% 2 / 5 22.15 0.00% 0 / 1
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 summary 100.00% 1 / 1 100.00% 1 / 1 1
 read 93.54% 29 / 31 0.00% 0 / 1 2.00
 pad 30.00% 3 / 10 0.00% 0 / 1 44.30
 state 50.00% 2 / 4 0.00% 0 / 1 6.00
1<?php
2
3declare(strict_types=1);
4
5namespace Lorekeeper\Server\Event\Map;
6
7use Lorekeeper\Core\Attribute\Health;
8use Lorekeeper\Core\Attribute\Mana;
9use Lorekeeper\Core\Combat\CombatState;
10use Lorekeeper\Core\Player\PlayerLevel;
11use Lorekeeper\Core\Player\PlayerName;
12use Lorekeeper\Core\World\Map\Cell;
13use Lorekeeper\Core\World\Map\Pad;
14use Lorekeeper\Server\Exception\MalformedEventException;
15use Override;
16use Psl\Type;
17use Psl\Type\Exception\CoercionException;
18
19final readonly class PlayersSeenEvent extends MapArrivalEvent
20{
21    /** @param list<SeenPlayer> $players */
22    public function __construct(
23        public array $players,
24    ) {}
25
26    #[Override]
27    public function summary(): string
28    {
29        return count($this->players) . ' players are in the map';
30    }
31
32    #[Override]
33    protected static function read(array $data): static
34    {
35        try {
36            $players = Type\shape([
37                'uoBranch' => Type\vec(Type\shape([
38                    'strUsername' => Type\non_empty_string(),
39                    'intLevel' => Type\int_range(min: 1, max: 100),
40                    'strFrame' => Type\non_empty_string(),
41                    'strPad' => Type\non_empty_string(),
42                    'intState' => Type\int_range(min: 0, max: 2),
43                    'intHP' => Type\uint(),
44                    'intHPMax' => Type\uint(),
45                    'intMP' => Type\uint(),
46                    'intMPMax' => Type\uint(),
47                    'afk' => Type\bool(),
48                ], allowUnknownFields: true)),
49            ], allowUnknownFields: true)->coerce($data)['uoBranch'];
50        } catch (CoercionException $exception) {
51            throw new MalformedEventException(static::class, 'players are missing or invalid', $exception);
52        }
53
54        return new static(array_map(
55            static fn(array $player): SeenPlayer => new SeenPlayer(
56                new PlayerName($player['strUsername']),
57                new PlayerLevel($player['intLevel']),
58                new Cell($player['strFrame']),
59                self::pad($player['strPad']),
60                self::state($player['intState']),
61                new Health($player['intHP']),
62                new Health($player['intHPMax']),
63                new Mana($player['intMP']),
64                new Mana($player['intMPMax']),
65                $player['afk'],
66            ),
67            $players,
68        ));
69    }
70
71    /** @throws MalformedEventException */
72    private static function pad(string $pad): Pad
73    {
74        return match (strtolower($pad)) {
75            'left' => Pad::Left,
76            'right' => Pad::Right,
77            'top' => Pad::Top,
78            'bottom' => Pad::Bottom,
79            'up' => Pad::Up,
80            'down' => Pad::Down,
81            'center' => Pad::Center,
82            'spawn' => Pad::Spawn,
83            default => throw new MalformedEventException(static::class, "unknown pad '{$pad}'"),
84        };
85    }
86
87    private static function state(int $state): CombatState
88    {
89        return match ($state) {
90            0 => CombatState::Dead,
91            2 => CombatState::Fighting,
92            default => CombatState::Idle,
93        };
94    }
95}