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

Passed
Pull Request — master (#932)
by Dan
04:13
created

SmrSector::isLinked()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 2
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php declare(strict_types=1);
2
3
// Exception thrown when a sector cannot be found in the database
4
class SectorNotFoundException extends Exception {}
5
6
class SmrSector {
7
	protected static $CACHE_SECTORS = array();
8
	protected static $CACHE_GALAXY_SECTORS = array();
9
	protected static $CACHE_LOCATION_SECTORS = array();
10
11
	protected $db;
12
	protected $SQL;
13
14
	protected $gameID;
15
	protected $sectorID;
16
	protected $battles;
17
	protected $galaxyID;
18
	protected $visited = array();
19
	protected $links;
20
	protected $warp;
21
22
	protected $hasChanged = false;
23
	protected $isNew = false;
24
25
	/**
26
	 * Constructs the sector to determine if it exists.
27
	 * Returns a boolean value.
28
	 */
29
	public static function sectorExists($gameID, $sectorID) {
30
		try {
31
			self::getSector($gameID, $sectorID);
32
			return true;
33
		} catch (SectorNotFoundException $e) {
34
			return false;
35
		}
36
	}
37
38
	public static function getGalaxySectors($gameID, $galaxyID, $forceUpdate = false) {
39
		if ($forceUpdate || !isset(self::$CACHE_GALAXY_SECTORS[$gameID][$galaxyID])) {
40
			$db = new SmrMySqlDatabase();
41
			$db->query('SELECT * FROM sector WHERE game_id = ' . $db->escapeNumber($gameID) . ' AND galaxy_id=' . $db->escapeNumber($galaxyID) . ' ORDER BY sector_id ASC');
42
			$sectors = array();
43
			while ($db->nextRecord()) {
44
				$sectorID = $db->getInt('sector_id');
45
				$sectors[$sectorID] = self::getSector($gameID, $sectorID, $forceUpdate, $db);
46
			}
47
			self::$CACHE_GALAXY_SECTORS[$gameID][$galaxyID] = $sectors;
48
		}
49
		return self::$CACHE_GALAXY_SECTORS[$gameID][$galaxyID];
50
	}
51
52
	public static function getLocationSectors($gameID, $locationTypeID, $forceUpdate = false) {
53
		if ($forceUpdate || !isset(self::$CACHE_LOCATION_SECTORS[$gameID][$locationTypeID])) {
54
			$db = new SmrMySqlDatabase();
55
			$db->query('SELECT * FROM location JOIN sector USING (game_id, sector_id) WHERE location_type_id = ' . $db->escapeNumber($locationTypeID) . ' AND game_id=' . $db->escapeNumber($gameID) . ' ORDER BY sector_id ASC');
56
			$sectors = array();
57
			while ($db->nextRecord()) {
58
				$sectorID = $db->getInt('sector_id');
59
				$sectors[$sectorID] = self::getSector($gameID, $sectorID, $forceUpdate, $db);
60
			}
61
			self::$CACHE_LOCATION_SECTORS[$gameID][$locationTypeID] = $sectors;
62
		}
63
		return self::$CACHE_LOCATION_SECTORS[$gameID][$locationTypeID];
64
	}
65
66
	public static function getSector($gameID, $sectorID, $forceUpdate = false, $db = null) {
67
		if (!isset(self::$CACHE_SECTORS[$gameID][$sectorID]) || $forceUpdate) {
68
			self::$CACHE_SECTORS[$gameID][$sectorID] = new SmrSector($gameID, $sectorID, false, $db);
69
		}
70
		return self::$CACHE_SECTORS[$gameID][$sectorID];
71
	}
72
73
	public static function clearCache() {
74
		self::$CACHE_LOCATION_SECTORS = array();
75
		self::$CACHE_GALAXY_SECTORS = array();
76
		self::$CACHE_SECTORS = array();
77
	}
78
79
	public static function saveSectors() {
80
		foreach (self::$CACHE_SECTORS as $gameSectors) {
81
			foreach ($gameSectors as $sector) {
82
				$sector->update();
83
			}
84
		}
85
	}
86
87
	public static function createSector($gameID, $sectorID) {
88
		if (!isset(self::$CACHE_SECTORS[$gameID][$sectorID])) {
89
			$s = new SmrSector($gameID, $sectorID, true);
90
			self::$CACHE_SECTORS[$gameID][$sectorID] = $s;
91
		}
92
		return self::$CACHE_SECTORS[$gameID][$sectorID];
93
	}
94
95
	protected function __construct($gameID, $sectorID, $create = false, $db = null) {
96
		$this->db = new SmrMySqlDatabase();
97
		$this->SQL = 'game_id = ' . $this->db->escapeNumber($gameID) . ' AND sector_id = ' . $this->db->escapeNumber($sectorID);
98
99
		// Do we already have a database query for this sector?
100
		if (isset($db)) {
101
			$sectorExists = true;
102
		} else {
103
			$db = $this->db;
104
			$db->query('SELECT * FROM sector WHERE ' . $this->SQL . ' LIMIT 1');
105
			$sectorExists = $db->nextRecord();
106
		}
107
108
		$this->gameID = (int)$gameID;
109
		$this->sectorID = (int)$sectorID;
110
111
		if ($sectorExists) {
112
			$this->galaxyID = $db->getInt('galaxy_id');
113
			$this->battles = $db->getInt('battles');
114
115
			$this->links = array();
116
			if ($db->getInt('link_up')) {
117
				$this->links['Up'] = $db->getInt('link_up');
118
			}
119
			if ($db->getInt('link_down')) {
120
				$this->links['Down'] = $db->getInt('link_down');
121
			}
122
			if ($db->getInt('link_left')) {
123
				$this->links['Left'] = $db->getInt('link_left');
124
			}
125
			if ($db->getInt('link_right')) {
126
				$this->links['Right'] = $db->getInt('link_right');
127
			}
128
			$this->warp = $db->getInt('warp');
129
		} elseif ($create) {
130
			$this->battles = 0;
131
			$this->links = array();
132
			$this->warp = 0;
133
			$this->isNew = true;
134
			return;
135
		} else {
136
			throw new SectorNotFoundException('No sector ' . $sectorID . ' in game ' . $gameID);
137
		}
138
	}
139
140
	public function update() {
141
		if ($this->isNew) {
142
			$this->db->query('INSERT INTO sector(sector_id,game_id,galaxy_id,link_up,link_down,link_left,link_right,warp)
143
								values
144
								(' . $this->db->escapeNumber($this->getSectorID()) .
145
								',' . $this->db->escapeNumber($this->getGameID()) .
146
								',' . $this->db->escapeNumber($this->getGalaxyID()) .
147
								',' . $this->db->escapeNumber($this->getLinkUp()) .
148
								',' . $this->db->escapeNumber($this->getLinkDown()) .
149
								',' . $this->db->escapeNumber($this->getLinkLeft()) .
150
								',' . $this->db->escapeNumber($this->getLinkRight()) .
151
								',' . $this->db->escapeNumber($this->getWarp()) .
152
								')');
153
		} elseif ($this->hasChanged) {
154
			$this->db->query('UPDATE sector SET battles = ' . $this->db->escapeNumber($this->getBattles()) .
155
									', galaxy_id=' . $this->db->escapeNumber($this->getGalaxyID()) .
156
									', link_up=' . $this->db->escapeNumber($this->getLinkUp()) .
157
									', link_right=' . $this->db->escapeNumber($this->getLinkRight()) .
158
									', link_down=' . $this->db->escapeNumber($this->getLinkDown()) .
159
									', link_left=' . $this->db->escapeNumber($this->getLinkLeft()) .
160
									', warp=' . $this->db->escapeNumber($this->getWarp()) .
161
								' WHERE ' . $this->SQL . ' LIMIT 1');
162
		}
163
		$this->isNew = false;
164
		$this->hasChanged = false;
165
	}
166
167
	public function markVisited(AbstractSmrPlayer $player) {
168
		if ($this->hasPort()) {
169
			$this->getPort()->addCachePort($player->getAccountID());
170
		}
171
172
		//now delete the entry from visited
173
		if (!$this->isVisited($player)) {
174
			$this->db->query('DELETE FROM player_visited_sector WHERE ' . $this->SQL . '
175
								 AND account_id = ' . $this->db->escapeNumber($player->getAccountID()) . ' LIMIT 1');
176
		}
177
		$this->visited[$player->getAccountID()] = true;
178
	}
179
180
	public function hasWeaponShop() {
181
		foreach ($this->getLocations() as $location) {
182
			if ($location->isWeaponSold()) {
183
				return true;
184
			}
185
		}
186
		return false;
187
	}
188
189
	public function hasHQ() {
190
		foreach ($this->getLocations() as $location) {
191
			if ($location->isHQ()) {
192
				return true;
193
			}
194
		}
195
		return false;
196
	}
197
198
	public function hasUG() {
199
		foreach ($this->getLocations() as $location) {
200
			if ($location->isUG()) {
201
				return true;
202
			}
203
		}
204
		return false;
205
	}
206
207
	public function hasShipShop() {
208
		foreach ($this->getLocations() as $location) {
209
			if ($location->isShipSold()) {
210
				return true;
211
			}
212
		}
213
		return false;
214
	}
215
216
	public function offersFederalProtection() {
217
		foreach ($this->getLocations() as $location) {
218
			if ($location->isFed()) {
219
				return true;
220
			}
221
		}
222
		return false;
223
	}
224
225
	public function getFedRaceIDs() {
226
		$raceIDs = array();
227
		foreach ($this->getLocations() as $location) {
228
			if ($location->isFed()) {
229
				$raceIDs[$location->getRaceID()] = $location->getRaceID();
230
			}
231
		}
232
		return $raceIDs;
233
	}
234
235
	public function hasBar() {
236
		foreach ($this->getLocations() as $location) {
237
			if ($location->isBar()) {
238
				return true;
239
			}
240
		}
241
		return false;
242
	}
243
244
	public function hasHardwareShop() {
245
		foreach ($this->getLocations() as $location) {
246
			if ($location->isHardwareSold()) {
247
				return true;
248
			}
249
		}
250
		return false;
251
	}
252
253
	public function hasBank() {
254
		foreach ($this->getLocations() as $location) {
255
			if ($location->isBank()) {
256
				return true;
257
			}
258
		}
259
		return false;
260
	}
261
262
	public function enteringSector(AbstractSmrPlayer $player, $movementType) {
263
		// send scout messages to user
264
		$message = 'Your forces have spotted ' . $player->getBBLink() . ' ';
265
		switch ($movementType) {
266
			case MOVEMENT_JUMP:
267
				$message .= 'jumping into';
268
			break;
269
			case MOVEMENT_WARP:
270
				$message .= 'warping into';
271
			break;
272
			case MOVEMENT_WALK:
273
			default:
274
				$message .= 'entering';
275
		}
276
		$message .= ' sector ' . Globals::getSectorBBLink($this->getSectorID());
277
278
		$forces = $this->getForces();
279
		foreach ($forces as $force) {
280
			$force->ping($message, $player);
281
		}
282
	}
283
284
	public function leavingSector(AbstractSmrPlayer $player, $movementType) {
285
		// send scout messages to user
286
		$message = 'Your forces have spotted ' . $player->getBBLink() . ' ';
287
		switch ($movementType) {
288
			case MOVEMENT_JUMP:
289
				$message .= 'jumping from';
290
			break;
291
			case MOVEMENT_WARP:
292
				$message .= 'warping from';
293
			break;
294
			case MOVEMENT_WALK:
295
			default:
296
				$message .= 'leaving';
297
		}
298
		$message .= ' sector ' . Globals::getSectorBBLink($this->getSectorID());
299
300
		// iterate over all scout drones in sector
301
		foreach ($this->getForces() as $force) {
302
			$force->ping($message, $player);
303
		}
304
		$this->db->query('UPDATE sector_has_forces SET refresher = 0 WHERE ' . $this->SQL . '
305
								AND refresher = ' . $this->db->escapeNumber($player->getAccountID()));
306
	}
307
308
	public function diedHere(AbstractSmrPlayer $player) {
309
		// iterate over all scout drones in sector
310
		foreach ($this->getForces() as $force) {
311
			// send scout messages to user
312
			$message = 'Your forces have spotted that ' . $player->getBBLink() . ' has been <span class="red">DESTROYED</span> in sector ' . Globals::getSectorBBLink($this->sectorID);
313
			$force->ping($message, $player);
314
		}
315
	}
316
317
	public function getSQL() {
318
		return $this->SQL;
319
	}
320
321
	public function getGameID() {
322
		return $this->gameID;
323
	}
324
325
	public function getSectorID() {
326
		return $this->sectorID;
327
	}
328
329
	public function getGalaxyID() {
330
		return $this->galaxyID;
331
	}
332
333
	public function setGalaxyID($galaxyID) {
334
		if ($this->galaxyID == $galaxyID) {
335
			return;
336
		}
337
		$this->galaxyID = $galaxyID;
338
		$this->hasChanged = true;
339
	}
340
341
	public function getNumberOfLinks() {
342
		$num = 0;
343
		if (!is_array($this->getLinks())) {
344
			return $num;
345
		}
346
		foreach ($this->getLinks() as $link) {
347
			if ($link !== 0) {
348
				$num++;
349
			}
350
		}
351
		return $num;
352
	}
353
354
	public function getNumberOfConnections() {
355
		$links = $this->getNumberOfLinks();
356
		if ($this->hasWarp()) {
357
			$links++;
358
		}
359
		return $links;
360
	}
361
362
	public function getGalaxy() {
363
		return SmrGalaxy::getGalaxy($this->getGameID(), $this->getGalaxyID());
364
	}
365
366
	public function getNeighbourID($dir) {
367
		if ($this->hasLink($dir)) {
368
			return $this->getLink($dir);
369
		}
370
		$galaxy = $this->getGalaxy();
371
		$neighbour = $this->getSectorID();
372
		switch ($dir) {
373
			case 'Up':
374
				$neighbour -= $galaxy->getWidth();
375
				if ($neighbour < $galaxy->getStartSector()) {
376
					$neighbour += $galaxy->getSize();
377
				}
378
			break;
379
			case 'Down':
380
				$neighbour += $galaxy->getWidth();
381
				if ($neighbour > $galaxy->getEndSector()) {
382
					$neighbour -= $galaxy->getSize();
383
				}
384
			break;
385
			case 'Left':
386
				$neighbour -= 1;
387
				if ((1 + $neighbour - $galaxy->getStartSector()) % $galaxy->getWidth() == 0) {
388
					$neighbour += $galaxy->getWidth();
389
				}
390
			break;
391
			case 'Right':
392
				$neighbour += 1;
393
				if (($neighbour - $galaxy->getStartSector()) % $galaxy->getWidth() == 0) {
394
					$neighbour -= $galaxy->getWidth();
395
				}
396
			break;
397
			default:
398
				throw new Exception($dir . ': is not a valid direction');
399
		}
400
		return $neighbour;
401
	}
402
403
	public function getSectorDirection($sectorID) {
404
		if ($sectorID == $this->getSectorID()) {
405
			return 'Current';
406
		}
407
		$dir = array_search($sectorID, $this->getLinks());
408
		if ($dir !== false) {
409
			return $dir;
410
		}
411
		if ($sectorID == $this->getWarp()) {
412
			return 'Warp';
413
		}
414
		return 'None';
415
	}
416
417
	public function getNeighbourSector($dir) {
418
		return SmrSector::getSector($this->getGameID(), $this->getNeighbourID($dir));
419
	}
420
421
	public function getLinks() {
422
		return $this->links;
423
	}
424
425
	public function isLinked($sectorID) {
426
		return in_array($sectorID, $this->links) || $sectorID == $this->getWarp();
427
	}
428
429
	public function getLink($name) {
430
		return $this->links[$name] ?? 0;
431
	}
432
433
	public function hasLink($name) {
434
		return $this->getLink($name) != 0;
435
	}
436
437
	public function getLinkSector($name) {
438
		if ($this->hasLink($name)) {
439
			return SmrSector::getSector($this->getGameID(), $this->getLink($name));
440
		}
441
		return false;
442
	}
443
444
	/**
445
	 * Cannot be used for Warps
446
	 */
447
	public function setLink($name, $linkID) {
448
		if ($this->getLink($name) == $linkID) {
449
			return;
450
		}
451
		if ($linkID == 0) {
452
			unset($this->links[$name]);
453
		} else {
454
			$this->links[$name] = $linkID;
455
		}
456
		$this->hasChanged = true;
457
	}
458
459
	/**
460
	 * Cannot be used for Warps
461
	 */
462
	public function setLinkSector($dir, SmrSector $linkSector) {
463
		if ($this->getLink($dir) == $linkSector->getSectorID() || $linkSector->equals($this)) {
464
			return;
465
		}
466
		$this->setLink($dir, $linkSector->getSectorID());
467
		$linkSector->setLink(self::oppositeDir($dir), $this->getSectorID());
468
		$this->hasChanged = true;
469
	}
470
	/**
471
	 * Cannot be used for Warps
472
	 */
473
	public function enableLink($dir) {
474
		$this->setLinkSector($dir, $this->getNeighbourSector($dir));
475
	}
476
	/**
477
	 * Cannot be used for Warps
478
	 */
479
	public function disableLink($dir) {
480
		$this->setLink($dir, 0);
481
		$this->getNeighbourSector($dir)->setLink(self::oppositeDir($dir), 0);
482
	}
483
	/**
484
	 * Cannot be used for Warps
485
	 */
486
	public function toggleLink($dir) {
487
		if ($this->hasLink($dir)) {
488
			$this->disableLink($dir);
489
		} else {
490
			$this->enableLink($dir);
491
		}
492
	}
493
494
	protected static function oppositeDir($dir) {
495
		switch ($dir) {
496
			case 'Up': return 'Down';
497
			case 'Down': return 'Up';
498
			case 'Left': return 'Right';
499
			case 'Right': return 'Left';
500
			case 'Warp': return 'Warp';
501
		}
502
	}
503
504
	public function getLinkUp() {
505
		return $this->getLink('Up');
506
	}
507
508
	public function setLinkUp($linkID) {
509
		$this->setLink('Up', $linkID);
510
	}
511
512
	public function hasLinkUp() {
513
		return $this->hasLink('Up');
514
	}
515
516
	public function getLinkDown() {
517
		return $this->getLink('Down');
518
	}
519
520
	public function setLinkDown($linkID) {
521
		$this->setLink('Down', $linkID);
522
	}
523
524
	public function hasLinkDown() {
525
		return $this->hasLink('Down');
526
	}
527
528
	public function getLinkLeft() {
529
		return $this->getLink('Left');
530
	}
531
532
	public function hasLinkLeft() {
533
		return $this->hasLink('Left');
534
	}
535
536
	public function setLinkLeft($linkID) {
537
		$this->setLink('Left', $linkID);
538
	}
539
540
	public function getLinkRight() {
541
		return $this->getLink('Right');
542
	}
543
544
	public function hasLinkRight() {
545
		return $this->hasLink('Right');
546
	}
547
548
	public function setLinkRight($linkID) {
549
		$this->setLink('Right', $linkID);
550
	}
551
552
	/**
553
	 * Returns the warp sector if the sector has a warp; returns 0 otherwise.
554
	 */
555
	public function getWarp() {
556
		return $this->warp;
557
	}
558
559
	public function getWarpSector() {
560
		return SmrSector::getSector($this->getGameID(), $this->getWarp());
561
	}
562
563
	public function hasWarp() {
564
		return $this->getWarp() != 0;
565
	}
566
567
	/**
568
	 * Set the warp sector for both $this and $warp to ensure
569
	 * a consistent 2-way warp.
570
	 */
571
	public function setWarp(SmrSector $warp) {
572
		if ($this->getWarp() == $warp->getSectorID() &&
573
		    $warp->getWarp() == $this->getSectorID()) {
574
			// Warps are already set correctly!
575
			return;
576
		}
577
578
		if ($this->equals($warp)) {
579
			throw new Exception('Sector must not warp to itself!');
580
		}
581
582
		// Can only have 1 warp per sector
583
		foreach ([[$warp, $this], [$this, $warp]] as $sectors) {
584
			$A = $sectors[0];
585
			$B = $sectors[1];
586
			if ($A->hasWarp() && $A->getWarp() != $B->getSectorID()) {
587
				throw new Exception('Sector ' . $A->getSectorID() . ' already has a warp (to ' . $A->getWarp() . ')!');
588
			}
589
		}
590
591
		$this->warp = $warp->getSectorID();
592
		$this->hasChanged = true;
593
594
		if ($warp->getWarp() != $this->getSectorID()) {
595
			// Set the other side if needed
596
			$warp->setWarp($this);
597
		}
598
	}
599
600
	/**
601
	 * Remove the warp sector for both sides of the warp.
602
	 */
603
	public function removeWarp() {
604
		if (!$this->hasWarp()) {
605
			return;
606
		}
607
608
		$warp = $this->getWarpSector();
609
		if ($warp->hasWarp() && $warp->getWarp() != $this->getSectorID()) {
610
			throw new Exception('Warp sectors do not match');
611
		}
612
613
		$this->warp = 0;
614
		$this->hasChanged = true;
615
616
		if ($warp->hasWarp()) {
617
			$warp->removeWarp();
618
		}
619
	}
620
621
	public function hasPort() {
622
		return $this->getPort()->exists();
623
	}
624
625
	public function getPort() {
626
		return SmrPort::getPort($this->getGameID(), $this->getSectorID());
627
	}
628
629
	public function createPort() {
630
		return SmrPort::createPort($this->getGameID(), $this->getSectorID());
631
	}
632
633
	public function removePort() {
634
		SmrPort::removePort($this->getGameID(), $this->getSectorID());
635
	}
636
637
	public function hasCachedPort(AbstractSmrPlayer $player = null) {
638
		return $this->getCachedPort($player) !== false;
639
	}
640
641
	public function getCachedPort(AbstractSmrPlayer $player = null) {
642
		if ($player == null) {
643
			$return = false;
644
			return $return;
645
		}
646
		return SmrPort::getCachedPort($this->getGameID(), $this->getSectorID(), $player->getAccountID());
647
	}
648
649
	public function hasAnyLocationsWithAction() {
650
		$locations = SmrLocation::getSectorLocations($this->getGameID(), $this->getSectorID());
651
		$hasAction = false;
652
		foreach ($locations as $location) {
653
			if ($location->hasAction()) {
654
				$hasAction = true;
655
			}
656
		}
657
		return $hasAction;
658
	}
659
660
	public function hasLocation($locationTypeID = false) {
661
		$locations = $this->getLocations();
662
		if (count($locations) == 0) {
663
			return false;
664
		}
665
		if ($locationTypeID == false) {
666
			return true;
667
		}
668
		foreach ($locations as $location) {
669
			if ($location->getTypeID() == $locationTypeID) {
670
				return true;
671
			}
672
		}
673
		return false;
674
	}
675
676
	public function getLocations() {
677
		return SmrLocation::getSectorLocations($this->getGameID(), $this->getSectorID());
678
	}
679
680
	public function addLocation(SmrLocation $location) {
681
		$this->db->query('INSERT INTO location (game_id,sector_id,location_type_id)
682
						values(' . $this->db->escapeNumber($this->getGameID()) . ',' . $this->db->escapeNumber($this->getSectorID()) . ',' . $this->db->escapeNumber($location->getTypeID()) . ')');
683
		SmrLocation::getSectorLocations($this->getGameID(), $this->getSectorID(), true);
684
	}
685
686
	public function removeAllLocations() {
687
		$this->db->query('DELETE FROM location WHERE ' . $this->SQL);
688
		SmrLocation::getSectorLocations($this->getGameID(), $this->getSectorID(), true);
689
	}
690
691
	public function hasPlanet() {
692
		return $this->getPlanet()->exists();
693
	}
694
695
	public function getPlanet() {
696
		return SmrPlanet::getPlanet($this->getGameID(), $this->getSectorID());
697
	}
698
699
	public function createPlanet($type = 1) {
700
		return SmrPlanet::createPlanet($this->getGameID(), $this->getSectorID(), $type);
701
	}
702
703
	public function removePlanet() {
704
		SmrPlanet::removePlanet($this->getGameID(), $this->getSectorID());
705
	}
706
707
	/**
708
	 * Removes ports, planets, locations, and warps from this sector.
709
	 * NOTE: This should only be used by the universe generator!
710
	 */
711
	public function removeAllFixtures() {
712
		if ($this->hasPort()) {
713
			$this->removePort();
714
		}
715
		if ($this->hasPlanet()) {
716
			$this->removePlanet();
717
		}
718
		if ($this->hasLocation()) {
719
			$this->removeAllLocations();
720
		}
721
		if ($this->hasWarp()) {
722
			$this->removeWarp();
723
		}
724
	}
725
726
	public function hasForces() {
727
		return count($this->getForces()) > 0;
728
	}
729
730
	public function hasEnemyForces(AbstractSmrPlayer $player = null) {
731
		if ($player == null || !$this->hasForces()) {
732
			return false;
733
		}
734
		foreach ($this->getForces() as $force) {
735
			if (!$player->forceNAPAlliance($force->getOwner())) {
736
				return true;
737
			}
738
		}
739
		return false;
740
	}
741
742
	public function getEnemyForces(AbstractSmrPlayer $player) {
743
		$enemyForces = array();
744
		foreach ($this->getForces() as $force) {
745
			if (!$player->forceNAPAlliance($force->getOwner())) {
746
				$enemyForces[] = $force;
747
			}
748
		}
749
		return $enemyForces;
750
	}
751
752
	/**
753
	 * Returns true if any forces in this sector belong to $player.
754
	 */
755
	public function hasPlayerForces(AbstractSmrPlayer $player) {
756
		foreach ($this->getForces() as $force) {
757
			if ($player->getAccountID() == $force->getOwnerID()) {
758
				return true;
759
			}
760
		}
761
		return false;
762
	}
763
764
	public function hasFriendlyForces(AbstractSmrPlayer $player = null) {
765
		if ($player == null || !$this->hasForces()) {
766
			return false;
767
		}
768
		foreach ($this->getForces() as $force) {
769
			if ($player->forceNAPAlliance($force->getOwner())) {
770
				return true;
771
			}
772
		}
773
		return false;
774
	}
775
776
	public function getFriendlyForces(AbstractSmrPlayer $player) {
777
		$friendlyForces = array();
778
		foreach ($this->getForces() as $force) {
779
			if ($player->forceNAPAlliance($force->getOwner())) {
780
				$friendlyForces[] = $force;
781
			}
782
		}
783
		return $friendlyForces;
784
	}
785
786
	public function getForces() {
787
		return SmrForce::getSectorForces($this->getGameID(), $this->getSectorID());
788
	}
789
790
	public function getPlayers() {
791
		return SmrPlayer::getSectorPlayers($this->getGameID(), $this->getSectorID());
792
	}
793
794
	public function hasPlayers() {
795
		return count($this->getPlayers()) > 0;
796
	}
797
798
	public function getOtherTraders(AbstractSmrPlayer $player) {
799
		$players = SmrPlayer::getSectorPlayers($this->getGameID(), $this->getSectorID()); //Do not use & because we unset something and only want that in what we return
800
		unset($players[$player->getAccountID()]);
801
		return $players;
802
	}
803
804
	public function hasOtherTraders(AbstractSmrPlayer $player) {
805
		return count($this->getOtherTraders($player)) > 0;
806
	}
807
808
	public function hasEnemyTraders(AbstractSmrPlayer $player = null) {
809
		if ($player == null || !$this->hasOtherTraders($player)) {
810
			return false;
811
		}
812
		$otherPlayers = $this->getOtherTraders($player);
813
		foreach ($otherPlayers as $otherPlayer) {
814
			if (!$player->traderNAPAlliance($otherPlayer) 
815
				&& !$otherPlayer->hasNewbieTurns()
816
				&& !$otherPlayer->hasFederalProtection()) {
817
				return true;
818
			}
819
		}
820
		return false;
821
	}
822
823
	public function hasFriendlyTraders(AbstractSmrPlayer $player = null) {
824
		if ($player == null || !$this->hasOtherTraders($player)) {
825
			return false;
826
		}
827
		$otherPlayers = $this->getOtherTraders($player);
828
		foreach ($otherPlayers as $otherPlayer) {
829
			if ($player->traderNAPAlliance($otherPlayer)) {
830
				return true;
831
			}
832
		}
833
		return false;
834
	}
835
836
	/**
837
	 * Is the $player's alliance flagship in this sector?
838
	 */
839
	public function hasAllianceFlagship(AbstractSmrPlayer $player = null) {
840
		if (is_null($player) || !$player->hasAlliance() || !$player->getAlliance()->hasFlagship()) {
841
			return false;
842
		}
843
		$flagshipID = $player->getAlliance()->getFlagshipID();
844
		foreach ($this->getPlayers() as $sectorPlayer) {
845
			if ($sectorPlayer->getAccountID() == $flagshipID) {
846
				return true;
847
			}
848
		}
849
		return false;
850
	}
851
852
	public function hasProtectedTraders(AbstractSmrPlayer $player = null) {
853
		if ($player == null || !$this->hasOtherTraders($player)) {
854
			return false;
855
		}
856
		$otherPlayers = $this->getOtherTraders($player);
857
		foreach ($otherPlayers as $otherPlayer) {
858
			if (!$player->traderNAPAlliance($otherPlayer) 
859
				&& ($otherPlayer->hasNewbieTurns() || $otherPlayer->hasFederalProtection())) {
860
				return true;
861
			}
862
		}
863
		return false;
864
	}
865
866
	public function getFightingTradersAgainstForces(AbstractSmrPlayer $attackingPlayer, $bump) {
0 ignored issues
show
Unused Code introduced by
The parameter $bump is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

866
	public function getFightingTradersAgainstForces(AbstractSmrPlayer $attackingPlayer, /** @scrutinizer ignore-unused */ $bump) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
867
		// Whether bumping or attacking, only the current player fires at forces
868
		return array($attackingPlayer);
869
	}
870
871
	public function getFightingTradersAgainstPort(AbstractSmrPlayer $attackingPlayer, SmrPort $defendingPort) {
0 ignored issues
show
Unused Code introduced by
The parameter $defendingPort is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

871
	public function getFightingTradersAgainstPort(AbstractSmrPlayer $attackingPlayer, /** @scrutinizer ignore-unused */ SmrPort $defendingPort) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
872
		$fightingPlayers = array();
873
		$alliancePlayers = SmrPlayer::getSectorPlayersByAlliances($this->getGameID(), $this->getSectorID(), array($attackingPlayer->getAllianceID()));
874
		foreach ($alliancePlayers as $accountID => $player) {
875
			if ($player->canFight()) {
876
				if ($attackingPlayer->traderAttackPortAlliance($player)) {
877
					$fightingPlayers[$accountID] = $alliancePlayers[$accountID];
878
				}
879
			}
880
		}
881
		return self::limitFightingTraders($fightingPlayers, $attackingPlayer, MAXIMUM_PORT_FLEET_SIZE);
882
	}
883
884
	public function getFightingTradersAgainstPlanet(AbstractSmrPlayer $attackingPlayer, SmrPlanet $defendingPlanet) {
885
		$fightingPlayers = array();
886
		$alliancePlayers = SmrPlayer::getSectorPlayersByAlliances($this->getGameID(), $this->getSectorID(), array($attackingPlayer->getAllianceID()));
887
		if (count($alliancePlayers) > 0) {
888
			$planetOwner = $defendingPlanet->getOwner();
889
			foreach ($alliancePlayers as $accountID => $player) {
890
				if ($player->canFight()) {
891
					if ($attackingPlayer->traderAttackPlanetAlliance($player) && !$planetOwner->planetNAPAlliance($player)) {
892
						$fightingPlayers[$accountID] = $alliancePlayers[$accountID];
893
					}
894
				}
895
			}
896
		}
897
		return self::limitFightingTraders($fightingPlayers, $attackingPlayer, min($defendingPlanet->getMaxAttackers(), MAXIMUM_PLANET_FLEET_SIZE));
898
	}
899
900
	public function getFightingTraders(AbstractSmrPlayer $attackingPlayer, AbstractSmrPlayer $defendingPlayer, $checkForCloak = false) {
901
		if ($attackingPlayer->traderNAPAlliance($defendingPlayer)) {
902
			throw new Exception('These traders are NAPed.');
903
		}
904
		$fightingPlayers = array('Attackers' => array(), 'Defenders' => array());
905
		$alliancePlayers = SmrPlayer::getSectorPlayersByAlliances($this->getGameID(), $this->getSectorID(), array($attackingPlayer->getAllianceID(), $defendingPlayer->getAllianceID()));
906
		$attackers = array();
907
		$defenders = array();
908
		foreach ($alliancePlayers as $accountID => $player) {
909
			if ($player->canFight()) {
910
				if ($attackingPlayer->traderAttackTraderAlliance($player) && !$defendingPlayer->traderDefendTraderAlliance($player) && !$defendingPlayer->traderNAPAlliance($player)) {
911
					$attackers[] = $alliancePlayers[$accountID];
912
				} elseif ($defendingPlayer->traderDefendTraderAlliance($player) && !$attackingPlayer->traderAttackTraderAlliance($player) && !$attackingPlayer->traderNAPAlliance($player) && ($checkForCloak === false || $attackingPlayer->canSee($player))) {
913
					$defenders[] = $alliancePlayers[$accountID];
914
				}
915
			}
916
		}
917
		$attackers = self::limitFightingTraders($attackers, $attackingPlayer, MAXIMUM_PVP_FLEET_SIZE);
918
		shuffle($attackers);
919
		foreach ($attackers as $attacker) {
920
			$fightingPlayers['Attackers'][$attacker->getAccountID()] = $attacker;
921
		}
922
		$defenders = self::limitFightingTraders($defenders, $defendingPlayer, MAXIMUM_PVP_FLEET_SIZE);
923
		shuffle($defenders);
924
		foreach ($defenders as $defender) {
925
			$fightingPlayers['Defenders'][$defender->getAccountID()] = $defender;
926
		}
927
		return $fightingPlayers;
928
	}
929
930
	public static function limitFightingTraders(array &$fightingPlayers, AbstractSmrPlayer $keepPlayer, $maximumFleetSize) {
931
		// Cap fleets to the required size
932
		$fleet_size = count($fightingPlayers);
933
		if ($fleet_size > $maximumFleetSize) {
934
			// We use random key to stop the same people being capped all the time
935
			for ($j = 0; $j < $fleet_size - $maximumFleetSize; ++$j) {
936
				do {
937
					$key = array_rand($fightingPlayers);
938
				} while ($keepPlayer->equals($fightingPlayers[$key]));
939
				unset($fightingPlayers[$key]);
940
			}
941
		}
942
		return $fightingPlayers;
943
	}
944
945
	public function getPotentialFightingTraders(AbstractSmrPlayer $attackingPlayer) {
946
		$fightingPlayers = array();
947
		$alliancePlayers = SmrPlayer::getSectorPlayersByAlliances($this->getGameID(), $this->getSectorID(), array($attackingPlayer->getAllianceID()));
948
		foreach ($alliancePlayers as $accountID => $player) {
949
			if ($player->canFight()) {
950
				if ($attackingPlayer->traderAttackTraderAlliance($player)) {
951
					$fightingPlayers['Attackers'][$accountID] = $player;
952
				}
953
			}
954
		}
955
		return $fightingPlayers;
956
	}
957
958
	public function getBattles() {
959
		return $this->battles;
960
	}
961
962
	public function setBattles($amount) {
963
		if ($this->battles == $amount) {
964
			return;
965
		}
966
		$this->battles = $amount;
967
		$this->hasChanged = true;
968
	}
969
970
	public function decreaseBattles($amount) {
971
		$this->setBattles($this->battles - $amount);
972
	}
973
974
	public function increaseBattles($amount) {
975
		$this->setBattles($this->battles + $amount);
976
	}
977
978
	public function equals(SmrSector $otherSector) {
979
		return $otherSector->getSectorID() == $this->getSectorID() && $otherSector->getGameID() == $this->getGameID();
980
	}
981
982
	public function isLinkedSector(SmrSector $otherSector) {
983
		return $otherSector->getGameID() == $this->getGameID() && $this->isLinked($otherSector->getSectorID());
984
	}
985
986
	public function isVisited(AbstractSmrPlayer $player = null) {
987
		if ($player === null) {
988
			return true;
989
		}
990
		if (!isset($this->visited[$player->getAccountID()])) {
991
			$this->db->query('SELECT sector_id FROM player_visited_sector WHERE ' . $this->SQL . ' AND account_id=' . $this->db->escapeNumber($player->getAccountID()) . ' LIMIT 1');
992
			$this->visited[$player->getAccountID()] = !$this->db->nextRecord();
993
		}
994
		return $this->visited[$player->getAccountID()];
995
	}
996
997
	public function getLocalMapMoveHREF() {
998
		return Globals::getSectorMoveHREF($this->getSectorID(), 'map_local.php');
999
	}
1000
1001
	public function getCurrentSectorMoveHREF() {
1002
		return Globals::getCurrentSectorMoveHREF($this->getSectorID());
1003
	}
1004
1005
	public function getGalaxyMapHREF() {
1006
		return '?sector_id=' . $this->getSectorID();
1007
	}
1008
1009
	public function getScanSectorHREF() {
1010
		return Globals::getSectorScanHREF($this->getSectorID());
1011
	}
1012
1013
	public function hasX(/*Object*/ $x, AbstractSmrPlayer $player = null) {
1014
		if ($x instanceof SmrSector) {
1015
			return $this->equals($x);
1016
		}
1017
		if ($x == 'Port') {
1018
			return $this->hasPort();
1019
		}
1020
		if ($x == 'Location') {
1021
			return $this->hasLocation();
1022
		}
1023
		if ($x instanceof SmrLocation) {
1024
			return $this->hasLocation($x->getTypeID());
1025
		}
1026
		if ($x instanceof SmrGalaxy) {
1027
			return $x->contains($this);
1028
		}
1029
1030
		if (is_array($x) && $x['Type'] == 'Good') { //Check if it's possible for port to have X, hacky but nice performance gains
1031
			if ($this->hasPort() && $this->getPort()->hasX($x)) {
1032
				return true;
1033
			}
1034
		}
1035
1036
		//Check if it's possible for location to have X, hacky but nice performance gains
1037
		if ($x instanceof SmrWeaponType || (is_array($x) && ($x['Type'] == 'Ship' || $x['Type'] == 'Hardware')) || (is_string($x) && ($x == 'Bank' || $x == 'Bar' || $x == 'Fed' || $x == 'SafeFed' || $x == 'HQ' || $x == 'UG' || $x == 'Hardware' || $x == 'Ship' || $x == 'Weapon'))) {
1038
			foreach ($this->getLocations() as $loc) {
1039
				if ($loc->hasX($x, $player)) {
1040
					return true;
1041
				}
1042
			}
1043
		}
1044
		return false;
1045
	}
1046
}
1047