Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Failed Conditions
Push — main ( 5797ad...3faf69 )
by Dan
29s queued 24s
created

AttackPlayerProcessor::build()   F

Complexity

Conditions 23
Paths 2688

Size

Total Lines 115
Code Lines 70

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 23
eloc 70
nc 2688
nop 1
dl 0
loc 115
rs 0
c 1
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php declare(strict_types=1);
2
3
namespace Smr\Pages\Player;
4
5
use AbstractSmrPlayer;
6
use Smr\Database;
7
use Smr\Epoch;
8
use Smr\Page\PlayerPageProcessor;
9
use Smr\SectorLock;
10
use SmrPlayer;
11
12
class AttackPlayerProcessor extends PlayerPageProcessor {
13
14
	public function __construct(
15
		private readonly int $targetAccountID
16
	) {}
17
18
	public function build(AbstractSmrPlayer $player): never {
19
		$account = $player->getAccount();
20
		$sector = $player->getSector();
21
22
		if ($player->hasNewbieTurns()) {
23
			create_error('You are under newbie protection.');
24
		}
25
		if ($player->hasFederalProtection()) {
26
			create_error('You are under federal protection.');
27
		}
28
		if ($player->isLandedOnPlanet()) {
29
			create_error('You cannot attack whilst on a planet!');
30
		}
31
		if ($player->getTurns() < TURNS_TO_SHOOT_SHIP) {
32
			create_error('You have insufficient turns to perform that action.');
33
		}
34
		if (!$player->canFight()) {
35
			create_error('You are not allowed to fight!');
36
		}
37
38
		$targetPlayer = SmrPlayer::getPlayer($this->targetAccountID, $player->getGameID());
39
40
		if ($player->traderNAPAlliance($targetPlayer)) {
41
			create_error('Your alliance does not allow you to attack this trader.');
42
		} elseif ($targetPlayer->isDead()) {
43
			create_error('Target is already dead.');
44
		} elseif ($targetPlayer->getSectorID() != $player->getSectorID()) {
45
			create_error('Target is no longer in this sector.');
46
		} elseif ($targetPlayer->hasNewbieTurns()) {
47
			create_error('Target is under newbie protection.');
48
		} elseif ($targetPlayer->isLandedOnPlanet()) {
49
			create_error('Target is protected by planetary shields.');
50
		} elseif ($targetPlayer->hasFederalProtection()) {
51
			create_error('Target is under federal protection.');
52
		}
53
54
		$fightingPlayers = $sector->getFightingTraders($player, $targetPlayer);
55
56
		// Randomize players so that the attack order is always different
57
		shuffle($fightingPlayers['Attackers']);
58
		shuffle($fightingPlayers['Defenders']);
59
60
		//decloak all fighters
61
		foreach ($fightingPlayers as $teamPlayers) {
62
			foreach ($teamPlayers as $teamPlayer) {
63
				$teamPlayer->getShip()->decloak();
64
			}
65
		}
66
67
		// Take off the 3 turns for attacking
68
		$player->takeTurns(TURNS_TO_SHOOT_SHIP);
69
		$player->update();
70
71
		/**
72
		 * @param array<string, array<int, AbstractSmrPlayer>> $fightingPlayers
73
		 * @return array<string, mixed>
74
		 */
75
		$teamAttack = function(array $fightingPlayers, string $attack, string $defend): array {
76
			$results = ['Traders' => [], 'TotalDamage' => 0];
77
			foreach ($fightingPlayers[$attack] as $accountID => $teamPlayer) {
78
				$playerResults = $teamPlayer->shootPlayers($fightingPlayers[$defend]);
79
				$results['Traders'][$teamPlayer->getAccountID()] = $playerResults;
80
				$results['TotalDamage'] += $playerResults['TotalDamage'];
81
82
				// Award assists (if there are multiple attackers)
83
				if (count($fightingPlayers[$attack]) > 1) {
84
					foreach ($playerResults['Weapons'] as $weaponResults) {
85
						if (isset($weaponResults['KillResults'])) {
86
							foreach ($fightingPlayers[$attack] as $assistPlayer) {
87
								if (!$assistPlayer->equals($teamPlayer)) {
88
									$assistPlayer->increaseAssists(1);
89
								}
90
							}
91
						}
92
					}
93
				}
94
			}
95
			return $results;
96
		};
97
98
		$results = [
99
			'Attackers' => $teamAttack($fightingPlayers, 'Attackers', 'Defenders'),
100
			'Defenders' => $teamAttack($fightingPlayers, 'Defenders', 'Attackers'),
101
		];
102
103
		$account->log(LOG_TYPE_TRADER_COMBAT, 'Player attacks player, their team does ' . $results['Attackers']['TotalDamage'] . ' and the other team does ' . $results['Defenders']['TotalDamage'], $sector->getSectorID());
104
105
		$db = Database::getInstance();
106
		$db->insert('combat_logs', [
107
			'game_id' => $db->escapeNumber($player->getGameID()),
108
			'type' => $db->escapeString('PLAYER'),
109
			'sector_id' => $db->escapeNumber($sector->getSectorID()),
110
			'timestamp' => $db->escapeNumber(Epoch::time()),
111
			'attacker_id' => $db->escapeNumber($player->getAccountID()),
112
			'attacker_alliance_id' => $db->escapeNumber($player->getAllianceID()),
113
			'defender_id' => $db->escapeNumber($this->targetAccountID),
114
			'defender_alliance_id' => $db->escapeNumber($targetPlayer->getAllianceID()),
115
			'result' => $db->escapeObject($results, true),
116
		]);
117
118
		// If player died they are now in another sector, and thus locks need reset
119
		if ($player->isDead()) {
120
			saveAllAndReleaseLock(updateSession: false);
121
			// Grab the lock in the new sector to avoid reloading session
122
			SectorLock::getInstance()->acquireForPlayer($player);
123
		}
124
125
		// If player or target is dead there is no continue attack button
126
		if ($player->isDead() || $targetPlayer->isDead()) {
127
			$targetAccountID = null;
128
		} else {
129
			$targetAccountID = $this->targetAccountID;
130
		}
131
		$container = new AttackPlayer($results, $targetAccountID, $player->isDead());
132
		$container->go();
133
	}
134
135
}
136