Lines 87.87% 29 / 33
Functions and Methods 50.00% 2 / 4
Classes and Traits 0.00% 0 / 1
Name Lines Functions and Methods CRAP Classes and Traits
MonstersSeenEvent 87.87% 29 / 33 50.00% 2 / 4 8.11 0.00% 0 / 1
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 summary 100.00% 5 / 5 100.00% 1 / 1 1
 read 91.30% 21 / 23 0.00% 0 / 1 2.00
 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\World\Monster\MonsterSpawnId;
11use Lorekeeper\Server\Exception\MalformedEventException;
12use Override;
13use Psl\Type;
14use Psl\Type\Exception\CoercionException;
15
16final readonly class MonstersSeenEvent extends MapArrivalEvent
17{
18    /** @param list<SeenMonster> $monsters */
19    public function __construct(
20        public array $monsters,
21    ) {}
22
23    #[Override]
24    public function summary(): string
25    {
26        $alive = count(array_filter(
27            $this->monsters,
28            static fn(SeenMonster $monster): bool => $monster->state !== CombatState::Dead,
29        ));
30
31        return "{$alive} of " . count($this->monsters) . ' monsters are alive';
32    }
33
34    #[Override]
35    protected static function read(array $data): static
36    {
37        try {
38            $monsters = Type\shape([
39                'monBranch' => Type\optional(Type\vec(Type\shape([
40                    'MonMapID' => Type\positive_int(),
41                    'intState' => Type\int_range(min: 0, max: 2),
42                    'intHP' => Type\uint(),
43                    'intHPMax' => Type\uint(),
44                    'intMP' => Type\uint(),
45                    'intMPMax' => Type\uint(),
46                ], allowUnknownFields: true))),
47            ], allowUnknownFields: true)->coerce($data)['monBranch'] ?? [];
48        } catch (CoercionException $exception) {
49            throw new MalformedEventException(static::class, 'monsters are invalid', $exception);
50        }
51
52        return new static(array_map(
53            static fn(array $monster): SeenMonster => new SeenMonster(
54                new MonsterSpawnId($monster['MonMapID']),
55                self::state($monster['intState']),
56                new Health($monster['intHP']),
57                new Health($monster['intHPMax']),
58                new Mana($monster['intMP']),
59                new Mana($monster['intMPMax']),
60            ),
61            $monsters,
62        ));
63    }
64
65    private static function state(int $state): CombatState
66    {
67        return match ($state) {
68            0 => CombatState::Dead,
69            2 => CombatState::Fighting,
70            default => CombatState::Idle,
71        };
72    }
73}