Completed
Push — work-fleets ( 3f92e6...b16c77 )
by SuperNova.WS
07:09
created

Fleet::shipsLand()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 42
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 6
eloc 14
nc 5
nop 1
dl 0
loc 42
rs 8.439
c 4
b 0
f 0
ccs 0
cts 19
cp 0
crap 42
1
<?php
2
use DBStatic\DBStaticFleetACS;
3
use DBStatic\DBStaticNote;
4
use DBStatic\DBStaticPlanet;
5
use DBStatic\DBStaticUnit;
6
use DBStatic\DBStaticUser;
7
use Exception\ExceptionFleetInvalid;
8
use Exception\ExceptionPropertyAccess;
9
use Vector\Vector;
10
11
/**
12
 * Class Fleet
13
 *
14
 * @property int dbId
15
 * @property int playerOwnerId
16
 * @property int group_id
17
 * @property int mission_type
18
 * @property int target_owner_id
19
 * @property int is_returning
20
 *
21
 * @property int time_launch
22
 * @property int time_arrive_to_target
23
 * @property int time_mission_job_complete
24
 * @property int time_return_to_source
25
 *
26
 * @property int fleet_start_planet_id
27
 * @property int fleet_start_galaxy
28
 * @property int fleet_start_system
29
 * @property int fleet_start_planet
30
 * @property int fleet_start_type
31
 *
32
 * @property int fleet_end_planet_id
33
 * @property int fleet_end_galaxy
34
 * @property int fleet_end_system
35
 * @property int fleet_end_planet
36
 * @property int fleet_end_type
37
 *
38
 */
39
class Fleet extends UnitContainer {
40
41
  // DBRow inheritance *************************************************************************************************
42
43
  /**
44
   * Table name in DB
45
   *
46
   * @var string
47
   */
48
  protected static $_table = 'fleets';
49
  /**
50
   * Name of ID field in DB
51
   *
52
   * @var string
53
   */
54
  protected static $_dbIdFieldName = 'fleet_id';
55
  /**
56
   * DB_ROW to Class translation scheme
57
   *
58
   * @var array
59
   */
60
  protected $_properties = array(
61
    'dbId'          => array(
62
      P_DB_FIELD => 'fleet_id',
63
    ),
64
    'playerOwnerId' => array(
65
      P_METHOD_EXTRACT => 'ownerExtract',
66
      P_METHOD_INJECT  => 'ownerInject',
67
//      P_DB_FIELD => 'fleet_owner',
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
68
    ),
69
    'mission_type'  => array(
70
      P_DB_FIELD   => 'fleet_mission',
71
      P_FUNC_INPUT => 'intval',
72
    ),
73
74
    'target_owner_id' => array(
75
      P_DB_FIELD => 'fleet_target_owner',
76
    ),
77
    'group_id'        => array(
78
      P_DB_FIELD => 'fleet_group',
79
    ),
80
    'is_returning'    => array(
81
      P_DB_FIELD   => 'fleet_mess',
82
      P_FUNC_INPUT => 'intval',
83
    ),
84
85
    'shipCount' => array(
86
      P_DB_FIELD  => 'fleet_amount',
87
// TODO - CHECK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
0 ignored issues
show
Unused Code Comprehensibility introduced by
80% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
88
//      P_FUNC_OUTPUT => 'get_ship_count',
89
//      P_DB_FIELDS_LINKED => array(
90
//        'fleet_amount',
91
//      ),
92
      P_READ_ONLY => true,
93
    ),
94
95
    'time_launch' => array(
96
      P_DB_FIELD => 'start_time',
97
    ),
98
99
    'time_arrive_to_target'     => array(
100
      P_DB_FIELD => 'fleet_start_time',
101
    ),
102
    'time_mission_job_complete' => array(
103
      P_DB_FIELD => 'fleet_end_stay',
104
    ),
105
    'time_return_to_source'     => array(
106
      P_DB_FIELD => 'fleet_end_time',
107
    ),
108
109
    'fleet_start_planet_id' => array(
110
      P_DB_FIELD   => 'fleet_start_planet_id',
111
      P_FUNC_INPUT => 'nullIfEmpty',
112
    ),
113
114
    'fleet_start_galaxy' => array(
115
      P_DB_FIELD => 'fleet_start_galaxy',
116
    ),
117
    'fleet_start_system' => array(
118
      P_DB_FIELD => 'fleet_start_system',
119
    ),
120
    'fleet_start_planet' => array(
121
      P_DB_FIELD => 'fleet_start_planet',
122
    ),
123
    'fleet_start_type'   => array(
124
      P_DB_FIELD => 'fleet_start_type',
125
    ),
126
127
    'fleet_end_planet_id' => array(
128
      P_DB_FIELD   => 'fleet_end_planet_id',
129
      P_FUNC_INPUT => 'nullIfEmpty',
130
    ),
131
    'fleet_end_galaxy'    => array(
132
      P_DB_FIELD => 'fleet_end_galaxy',
133
    ),
134
    'fleet_end_system'    => array(
135
      P_DB_FIELD => 'fleet_end_system',
136
    ),
137
    'fleet_end_planet'    => array(
138
      P_DB_FIELD => 'fleet_end_planet',
139
    ),
140
    'fleet_end_type'      => array(
141
      P_DB_FIELD => 'fleet_end_type',
142
    ),
143
144
    'resource_list' => array(
145
      P_METHOD_EXTRACT   => 'resourcesExtract',
146
      P_METHOD_INJECT    => 'resourcesInject',
147
      P_DB_FIELDS_LINKED => array(
148
        'fleet_resource_metal',
149
        'fleet_resource_crystal',
150
        'fleet_resource_deuterium',
151
      ),
152
    ),
153
  );
154
155
156
  // UnitContainer inheritance *****************************************************************************************
157
  /**
158
   * Type of this location
159
   *
160
   * @var int $locationType
161
   */
162
  protected static $locationType = LOC_FLEET;
163
164
165
  // New properties ****************************************************************************************************
166
  public static $snGroupFleet = array();
167
  public static $snGroupFleetAndMissiles = array();
168
  public static $snGroupRecyclers = array();
169
170
  /**
171
   * `fleet_owner`
172
   *
173
   * @var int
174
   */
175
  protected $_playerOwnerId = 0;
176
  /**
177
   * `fleet_group`
178
   *
179
   * @var int
180
   */
181
  protected $_group_id = 0;
182
  public $acs = array();
183
184
  /**
185
   * `fleet_mission`
186
   *
187
   * @var int
188
   */
189
  protected $_mission_type = 0;
190
191
  /**
192
   * `fleet_target_owner`
193
   *
194
   * @var int
195
   */
196
  protected $_target_owner_id = null;
197
198
  /**
199
   * @var array
200
   */
201
  public $resource_list = array(
202
    RES_METAL     => 0,
203
    RES_CRYSTAL   => 0,
204
    RES_DEUTERIUM => 0,
205
  );
206
207
208
  /**
209
   * `fleet__mess` - Флаг возвращающегося флота
210
   *
211
   * @var int
212
   */
213
  protected $_is_returning = 0;
214
  /**
215
   * `start_time` - Время отправления - таймштамп взлёта флота из точки отправления
216
   *
217
   * @var int $_time_launch
218
   */
219
  protected $_time_launch = 0; // `start_time` = SN_TIME_NOW
220
  /**
221
   * `fleet_start_time` - Время прибытия в точку миссии/время начала выполнения миссии
222
   *
223
   * @var int $_time_arrive_to_target
224
   */
225
  protected $_time_arrive_to_target = 0; // `fleet_start_time` = SN_TIME_NOW + $time_travel
226
  /**
227
   * `fleet_end_stay` - Время окончания миссии в точке назначения
228
   *
229
   * @var int $_time_mission_job_complete
230
   */
231
  protected $_time_mission_job_complete = 0; // `fleet_end_stay`
232
  /**
233
   * `fleet_end_time` - Время возвращения флота после окончания миссии
234
   *
235
   * @var int $_time_return_to_source
236
   */
237
  protected $_time_return_to_source = 0; // `fleet_end_time`
238
239
240
  protected $_fleet_start_planet_id = null;
241
  protected $_fleet_start_galaxy = 0;
242
  protected $_fleet_start_system = 0;
243
  protected $_fleet_start_planet = 0;
244
  protected $_fleet_start_type = PT_ALL;
245
246
  protected $_fleet_end_planet_id = null;
247
  protected $_fleet_end_galaxy = 0;
248
  protected $_fleet_end_system = 0;
249
  protected $_fleet_end_planet = 0;
250
  protected $_fleet_end_type = PT_ALL;
251
252
  // Missile properties
253
  public $missile_target = 0;
254
255
  // Fleet event properties
256
  public $fleet_start_name = '';
257
  public $fleet_end_name = '';
258
  public $ov_label = '';
259
  public $ov_this_planet = '';
260
  public $event_time = 0;
261
262
  protected $resource_delta = array();
263
  protected $resource_replace = array();
264
265
266
//
267
268
269
  /**
270
   * @var array $allowed_missions
271
   */
272
  public $allowed_missions = array();
273
  /**
274
   * @var array $exists_missions
275
   */
276
  public $exists_missions = array();
277
  public $allowed_planet_types = array(
278
    // PT_NONE => PT_NONE,
279
    PT_PLANET => PT_PLANET,
280
    PT_MOON   => PT_MOON,
281
    PT_DEBRIS => PT_DEBRIS
282
  );
283
284
  // TODO - Move to Player
285
  public $dbOwnerRow = array();
286
  public $dbSourcePlanetRow = array();
287
288
  /**
289
   * GSPT coordinates of target
290
   *
291
   * @var Vector
292
   */
293
  public $targetVector = array();
294
  /**
295
   * Target planet row
296
   *
297
   * @var array
298
   */
299
  public $dbTargetRow = array();
300
  public $dbTargetOwnerRow = array();
301
302
  /**
303
   * Fleet speed - old in 1/10 of 100%
304
   *
305
   * @var int
306
   */
307
  public $oldSpeedInTens = 0;
308
309
  public $tempPlayerMaxFleets = 0;
310
  public $travelData = array();
311
312
  public $isRealFlight = false;
313
314
  /**
315
   * @var int $targetedUnitId
316
   */
317
  public $targetedUnitId = 0;
318
319
  /**
320
   * @var array $captain
321
   */
322
  public $captain = array();
323
  /**
324
   * @var int $captainId
325
   */
326
  public $captainId = 0;
327
328
  /**
329
   * @var FleetValidator $validator
330
   */
331
  public $validator;
332
333
334
  /**
335
   * @var UnitList $unitList
336
   */
337
  protected $unitList = null;
338
339
340
  /**
341
   * Fleet constructor.
342
   */
343
  public function __construct() {
344
    parent::__construct();
345
    $this->exists_missions = sn_get_groups('missions');
346
    $this->validator = new FleetValidator($this);
347
  }
348
349
  /**
350
   * @param array $playerRow
351
   * @param array $planetRow
352
   *
353
   * @return array
354
   */
355
  // TODO - redo to unit/unitlist renderer
356
  public function renderAvailableShips($playerRow, $planetRow) {
357
    $record_index = 0;
358
    $ship_list = array();
359
    foreach (Fleet::$snGroupFleet as $n => $unit_id) {
360
      $unit_level = mrc_get_level($playerRow, $planetRow, $unit_id, false, true);
361
      if ($unit_level <= 0) {
362
        continue;
363
      }
364
      $ship_data = get_ship_data($unit_id, $playerRow);
365
      $ship_list[$unit_id] = array(
366
        '__INDEX'          => $record_index++,
367
        'ID'               => $unit_id,
368
        'NAME'             => classLocale::$lang['tech'][$unit_id],
369
        'AMOUNT'           => $unit_level,
370
        'AMOUNT_TEXT'      => pretty_number($unit_level),
371
        'CONSUMPTION'      => $ship_data['consumption'],
372
        'CONSUMPTION_TEXT' => pretty_number($ship_data['consumption']),
373
        'SPEED'            => $ship_data['speed'],
374
        'SPEED_TEXT'       => pretty_number($ship_data['speed']),
375
        'CAPACITY'         => $ship_data['capacity'],
376
        'CAPACITY_TEXT'    => pretty_number($ship_data['capacity']),
377
      );
378
    }
379
380
    sortUnitRenderedList($ship_list, classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_SORT], classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_SORT_INVERSE]);
381
382
    return $ship_list;
383
  }
384
385
  public function isEmpty() {
386
    return !$this->resourcesGetTotal() && !$this->shipsGetTotal();
387
  }
388
389
//  public function getPlayerOwnerId() {
0 ignored issues
show
Unused Code Comprehensibility introduced by
48% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
390
//    return $this->playerOwnerId;
391
//  }
392
393
  /**
394
   * Initializes Fleet from user params and posts it to DB
395
   */
396
  public function dbInsert() {
397
    // WARNING! MISSION TIMES MUST BE SET WITH set_times() method!
398
    // TODO - more checks!
399
    if (empty($this->_time_launch)) {
400
      die('Fleet time not set!');
401
    }
402
403
    parent::dbInsert();
404
  }
405
406
407
  /* FLEET DB ACCESS =================================================================================================*/
408
409
  /**
410
   * LOCK - Lock all records which can be used with mission
411
   *
412
   * @param $mission_data
413
   *
414
   * @return array|bool|mysqli_result|null
415
   */
416
  public function dbLockFlying(&$mission_data) {
417
    // Тупо лочим всех юзеров, чьи флоты летят или улетают с координат отбытия/прибытия $fleet_row
418
    // Что бы делать это умно - надо учитывать fleet__mess во $fleet_row и в таблице fleets
419
420
    $fleet_id_safe = idval($this->_dbId);
421
422
    return classSupernova::$db->doSelect(
423
    // Блокировка самого флота
424
      "SELECT 1 FROM {{fleets}} AS f " .
425
426
      // Блокировка всех юнитов, принадлежащих этому флоту
427
      "LEFT JOIN {{unit}} as unit ON unit.unit_location_type = " . static::$locationType . " AND unit.unit_location_id = f.fleet_id " .
428
429
      // Блокировка всех прилетающих и улетающих флотов, если нужно
430
      // TODO - lock fleets by COORDINATES
431
      ($mission_data['dst_fleets'] ? "LEFT JOIN {{fleets}} AS fd ON fd.fleet_end_planet_id = f.fleet_end_planet_id OR fd.fleet_start_planet_id = f.fleet_end_planet_id " : '') .
432
      // Блокировка всех юнитов, принадлежащих прилетающим и улетающим флотам - ufd = unit_fleet_destination
433
      ($mission_data['dst_fleets'] ? "LEFT JOIN {{unit}} AS ufd ON ufd.unit_location_type = " . static::$locationType . " AND ufd.unit_location_id = fd.fleet_id " : '') .
434
435
      ($mission_data['dst_user'] || $mission_data['dst_planet'] ? "LEFT JOIN {{users}} AS ud ON ud.id = f.fleet_target_owner " : '') .
436
      // Блокировка всех юнитов, принадлежащих владельцу планеты-цели
437
      ($mission_data['dst_user'] || $mission_data['dst_planet'] ? "LEFT JOIN {{unit}} AS unit_player_dest ON unit_player_dest.unit_player_id = ud.id " : '') .
438
      // Блокировка планеты-цели
439
      ($mission_data['dst_planet'] ? "LEFT JOIN {{planets}} AS pd ON pd.id = f.fleet_end_planet_id " : '') .
440
      // Блокировка всех юнитов, принадлежащих планете-цели - НЕ НУЖНО. Уже залочили ранее, как принадлежащие игроку-цели
441
//      ($mission_data['dst_planet'] ? "LEFT JOIN {{unit}} AS upd ON upd.unit_location_type = " . LOC_PLANET . " AND upd.unit_location_id = pd.id " : '') .
442
443
444
      ($mission_data['src_user'] || $mission_data['src_planet'] ? "LEFT JOIN {{users}} AS us ON us.id = f.fleet_owner " : '') .
445
      // Блокировка всех юнитов, принадлежащих владельцу флота
446
      ($mission_data['src_user'] || $mission_data['src_planet'] ? "LEFT JOIN {{unit}} AS unit_player_src ON unit_player_src.unit_player_id = us.id " : '') .
447
      // Блокировка планеты отправления
448
      ($mission_data['src_planet'] ? "LEFT JOIN {{planets}} AS ps ON ps.id = f.fleet_start_planet_id " : '') .
449
      // Блокировка всех юнитов, принадлежащих планете с которой юниты были отправлены - НЕ НУЖНО. Уже залочили ранее, как принадлежащие владельцу флота
450
//      ($mission_data['src_planet'] ? "LEFT JOIN {{unit}} AS ups ON ups.unit_location_type = " . LOC_PLANET . " AND ups.unit_location_id = ps.id " : '') .
451
452
      "WHERE f.fleet_id = {$fleet_id_safe} GROUP BY 1 FOR UPDATE"
453
    );
454
  }
455
456
  /**
457
   * Lock all fields that belongs to operation
458
   *
459
   * @param $dbId
460
   */
461
  // TODO = make static
462
  public function dbGetLockById($dbId) {
463
    classSupernova::$db->doSelect(
464
    // Блокировка самого флота
465
      "SELECT 1 FROM {{fleets}} AS FLEET0 " .
466
      // Lock fleet owner
467
      "LEFT JOIN {{users}} as USER0 on USER0.id = FLEET0.fleet_owner " .
468
      // Блокировка всех юнитов, принадлежащих этому флоту
469
      "LEFT JOIN {{unit}} as UNIT0 ON UNIT0.unit_location_type = " . LOC_FLEET . " AND UNIT0.unit_location_id = FLEET0.fleet_id " .
470
471
      // Без предварительной выборки неизвестно - куда летит этот флот.
472
      // Поэтому надо выбирать флоты, чьи координаты прибытия ИЛИ отбытия совпадают с координатами прибытия ИЛИ отбытия текущего флота.
473
      // Получаем матрицу 2х2 - т.е. 4 подзапроса.
474
      // При блокировке всегда нужно выбирать И лпанету, И луну - поскольку при бое на орбите луны обломки падают на орбиту планеты.
475
      // Поэтому тип планеты не указывается
476
477
      // Lock fleet heading to destination planet. Only if FLEET0.fleet_mess == 0
478
      "LEFT JOIN {{fleets}} AS FLEET1 ON
479
        FLEET1.fleet_mess = 0 AND FLEET0.fleet_mess = 0 AND
480
        FLEET1.fleet_end_galaxy = FLEET0.fleet_end_galaxy AND
481
        FLEET1.fleet_end_system = FLEET0.fleet_end_system AND
482
        FLEET1.fleet_end_planet = FLEET0.fleet_end_planet
483
      " .
484
      // Блокировка всех юнитов, принадлежащих этим флотам
485
      "LEFT JOIN {{unit}} as UNIT1 ON UNIT1.unit_location_type = " . LOC_FLEET . " AND UNIT1.unit_location_id = FLEET1.fleet_id " .
486
      // Lock fleet owner
487
      "LEFT JOIN {{users}} as USER1 on USER1.id = FLEET1.fleet_owner " .
488
489
      "LEFT JOIN {{fleets}} AS FLEET2 ON
490
        FLEET2.fleet_mess = 1   AND FLEET0.fleet_mess = 0 AND
491
        FLEET2.fleet_start_galaxy = FLEET0.fleet_end_galaxy AND
492
        FLEET2.fleet_start_system = FLEET0.fleet_end_system AND
493
        FLEET2.fleet_start_planet = FLEET0.fleet_end_planet
494
      " .
495
      // Блокировка всех юнитов, принадлежащих этим флотам
496
      "LEFT JOIN {{unit}} as UNIT2 ON
497
        UNIT2.unit_location_type = " . LOC_FLEET . " AND
498
        UNIT2.unit_location_id = FLEET2.fleet_id
499
      " .
500
      // Lock fleet owner
501
      "LEFT JOIN {{users}} as USER2 on
502
        USER2.id = FLEET2.fleet_owner
503
      " .
504
505
      // Lock fleet heading to source planet. Only if FLEET0.fleet_mess == 1
506
      "LEFT JOIN {{fleets}} AS FLEET3 ON
507
        FLEET3.fleet_mess = 0 AND FLEET0.fleet_mess = 1 AND
508
        FLEET3.fleet_end_galaxy = FLEET0.fleet_start_galaxy AND
509
        FLEET3.fleet_end_system = FLEET0.fleet_start_system AND
510
        FLEET3.fleet_end_planet = FLEET0.fleet_start_planet
511
      " .
512
      // Блокировка всех юнитов, принадлежащих этим флотам
513
      "LEFT JOIN {{unit}} as UNIT3 ON
514
        UNIT3.unit_location_type = " . LOC_FLEET . " AND
515
        UNIT3.unit_location_id = FLEET3.fleet_id
516
      " .
517
      // Lock fleet owner
518
      "LEFT JOIN {{users}} as USER3 on USER3.id = FLEET3.fleet_owner " .
519
520
      "LEFT JOIN {{fleets}} AS FLEET4 ON
521
        FLEET4.fleet_mess = 1   AND FLEET0.fleet_mess = 1 AND
522
        FLEET4.fleet_start_galaxy = FLEET0.fleet_start_galaxy AND
523
        FLEET4.fleet_start_system = FLEET0.fleet_start_system AND
524
        FLEET4.fleet_start_planet = FLEET0.fleet_start_planet
525
      " .
526
      // Блокировка всех юнитов, принадлежащих этим флотам
527
      "LEFT JOIN {{unit}} as UNIT4 ON
528
        UNIT4.unit_location_type = " . LOC_FLEET . " AND
529
        UNIT4.unit_location_id = FLEET4.fleet_id
530
      " .
531
      // Lock fleet owner
532
      "LEFT JOIN {{users}} as USER4 on
533
        USER4.id = FLEET4.fleet_owner
534
      " .
535
536
537
      // Locking start planet
538
      "LEFT JOIN {{planets}} AS PLANETS5 ON
539
        FLEET0.fleet_mess = 1 AND
540
        PLANETS5.galaxy = FLEET0.fleet_start_galaxy AND
541
        PLANETS5.system = FLEET0.fleet_start_system AND
542
        PLANETS5.planet = FLEET0.fleet_start_planet
543
      " .
544
      // Lock planet owner
545
      "LEFT JOIN {{users}} as USER5 on
546
        USER5.id = PLANETS5.id_owner
547
      " .
548
      // Блокировка всех юнитов, принадлежащих этой планете
549
      "LEFT JOIN {{unit}} as UNIT5 ON
550
        UNIT5.unit_location_type = " . LOC_PLANET . " AND
551
        UNIT5.unit_location_id = PLANETS5.id
552
      " .
553
554
555
      // Locking destination planet
556
      "LEFT JOIN {{planets}} AS PLANETS6 ON
557
        FLEET0.fleet_mess = 0 AND
558
        PLANETS6.galaxy = FLEET0.fleet_end_galaxy AND
559
        PLANETS6.system = FLEET0.fleet_end_system AND
560
        PLANETS6.planet = FLEET0.fleet_end_planet
561
      " .
562
      // Lock planet owner
563
      "LEFT JOIN {{users}} as USER6 on
564
        USER6.id = PLANETS6.id_owner
565
      " .
566
      // Блокировка всех юнитов, принадлежащих этой планете
567
      "LEFT JOIN {{unit}} as UNIT6 ON
568
        UNIT6.unit_location_type = " . LOC_PLANET . " AND
569
        UNIT6.unit_location_id = PLANETS6.id
570
      " .
571
      "WHERE FLEET0.fleet_id = {$dbId} GROUP BY 1 FOR UPDATE"
572
    );
573
  }
574
575
576
  public function dbRowParse($db_row) {
577
    parent::dbRowParse($db_row); // TODO: Change the autogenerated stub
578
    $player = new Player();
579
    $player->dbLoad($db_row['fleet_owner']);
580
    $this->setLocatedAt($player);
581
  }
582
583
  /* FLEET HELPERS =====================================================================================================*/
584
  /**
585
   * Forcibly returns fleet before time outs
586
   */
587
  public function commandReturn() {
588
    $ReturnFlyingTime = ($this->_time_mission_job_complete != 0 && $this->_time_arrive_to_target < SN_TIME_NOW ? $this->_time_arrive_to_target : SN_TIME_NOW) - $this->_time_launch + SN_TIME_NOW + 1;
589
590
    // Считаем, что флот уже долетел TODO
591
    $this->time_arrive_to_target = SN_TIME_NOW;
592
    // Убираем флот из группы
593
    $this->group_id = 0;
594
    // Отменяем работу в точке назначения
595
    $this->time_mission_job_complete = 0;
596
    // TODO - правильно вычслять время возвращения - по проделанному пути, а не по старому времени возвращения
597
    $this->time_return_to_source = $ReturnFlyingTime;
598
599
    // Записываем изменения в БД
600
    $this->markReturnedAndSave();
601
602
    if ($this->_group_id) {
603
      // TODO: Make here to delete only one AKS - by adding aks_fleet_count to AKS table
604
      DBStaticFleetACS::db_fleet_aks_purge();
605
    }
606
  }
607
608
609
  /**
610
   * @return array
611
   */
612
  public function target_coordinates_without_type() {
613
    return array(
614
      'galaxy' => $this->_fleet_end_galaxy,
615
      'system' => $this->_fleet_end_system,
616
      'planet' => $this->_fleet_end_planet,
617
    );
618
  }
619
620
  /**
621
   * @return array
622
   */
623
  public function target_coordinates_typed() {
624
    return array(
625
      'galaxy' => $this->_fleet_end_galaxy,
626
      'system' => $this->_fleet_end_system,
627
      'planet' => $this->_fleet_end_planet,
628
      'type'   => $this->_fleet_end_type,
629
    );
630
  }
631
632
  /**
633
   * @return array
634
   */
635
  public function launch_coordinates_typed() {
636
    return array(
637
      'galaxy' => $this->_fleet_start_galaxy,
638
      'system' => $this->_fleet_start_system,
639
      'planet' => $this->_fleet_start_planet,
640
      'type'   => $this->_fleet_start_type,
641
    );
642
  }
643
644
  public function isReturning() {
645
    return FLEET_FLAG_RETURNING == $this->_is_returning;
646
  }
647
648
  /**
649
   * Sets object fields for fleet return
650
   */
651
  public function markReturnedAndSave() {
652
    // TODO - Проверка - а не возвращается ли уже флот?
653
    $this->is_returning = FLEET_FLAG_RETURNING;
654
    $this->dbSave();
655
  }
656
657
  /**
658
   * Parses extended unit_array which can include not only ships but resources, captains etc
659
   *
660
   * @param $unit_array
661
   *
662
   * @throws Exception
663
   */
664
  // TODO - separate shipList and unitList
665
  public function unitsSetFromArray($unit_array) {
666
    if (empty($unit_array) || !is_array($unit_array)) {
667
      return;
668
    }
669
    foreach ($unit_array as $unit_id => $unit_count) {
670
      $unit_count = floatval($unit_count);
671
      if (!$unit_count) {
672
        continue;
673
      }
674
675
      if ($this->isShip($unit_id) || $this->isMissile($unit_id)) {
676
        $this->unitList->unitSetCount($unit_id, $unit_count);
677
      } elseif ($this->isResource($unit_id)) {
678
        $this->resource_list[$unit_id] = $unit_count;
679
      } else {
680
        throw new Exception('Trying to pass to fleet non-resource and non-ship ' . var_export($unit_array, true), FLIGHT_SHIPS_UNIT_WRONG);
681
      }
682
    }
683
  }
684
685
686
  /**
687
   * Sets fleet timers based on flight duration, time on mission (HOLD/EXPLORE) and fleet departure time.
688
   *
689
   * @param int $time_to_travel - flight duration in seconds
690
   * @param int $time_on_mission - time on mission in seconds
691
   * @param int $flight_departure - fleet departure from source planet timestamp. Allows to send fleet in future or in past
692
   */
693
  public function set_times($time_to_travel, $time_on_mission = 0, $flight_departure = SN_TIME_NOW) {
694
    $this->_time_launch = $flight_departure;
695
696
    $this->_time_arrive_to_target = $this->_time_launch + $time_to_travel;
697
    $this->_time_mission_job_complete = $time_on_mission ? $this->_time_arrive_to_target + $time_on_mission : 0;
698
    $this->_time_return_to_source = ($this->_time_mission_job_complete ? $this->_time_mission_job_complete : $this->_time_arrive_to_target) + $time_to_travel;
699
  }
700
701
702
  public function parse_missile_db_row($missile_db_row) {
703
//    $this->_reset();
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
704
705
    if (empty($missile_db_row) || !is_array($missile_db_row)) {
706
      return;
707
    }
708
709
//      $planet_start = db_planet_by_vector($irak_original, FLEET_START_PREFIX, false, 'name');
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
710
//      $irak_original['fleet_start_name'] = $planet_start['name'];
711
    $this->missile_target = $missile_db_row['primaer'];
712
713
    $this->_dbId = -$missile_db_row['id'];
714
    $this->_playerOwnerId = $missile_db_row['fleet_owner'];
715
    $this->_mission_type = MT_MISSILE;
716
717
    $this->_target_owner_id = $missile_db_row['fleet_target_owner'];
718
719
    $this->_group_id = 0;
720
    $this->_is_returning = 0;
721
722
    $this->_time_launch = 0; // $irak['start_time'];
0 ignored issues
show
Unused Code Comprehensibility introduced by
84% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
723
    $this->_time_arrive_to_target = 0; // $irak['fleet_start_time'];
0 ignored issues
show
Unused Code Comprehensibility introduced by
84% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
724
    $this->_time_mission_job_complete = 0; // $irak['fleet_end_stay'];
0 ignored issues
show
Unused Code Comprehensibility introduced by
84% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
725
    $this->_time_return_to_source = $missile_db_row['fleet_end_time'];
726
727
    $this->_fleet_start_planet_id = !empty($missile_db_row['fleet_start_planet_id']) ? $missile_db_row['fleet_start_planet_id'] : null;
728
    $this->_fleet_start_galaxy = $missile_db_row['fleet_start_galaxy'];
729
    $this->_fleet_start_system = $missile_db_row['fleet_start_system'];
730
    $this->_fleet_start_planet = $missile_db_row['fleet_start_planet'];
731
    $this->_fleet_start_type = $missile_db_row['fleet_start_type'];
732
733
    $this->_fleet_end_planet_id = !empty($missile_db_row['fleet_end_planet_id']) ? $missile_db_row['fleet_end_planet_id'] : null;
734
    $this->_fleet_end_galaxy = $missile_db_row['fleet_end_galaxy'];
735
    $this->_fleet_end_system = $missile_db_row['fleet_end_system'];
736
    $this->_fleet_end_planet = $missile_db_row['fleet_end_planet'];
737
    $this->_fleet_end_type = $missile_db_row['fleet_end_type'];
738
739
    $this->unitList->unitSetCount(UNIT_DEF_MISSILE_INTERPLANET, $missile_db_row['fleet_amount']);
740
  }
741
742
743
  /**
744
   * @param $from
745
   */
746
  public function set_start_planet($from) {
747
    $this->fleet_start_planet_id = intval($from['id']) ? $from['id'] : null;
748
    $this->fleet_start_galaxy = $from['galaxy'];
749
    $this->fleet_start_system = $from['system'];
750
    $this->fleet_start_planet = $from['planet'];
751
    $this->fleet_start_type = $from['planet_type'];
752
  }
753
754
  /**
755
   * @param $to
756
   */
757
  public function set_end_planet($to) {
758
    $this->target_owner_id = intval($to['id_owner']) ? $to['id_owner'] : 0;
759
    $this->fleet_end_planet_id = intval($to['id']) ? $to['id'] : null;
760
    $this->fleet_end_galaxy = $to['galaxy'];
761
    $this->fleet_end_system = $to['system'];
762
    $this->fleet_end_planet = $to['planet'];
763
    $this->fleet_end_type = $to['planet_type'];
764
  }
765
766
  /**
767
   * @param Vector $to
768
   */
769
  public function setTargetFromVectorObject($to) {
770
    $this->_fleet_end_galaxy = $to->galaxy;
771
    $this->_fleet_end_system = $to->system;
772
    $this->_fleet_end_planet = $to->planet;
773
    $this->_fleet_end_type = $to->type;
774
  }
775
776
  /**
777
   * @param array $db_row
778
   */
779
  protected function ownerExtract(array &$db_row) {
780
    $player = new Player();
781
    $player->dbLoad($db_row['fleet_owner']);
782
    $this->setLocatedAt($player);
783
  }
784
785
  /**
786
   * @param array $db_row
787
   */
788
  protected function ownerInject(array &$db_row) {
789
    $db_row['fleet_owner'] = $this->getPlayerOwnerId();
790
  }
791
792
793
794
795
  // UnitList/Ships access ***************************************************************************************************
796
797
  // TODO - перекрывать пожже - для миссайл-флотов и дефенс-флотов
798
  protected function isShip($unit_id) {
799
    return UnitShip::is_in_group($unit_id);
800
  }
801
802
  protected function isMissile($unit_id) {
803
    return isInGroup(GROUP_STR_MISSILES, $unit_id);
804
  }
805
806
  /**
807
   * Set unit count of $unit_id to $unit_count
808
   * If there is no $unit_id - it will be created and saved to DB on dbSave
809
   *
810
   * @param int $unit_id
811
   * @param int $unit_count
812
   */
813
  public function shipSetCount($unit_id, $unit_count = 0) {
814
    pdump(__CLASS__ . '->' . __FUNCTION__);
815
    $this->shipAdjustCount($unit_id, $unit_count, true);
816
  }
817
818
  /**
819
   * Adjust unit count of $unit_id by $unit_count - or just replace value
820
   * If there is no $unit_id - it will be created and saved to DB on dbSave
821
   *
822
   * @param int  $unit_id
823
   * @param int  $unit_count
824
   * @param bool $replace_value
825
   */
826
  public function shipAdjustCount($unit_id, $unit_count = 0, $replace_value = false) {
827
    $this->unitList->unitAdjustCount($unit_id, $unit_count, $replace_value);
828
  }
829
830
  public function shipGetCount($unit_id) {
831
    return $this->unitList->unitGetCount($unit_id);
832
  }
833
834
  public function shipsCountApplyLossMultiplier($ships_lost_multiplier) {
835
    $this->unitList->unitsCountApplyLossMultiplier($ships_lost_multiplier);
836
  }
837
838
  /**
839
   * Returns fleet ships cost in metal
840
   *
841
   * @param array $shipCostInMetalPerPiece
842
   *
843
   * @return float[]
844
   */
845
  public function shipsCostInMetal($shipCostInMetalPerPiece) {
846
    return $this->unitList->unitsCostInMetal($shipCostInMetalPerPiece);
847
  }
848
849
  /**
850
   * @return UnitIterator
851
   */
852
  public function shipsIterator() {
853
    return $this->unitList->getUnitIterator();
854
  }
855
856
  public function shipsGetTotal() {
857
    return $this->unitList->unitsCount();
858
  }
859
860
  public function shipsGetCapacity() {
861
    return $this->unitList->shipsCapacity();
862
  }
863
864
  public function shipsGetHoldFree() {
865
    return max(0, $this->shipsGetCapacity() - $this->resourcesGetTotal());
866
  }
867
868
  /**
869
   * Get count of ships with $ship_id
870
   *
871
   * @param int $ship_id
872
   *
873
   * @return int
874
   */
875
  public function shipsGetTotalById($ship_id) {
876
    return $this->unitList->unitsCountById($ship_id);
877
  }
878
879
  /**
880
   * Возвращает ёмкость переработчиков во флоте
881
   *
882
   * @param array $recycler_info
883
   *
884
   * @return int
885
   *
886
   */
887
  public function shipsGetCapacityRecyclers($recycler_info) {
888
    $recyclers_incoming_capacity = 0;
889
    foreach ($this->shipsIterator() as $unitId => $unit) {
890
      if (!empty(static::$snGroupRecyclers[$unitId]) && $unit->count >= 1) {
891
        $recyclers_incoming_capacity += $unit->count * $recycler_info[$unitId]['capacity'];
892
      }
893
    }
894
895
    return $recyclers_incoming_capacity;
896
  }
897
898
  /**
899
   * @return bool
900
   */
901
  // TODO - А если не на планете????
902
  public function shipsIsEnoughOnPlanet() {
903
    return $this->unitList->shipsIsEnoughOnPlanet($this->dbOwnerRow, $this->dbSourcePlanetRow);
904
  }
905
906
  /**
907
   * @return bool
908
   */
909
  public function shipsAllPositive() {
910
    return $this->unitList->unitsPositive();
911
  }
912
913
  /**
914
   * @return bool
915
   */
916
  public function shipsAllFlying() {
917
    return $this->unitList->unitsInGroup(static::$snGroupFleetAndMissiles);
918
  }
919
920
  /**
921
   * @return bool
922
   */
923
  public function shipsAllMovable() {
924
    return $this->unitList->unitsIsAllMovable($this->dbOwnerRow);
925
  }
926
927
  /**
928
   * Restores fleet or resources to planet
929
   *
930
   * @param bool $start
931
   * @param int  $result
932
   */
933
  // TODO - split to functions
934
  public function shipsLand($start = true) {
935
    sn_db_transaction_check(true);
936
937
    // Если флот уже обработан - не существует или возращается - тогда ничего не делаем
938
    if ($this->isEmpty()) {
939
      return;
940
    }
941
942
    $coordinates = $start ? $this->launch_coordinates_typed() : $this->target_coordinates_typed();
943
944
    // Поскольку эта функция может быть вызвана не из обработчика флотов - нам надо всё заблокировать вроде бы НЕ МОЖЕТ!!!
945
    // TODO Проверить от многократного срабатывания !!!
946
    // Тут не блокируем пока - сначала надо заблокировать пользователя, что бы не было дедлока
947
    // TODO поменять на владельца планеты - когда его будут возвращать всегда !!!
948
949
    // Узнаем ИД владельца планеты.
950
    // С блокировкой, поскольку эта функция может быть вызвана только из менеджера летящих флотов.
951
    // А там уже всё заблокировано как надо и повторная блокировка не вызовет дедлок.
952
    $planet_arrival = DBStaticPlanet::db_planet_by_vector($coordinates, '', true);
953
    // Блокируем пользователя
954
    // TODO - вообще-то нам уже известен пользователь в МЛФ - так что можно просто передать его сюда
955
    $user = DBStaticUser::db_user_by_id($planet_arrival['id_owner'], true);
956
957
    // TODO - Проверка, что планета всё еще существует на указанных координатах, а не телепортировалась, не удалена хозяином, не уничтожена врагом
958
    // Флот, который возвращается на захваченную планету, пропадает
959
    // Ship landing is possible only to fleet owner's planet
960
    if ($this->getPlayerOwnerId() == $planet_arrival['id_owner']) {
961
      // Adjusting ship amount on planet
962
      foreach ($this->shipsIterator() as $ship_id => $ship) {
963
        if ($ship->count) {
964
          DBStaticUnit::dbUpdateOrInsertUnit($ship_id, $ship->count, $user, $planet_arrival['id']);
965
        }
966
      }
967
968
      // Restoring resources to planet
969
      $this->resourcesUnload($start);
970
    }
971
972
    RestoreFleetToPlanet($this, $start);
973
974
    $this->dbDelete();
975
  }
976
977
978
  // Resources access ***************************************************************************************************
979
980
  /**
981
   * Extracts resources value from db_row
982
   *
983
   * @param array $db_row
984
   */
985
  protected function resourcesExtract(array &$db_row) {
986
    $this->resource_list = array(
987
      RES_METAL     => !empty($db_row['fleet_resource_metal']) ? floor($db_row['fleet_resource_metal']) : 0,
988
      RES_CRYSTAL   => !empty($db_row['fleet_resource_crystal']) ? floor($db_row['fleet_resource_crystal']) : 0,
989
      RES_DEUTERIUM => !empty($db_row['fleet_resource_deuterium']) ? floor($db_row['fleet_resource_deuterium']) : 0,
990
    );
991
  }
992
993
  protected function resourcesInject(array &$db_row) {
994
    $db_row['fleet_resource_metal'] = $this->resource_list[RES_METAL];
995
    $db_row['fleet_resource_crystal'] = $this->resource_list[RES_CRYSTAL];
996
    $db_row['fleet_resource_deuterium'] = $this->resource_list[RES_DEUTERIUM];
997
  }
998
999
  /**
1000
   * Set current resource list from array of units
1001
   *
1002
   * @param array $resource_list
1003
   */
1004
  public function resourcesSet($resource_list) {
1005
    if (!empty($this->propertiesAdjusted['resource_list'])) {
1006
      throw new ExceptionPropertyAccess('Property "resource_list" already was adjusted so no SET is possible until dbSave in ' . get_called_class() . '::unitSetResourceList', ERR_ERROR);
1007
    }
1008
    $this->resourcesAdjust($resource_list, true);
1009
  }
1010
1011
  /**
1012
   * Updates fleet resource list with deltas
1013
   *
1014
   * @param array $resource_delta_list
1015
   * @param bool  $replace_value
1016
   *
1017
   * @throws Exception
1018
   */
1019
  public function resourcesAdjust($resource_delta_list, $replace_value = false) {
1020
    !is_array($resource_delta_list) ? $resource_delta_list = array() : false;
1021
1022
    foreach ($resource_delta_list as $resource_id => $unit_delta) {
1023
      if (!UnitResourceLoot::is_in_group($resource_id) || !($unit_delta = floor($unit_delta))) {
1024
        // Not a resource or no resources - continuing
1025
        continue;
1026
      }
1027
1028
      if ($replace_value) {
1029
        $this->resource_list[$resource_id] = $unit_delta;
1030
      } else {
1031
        $this->resource_list[$resource_id] += $unit_delta;
1032
        // Preparing changes
1033
        $this->resource_delta[$resource_id] += $unit_delta;
1034
        $this->propertiesAdjusted['resource_list'] = 1;
1035
      }
1036
1037
      // Check for negative unit value
1038
      if ($this->resource_list[$resource_id] < 0) {
1039
        // TODO
1040
        throw new Exception('Resource ' . $resource_id . ' will become negative in ' . get_called_class() . '::unitAdjustResourceList', ERR_ERROR);
1041
      }
1042
    }
1043
  }
1044
1045
  public function resourcesGetTotal() {
1046
    return empty($this->resource_list) || !is_array($this->resource_list) ? 0 : array_sum($this->resource_list);
1047
  }
1048
1049
  /**
1050
   * @param array $rate
1051
   *
1052
   * @return float
1053
   */
1054
  public function resourcesGetTotalInMetal(array $rate) {
1055
    return
1056
      $this->resource_list[RES_METAL] * $rate[RES_METAL]
1057
      + $this->resource_list[RES_CRYSTAL] * $rate[RES_CRYSTAL] / $rate[RES_METAL]
1058
      + $this->resource_list[RES_DEUTERIUM] * $rate[RES_DEUTERIUM] / $rate[RES_METAL];
1059
  }
1060
1061
  /**
1062
   * Returns resource list in fleet
1063
   */
1064
  // TODO
1065
  public function resourcesGetList() {
1066
    return $this->resource_list;
1067
  }
1068
1069
  public function resourcesReset() {
1070
    $this->resourcesSet(array(
1071
      RES_METAL     => 0,
1072
      RES_CRYSTAL   => 0,
1073
      RES_DEUTERIUM => 0,
1074
    ));
1075
  }
1076
1077
  /**
1078
   * Restores fleet or resources to planet
1079
   *
1080
   * @param bool $start
1081
   * @param bool $only_resources
0 ignored issues
show
Bug introduced by
There is no parameter named $only_resources. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1082
   * @param int  $result
0 ignored issues
show
Bug introduced by
There is no parameter named $result. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1083
   */
1084
  public function resourcesUnload($start = true) {
1085
    sn_db_transaction_check(true);
1086
1087
    // Если флот уже обработан - не существует или возращается - тогда ничего не делаем
1088
    if (!$this->resourcesGetTotal()) {
1089
      return;
1090
    }
1091
1092
    $coordinates = $start ? $this->launch_coordinates_typed() : $this->target_coordinates_typed();
1093
1094
    // Поскольку эта функция может быть вызвана не из обработчика флотов - нам надо всё заблокировать вроде бы НЕ МОЖЕТ!!!
1095
    // TODO Проверить от многократного срабатывания !!!
1096
    // Тут не блокируем пока - сначала надо заблокировать пользователя, что бы не было дедлока
1097
    // TODO поменять на владельца планеты - когда его будут возвращать всегда !!!
1098
1099
1100
    // Узнаем ИД владельца планеты.
1101
    // С блокировкой, поскольку эта функция может быть вызвана только из менеджера летящих флотов.
1102
    // А там уже всё заблокировано как надо и повторная блокировка не вызовет дедлок.
1103
    $planet_arrival = DBStaticPlanet::db_planet_by_vector($coordinates, '', true);
1104
1105
    // TODO - Проверка, что планета всё еще существует на указанных координатах, а не телепортировалась, не удалена хозяином, не уничтожена врагом
1106
1107
    // Restoring resources to planet
1108
    if ($this->resourcesGetTotal()) {
1109
      $fleet_resources = $this->resourcesGetList();
1110
      DBStaticPlanet::db_planet_update_adjust_by_id(
1111
        $planet_arrival['id'],
1112
        array(
1113
          'metal'     => +$fleet_resources[RES_METAL],
1114
          'crystal'   => +$fleet_resources[RES_CRYSTAL],
1115
          'deuterium' => +$fleet_resources[RES_DEUTERIUM],
1116
        )
1117
      );
1118
    }
1119
1120
    $this->resourcesReset();
1121
  }
1122
1123
1124
  protected function isResource($unit_id) {
1125
    return UnitResourceLoot::is_in_group($unit_id);
1126
  }
1127
1128
  /**
1129
   * @param int $speed_percent
1130
   *
1131
   * @return array
1132
   */
1133
  protected function flt_travel_data($speed_percent = 10) {
1134
    $distance = $this->targetVector->distanceFromCoordinates($this->dbSourcePlanetRow);
1135
1136
    return $this->unitList->travelData($speed_percent, $distance, $this->dbOwnerRow);
1137
  }
1138
1139
1140
  /**
1141
   * @param array  $dbPlayerRow
1142
   * @param array  $dbPlanetRow
1143
   * @param Vector $targetVector
1144
   *
1145
   */
1146
  public function initDefaults($dbPlayerRow, $dbPlanetRow, $targetVector, $mission, $ships, $fleet_group_mr, $oldSpeedInTens = 10, $targetedUnitId = 0, $captainId = 0, $resources = array()) {
0 ignored issues
show
Unused Code introduced by
The parameter $resources is not used and could be removed.

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

Loading history...
1147
    $objFleet5Player = new Player();
1148
    $objFleet5Player->dbRowParse($dbPlayerRow);
1149
    $this->setLocatedAt($objFleet5Player);
1150
1151
    $this->mission_type = $mission;
1152
1153
    $this->dbOwnerRow = $dbPlayerRow;
1154
1155
    $this->set_start_planet($dbPlanetRow);
1156
    $this->dbSourcePlanetRow = $dbPlanetRow;
1157
1158
    $this->setTargetFromVectorObject($targetVector);
1159
    $this->targetVector = $targetVector;
1160
1161
//    if ($this->mission_type != MT_NONE) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1162
//      $this->restrictTargetTypeByMission();
1163
//
1164
//      // TODO - Нельзя тут просто менять тип планеты или координат!
1165
//      // If current planet type is not allowed on mission - switch planet type
1166
//      if (empty($this->allowed_planet_types[$this->targetVector->type])) {
1167
//        $targetPlanetCoords->type = reset($this->allowed_planet_types);
1168
//      }
1169
//    }
1170
1171
    $this->populateTargetPlanetAndOwner();
1172
1173
    $this->unitsSetFromArray($ships);
1174
1175
    $this->_group_id = intval($fleet_group_mr);
1176
1177
    $this->oldSpeedInTens = $oldSpeedInTens;
1178
1179
    $this->targetedUnitId = $targetedUnitId;
1180
1181
    $this->captainId = $captainId;
1182
1183
    $this->_time_launch = SN_TIME_NOW;
1184
1185
    $this->renderParamCoordinates();
1186
1187
  }
1188
1189
  protected function restrictTargetTypeByMission() {
1190
    if ($this->_mission_type == MT_MISSILE) {
1191
      $this->allowed_planet_types = array(PT_PLANET => PT_PLANET);
1192
    } elseif ($this->_mission_type == MT_COLONIZE || $this->_mission_type == MT_EXPLORE) {
1193
      // TODO - PT_NONE
1194
      $this->allowed_planet_types = array(PT_PLANET => PT_PLANET);
1195
    } elseif ($this->_mission_type == MT_RECYCLE) {
1196
      $this->allowed_planet_types = array(PT_DEBRIS => PT_DEBRIS);
1197
    } elseif ($this->_mission_type == MT_DESTROY) {
1198
      $this->allowed_planet_types = array(PT_MOON => PT_MOON);
1199
    } else {
1200
      $this->allowed_planet_types = array(PT_PLANET => PT_PLANET, PT_MOON => PT_MOON);
1201
    }
1202
  }
1203
1204
  protected function populateTargetPlanetAndOwner() {
1205
    // If vector points to no exact object OR debris - then getting planet on coordinates
1206
    $targetVector = clone $this->targetVector;
1207
    if ($targetVector->type == PT_DEBRIS || $targetVector == PT_NONE) {
1208
      $targetVector->type = PT_PLANET;
1209
    }
1210
1211
    $this->dbTargetRow = DBStaticPlanet::db_planet_by_vector_object($targetVector);
1212 View Code Duplication
    if (!empty($this->dbTargetRow['id_owner'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1213
      $this->dbTargetOwnerRow = DBStaticUser::db_user_by_id($this->dbTargetRow['id_owner'], true);
0 ignored issues
show
Documentation Bug introduced by
It seems like \DBStatic\DBStaticUser::...tRow['id_owner'], true) can also be of type false. However, the property $dbTargetOwnerRow is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
1214
    }
1215
  }
1216
1217
1218
  protected function printErrorIfNoShips() {
1219
    if ($this->unitList->unitsCount() <= 0) {
1220
      message(classLocale::$lang['fl_err_no_ships'], classLocale::$lang['fl_error'], 'fleet' . DOT_PHP_EX, 5);
1221
    }
1222
  }
1223
1224
  /**
1225
   */
1226
  public function renderParamCoordinates() {
1227
    global $template_result;
1228
    $template_result += array(
1229
      'thisgalaxy'      => $this->dbSourcePlanetRow['galaxy'],
1230
      'thissystem'      => $this->dbSourcePlanetRow['system'],
1231
      'thisplanet'      => $this->dbSourcePlanetRow['planet'],
1232
      'thisplanet_type' => $this->dbSourcePlanetRow['planet_type'],
1233
1234
      'galaxy'         => $this->targetVector->galaxy,
1235
      'system'         => $this->targetVector->system,
1236
      'planet'         => $this->targetVector->planet,
1237
      'planet_type'    => $this->targetVector->type,
1238
      'target_mission' => $this->_mission_type,
1239
      'MISSION_NAME'   => $this->_mission_type ? classLocale::$lang['type_mission'][$this->_mission_type] : '',
1240
1241
      'MT_COLONIZE' => MT_COLONIZE,
1242
    );
1243
  }
1244
1245
1246
  protected function renderFleetCoordinates($missionStartTimeStamp = SN_TIME_NOW, $timeMissionJob = 0) {
1247
    $timeToReturn = $this->travelData['duration'] * 2 + $timeMissionJob;
1248
1249
    return array(
1250
      'ID'                 => 1,
1251
      'START_TYPE_TEXT_SH' => classLocale::$lang['sys_planet_type_sh'][$this->dbSourcePlanetRow['planet_type']],
1252
      'START_COORDS'       => uni_render_coordinates($this->dbSourcePlanetRow),
1253
      'START_NAME'         => $this->dbSourcePlanetRow['name'],
1254
      'START_TIME_TEXT'    => date(FMT_DATE_TIME, $missionStartTimeStamp + $timeToReturn + SN_CLIENT_TIME_DIFF),
1255
      'START_LEFT'         => floor($timeToReturn),
1256
      'END_TYPE_TEXT_SH'   =>
1257
        !empty($this->targetVector->type)
1258
          ? classLocale::$lang['sys_planet_type_sh'][$this->targetVector->type]
1259
          : '',
1260
      'END_COORDS'         => uniRenderVector($this->targetVector),
1261
      'END_NAME'           => !empty($this->dbTargetRow['name']) ? $this->dbTargetRow['name'] : '',
1262
      'END_TIME_TEXT'      => date(FMT_DATE_TIME, $missionStartTimeStamp + $this->travelData['duration'] + SN_CLIENT_TIME_DIFF),
1263
      'END_LEFT'           => floor($this->travelData['duration']),
1264
    );
1265
  }
1266
1267
  /**
1268
   * @param int $missionStartTimeStamp
1269
   * @param int $timeMissionJob
1270
   *
1271
   * @return array
1272
   *
1273
   * @throws Exception
1274
   */
1275
  protected function renderFleet($missionStartTimeStamp = SN_TIME_NOW, $timeMissionJob = 0) {
1276
    $this->printErrorIfNoShips();
1277
1278
    $result = $this->renderFleetCoordinates($missionStartTimeStamp, $timeMissionJob);
1279
    $result['.']['ships'] = $this->unitList->unitsRender();
1280
1281
    return $result;
1282
  }
1283
1284
  /**
1285
   * @return array
1286
   */
1287
  protected function renderAllowedMissions() {
1288
    $result = array();
1289
1290
    ksort($this->allowed_missions);
1291
    // If mission is not set - setting first mission from allowed
1292
    if (empty($this->_mission_type) && is_array($this->allowed_missions)) {
1293
      reset($this->allowed_missions);
1294
      $this->_mission_type = key($this->allowed_missions);
1295
    }
1296
    foreach ($this->allowed_missions as $key => $value) {
1297
      $result[] = array(
1298
        'ID'   => $key,
1299
        'NAME' => classLocale::$lang['type_mission'][$key],
1300
      );
1301
    };
1302
1303
    return $result;
1304
  }
1305
1306
  /**
1307
   * @param $max_duration
1308
   *
1309
   * @return array
1310
   */
1311
  protected function renderDuration($max_duration) {
1312
    $result = array();
1313
1314
    if (!$max_duration) {
1315
      return $result;
1316
    }
1317
1318
    $config_game_speed_expedition = ($this->_mission_type == MT_EXPLORE && classSupernova::$config->game_speed_expedition ? classSupernova::$config->game_speed_expedition : 1);
1319
    for ($i = 1; $i <= $max_duration; $i++) {
1320
      $result[] = array(
1321
        'ID'   => $i,
1322
        'TIME' => pretty_time(ceil($i * 3600 / $config_game_speed_expedition)),
1323
      );
1324
    }
1325
1326
    return $result;
1327
  }
1328
1329
  /**
1330
   * @param array $planetResources
1331
   *
1332
   * @return array
1333
   */
1334
  // TODO - REDO to resource_id
1335
  protected function renderPlanetResources(&$planetResources) {
1336
    $result = array();
1337
1338
    $i = 0;
1339
    foreach ($planetResources as $resource_id => $resource_amount) {
1340
      $result[] = array(
1341
        'ID'        => $i++, // $resource_id,
1342
        'ON_PLANET' => $resource_amount,
1343
        'TEXT'      => pretty_number($resource_amount),
1344
        'NAME'      => classLocale::$lang['tech'][$resource_id],
1345
      );
1346
    }
1347
1348
    return $result;
1349
  }
1350
1351
  /**
1352
   * @return array
1353
   */
1354
  protected function renderAllowedPlanetTypes() {
1355
    $result = array();
1356
1357
    foreach ($this->allowed_planet_types as $possible_planet_type_id) {
1358
      $result[] = array(
1359
        'ID'         => $possible_planet_type_id,
1360
        'NAME'       => classLocale::$lang['sys_planet_type'][$possible_planet_type_id],
1361
        'NAME_SHORT' => classLocale::$lang['sys_planet_type_sh'][$possible_planet_type_id],
1362
      );
1363
    }
1364
1365
    return $result;
1366
  }
1367
1368
1369
  protected function renderFleet1TargetSelect(&$shortcut) {
1370
    global $note_priority_classes;
1371
1372
    $name = !empty($shortcut['title']) ? $shortcut['title'] : $shortcut['name'];
1373
1374
    $result = array(
1375
      'NAME'       => $name,
1376
      'GALAXY'     => $shortcut['galaxy'],
1377
      'SYSTEM'     => $shortcut['system'],
1378
      'PLANET'     => $shortcut['planet'],
1379
      'TYPE'       => $shortcut['planet_type'],
1380
      'TYPE_PRINT' => classLocale::$lang['fl_shrtcup'][$shortcut['planet_type']],
1381
    );
1382
1383
    if (isset($shortcut['priority'])) {
1384
      $result += array(
1385
        'PRIORITY'       => $shortcut['priority'],
1386
        'PRIORITY_CLASS' => $note_priority_classes[$shortcut['priority']],
1387
      );
1388
    }
1389
1390
    if (isset($shortcut['id'])) {
1391
      $result += array(
1392
        'ID' => $shortcut['id'],
1393
      );
1394
    }
1395
1396
    return $result;
1397
  }
1398
1399
  /**
1400
   * @return array
1401
   */
1402
  protected function renderFleetShortcuts() {
1403
    $result = array();
1404
1405
    // Building list of shortcuts
1406
    $query = DBStaticNote::db_note_list_select_by_owner_and_planet($this->dbOwnerRow);
1407
    while ($row = db_fetch($query)) {
1408
      $result[] = $this->renderFleet1TargetSelect($row);
1409
    }
1410
1411
    return $result;
1412
  }
1413
1414
  /**
1415
   * Building list of own planets & moons
1416
   *
1417
   * @return array
1418
   */
1419
  protected function renderOwnPlanets() {
1420
    $result = array();
1421
1422
    $colonies = DBStaticPlanet::db_planet_list_sorted($this->dbOwnerRow);
1423
    if (count($colonies) <= 1) {
1424
      return $result;
1425
    }
1426
1427
    foreach ($colonies as $row) {
1428
      if ($row['id'] == $this->dbSourcePlanetRow['id']) {
1429
        continue;
1430
      }
1431
1432
      $result[] = $this->renderFleet1TargetSelect($row);
1433
    }
1434
1435
    return $result;
1436
  }
1437
1438
  /**
1439
   * @return array
1440
   */
1441
  protected function renderACSList() {
1442
    $result = array();
1443
1444
    $query = DBStaticFleetACS::db_acs_get_list();
1445
    while ($row = db_fetch($query)) {
1446
      $members = explode(',', $row['eingeladen']);
1447
      foreach ($members as $a => $b) {
1448
        if ($b == $this->dbOwnerRow['id']) {
1449
          $result[] = $this->renderFleet1TargetSelect($row);
1450
        }
1451
      }
1452
    }
1453
1454
    return $result;
1455
  }
1456
1457
1458
  /**
1459
   * @param $template_result
1460
   */
1461
  protected function renderShipSortOptions(&$template_result) {
1462
    foreach (classLocale::$lang['player_option_fleet_ship_sort'] as $sort_id => $sort_text) {
1463
      $template_result['.']['ship_sort_list'][] = array(
1464
        'VALUE' => $sort_id,
1465
        'TEXT'  => $sort_text,
1466
      );
1467
    }
1468
    $template_result += array(
1469
      'FLEET_SHIP_SORT'         => classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_SORT],
1470
      'FLEET_SHIP_SORT_INVERSE' => classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_SORT_INVERSE],
1471
    );
1472
  }
1473
1474
1475
  /**
1476
   *
1477
   */
1478
  public function fleetPage0() {
1479
    global $template_result;
1480
1481
    lng_include('overview');
1482
1483
    if (empty($this->dbSourcePlanetRow)) {
1484
      message(classLocale::$lang['fl_noplanetrow'], classLocale::$lang['fl_error']);
1485
    }
1486
1487
    // TODO - redo to unitlist render/unit render
1488
    $template_result['.']['ships'] = $this->renderAvailableShips($this->dbOwnerRow, $this->dbSourcePlanetRow);
1489
1490
    $this->renderShipSortOptions($template_result);
1491
1492
    /**
1493
     * @var Player $playerOwner
1494
     */
1495
    $playerOwner = $this->getLocatedAt();
1496
1497
    $template_result += array(
1498
      'FLYING_FLEETS'      => $playerOwner->fleetsFlying(),
1499
      'MAX_FLEETS'         => $playerOwner->fleetsMax(),
1500
      'FREE_FLEETS'        => $playerOwner->fleetsMax() - $playerOwner->fleetsFlying(),
1501
      'FLYING_EXPEDITIONS' => $playerOwner->expeditionsFlying(),
1502
      'MAX_EXPEDITIONS'    => $playerOwner->expeditionsMax(),
1503
      'FREE_EXPEDITIONS'   => $playerOwner->expeditionsMax() - $playerOwner->expeditionsFlying(),
1504
      'COLONIES_CURRENT'   => $playerOwner->coloniesCurrent(),
1505
      'COLONIES_MAX'       => $playerOwner->coloniesMax(),
1506
1507
      'TYPE_NAME' => classLocale::$lang['fl_planettype'][$this->targetVector->type],
1508
1509
      'speed_factor' => flt_server_flight_speed_multiplier(),
1510
1511
      'PLANET_RESOURCES' => pretty_number($this->dbSourcePlanetRow['metal'] + $this->dbSourcePlanetRow['crystal'] + $this->dbSourcePlanetRow['deuterium']),
1512
      'PLANET_DEUTERIUM' => pretty_number($this->dbSourcePlanetRow['deuterium']),
1513
1514
      'PLAYER_OPTION_FLEET_SHIP_SELECT_OLD'       => classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_SELECT_OLD],
1515
      'PLAYER_OPTION_FLEET_SHIP_HIDE_SPEED'       => classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_HIDE_SPEED],
1516
      'PLAYER_OPTION_FLEET_SHIP_HIDE_CAPACITY'    => classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_HIDE_CAPACITY],
1517
      'PLAYER_OPTION_FLEET_SHIP_HIDE_CONSUMPTION' => classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_HIDE_CONSUMPTION],
1518
    );
1519
1520
    $template = gettemplate('fleet0', true);
1521
    $template->assign_recursive($template_result);
1522
    display($template, classLocale::$lang['fl_title']);
1523
  }
1524
1525
  /**
1526
   *
1527
   */
1528
  public function fleetPage1() {
1529
    global $template_result;
1530
1531
    $template_result['.']['fleets'][] = $this->renderFleet(SN_TIME_NOW);
1532
    $template_result['.']['possible_planet_type_id'] = $this->renderAllowedPlanetTypes();
1533
    $template_result['.']['colonies'] = $this->renderOwnPlanets();
1534
    $template_result['.']['shortcut'] = $this->renderFleetShortcuts();
1535
    $template_result['.']['acss'] = $this->renderACSList();
1536
1537
    $template_result += array(
1538
      'speed_factor' => flt_server_flight_speed_multiplier(),
1539
1540
      'fleet_speed'    => $this->fleetSpeed(),
1541
      'fleet_capacity' => $this->shipsGetCapacity(),
1542
1543
      'PLANET_DEUTERIUM' => pretty_number($this->dbSourcePlanetRow['deuterium']),
1544
1545
      'PAGE_HINT' => classLocale::$lang['fl_page1_hint'],
1546
    );
1547
1548
    $template = gettemplate('fleet1', true);
1549
    $template->assign_recursive($template_result);
1550
    display($template, classLocale::$lang['fl_title']);
1551
  }
1552
1553
  public function fleetSpeed() {
1554
    $maxSpeed = array();
1555
    foreach ($this->shipsIterator() as $ship_id => $unit) {
1556
      if ($unit->count > 0 && !empty(static::$snGroupFleetAndMissiles[$ship_id])) {
1557
        $single_ship_data = get_ship_data($ship_id, $this->dbOwnerRow);
1558
        $maxSpeed[$ship_id] = $single_ship_data['speed'];
1559
      }
1560
    }
1561
1562
    return empty($maxSpeed) ? 0 : min($maxSpeed);
1563
  }
1564
1565
  /**
1566
   * @param array $planetResourcesWithoutConsumption
1567
   */
1568
  public function fleetPage2Prepare($planetResourcesWithoutConsumption) {
0 ignored issues
show
Unused Code introduced by
The parameter $planetResourcesWithoutConsumption is not used and could be removed.

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

Loading history...
1569
    $this->travelData = $this->flt_travel_data($this->oldSpeedInTens);
1570
1571
//    /**
1572
//     * @var array $allowed_missions
1573
//     */
1574
//    public $allowed_missions = array();
1575
//    /**
1576
//     * @var array $exists_missions
1577
//     */
1578
//    public $exists_missions = array();
1579
//    public $allowed_planet_types = array(
1580
//      // PT_NONE => PT_NONE,
1581
//      PT_PLANET => PT_PLANET,
1582
//      PT_MOON   => PT_MOON,
1583
//      PT_DEBRIS => PT_DEBRIS
1584
//    );
1585
1586
//    $this->exists_missions = array(
1587
////      MT_EXPLORE => MT_EXPLORE,
1588
////      MT_MISSILE => MT_MISSILE,
1589
//      MT_COLONIZE => MT_COLONIZE,
1590
//    );  // TODO
1591
    $this->allowed_missions = array();
1592
1593
    if ($this->mission_type != MT_NONE && empty($this->exists_missions[$this->mission_type])) {
1594
      throw new ExceptionFleetInvalid(FLIGHT_MISSION_UNKNOWN, FLIGHT_MISSION_UNKNOWN);
1595
    }
1596
1597
    $this->validator->validateGlobals();
1598
1599
    $validateResult = array();
1600
    foreach ($this->exists_missions as $missionType => $missionData) {
1601
//print('qwe');
1602
      $mission = \Mission\MissionFactory::build($missionType, $this);
1603
//print('wer');
1604
      $validateResult[$missionType] = $mission->validate();
1605
      if (FLIGHT_ALLOWED == $validateResult[$missionType]) {
1606
        $this->allowed_missions[$missionType] = $mission;
1607
      } else {
1608
        if($missionType == $this->mission_type) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
1609
        }
1610
        unset($this->allowed_missions[$missionType]);
1611
      }
1612
    }
1613
1614
    if(empty($this->allowed_missions)) {
1615
      if($this->mission_type != MT_NONE && isset($validateResult[$this->mission_type])) {
1616
        throw new ExceptionFleetInvalid($validateResult[$this->mission_type], $validateResult[$this->mission_type]);
1617
      } else {
1618
        throw new ExceptionFleetInvalid(FLIGHT_MISSION_IMPOSSIBLE, FLIGHT_MISSION_IMPOSSIBLE);
1619
      }
1620
    }
1621
1622
//    $this->validator->validate();
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1623
  }
1624
1625
  /**
1626
   * @param array $planetResourcesWithoutConsumption
1627
   */
1628
  public function fleetPage3Prepare($planetResourcesWithoutConsumption) {
0 ignored issues
show
Unused Code introduced by
The parameter $planetResourcesWithoutConsumption is not used and could be removed.

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

Loading history...
1629
    $this->travelData = $this->flt_travel_data($this->oldSpeedInTens);
1630
1631
    if (empty($this->exists_missions[$this->mission_type])) {
1632
      throw new ExceptionFleetInvalid(FLIGHT_MISSION_UNKNOWN, FLIGHT_MISSION_UNKNOWN);
1633
    }
1634
1635
    $this->validator->validateGlobals();
1636
1637
    $mission = \Mission\MissionFactory::build($this->mission_type, $this);
1638
    $result = $mission->validate();
1639
    if (FLIGHT_ALLOWED != $result) {
1640
      throw new ExceptionFleetInvalid($result, $result);
1641
    }
1642
1643
  }
1644
1645
  /**
1646
   *
1647
   */
1648
  public function fleetPage2() {
1649
    global $template_result;
1650
1651
    $planetResourcesTotal = DBStaticPlanet::getResources($this->dbOwnerRow, $this->dbSourcePlanetRow);
1652
    $planetResourcesWithoutConsumption = $this->resourcesSubstractConsumption($planetResourcesTotal);
1653
1654
    try {
1655
      $this->fleetPage2Prepare($planetResourcesWithoutConsumption);
1656
    } catch (Exception $e) {
1657
      // TODO - MESSAGE BOX
1658 View Code Duplication
      if ($e instanceof ExceptionFleetInvalid) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1659
        sn_db_transaction_rollback();
1660
        pdie(classLocale::$lang['fl_attack_error'][$e->getCode()]);
1661
      } else {
1662
        throw $e;
1663
      }
1664
    }
1665
1666
    // Flight allowed here
1667
    pdump('FLIGHT_ALLOWED', FLIGHT_ALLOWED);
1668
//    pdump('// TODO - Сделать flletvalidator DI - внутре контейнер для методов, а методы - анонимные функции, вызывающие другие методы же', FLIGHT_ALLOWED);
0 ignored issues
show
Unused Code Comprehensibility introduced by
56% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1669
1670
    $template_result['.']['missions'] = $this->renderAllowedMissions();
1671
1672
    $template_result['.']['fleets'][] = $this->renderFleet(SN_TIME_NOW);
1673
1674
    $max_duration =
1675
      $this->_mission_type == MT_EXPLORE
1676
        ? get_player_max_expedition_duration($this->dbOwnerRow)
1677
        : (isset($this->allowed_missions[MT_HOLD]) ? 12 : 0);
1678
    $template_result['.']['duration'] = $this->renderDuration($max_duration);
1679
1680
    $this->captainGet();
1681
    $template_result += $this->renderCaptain();
1682
1683
    $template_result['.']['resources'] = $this->renderPlanetResources($planetResourcesWithoutConsumption);
1684
1685
    $template_result += array(
1686
      'planet_metal'     => $planetResourcesWithoutConsumption[RES_METAL],
1687
      'planet_crystal'   => $planetResourcesWithoutConsumption[RES_CRYSTAL],
1688
      'planet_deuterium' => $planetResourcesWithoutConsumption[RES_DEUTERIUM],
1689
1690
      'fleet_capacity' => $this->shipsGetCapacity() - $this->travelData['consumption'],
1691
      'speed'          => $this->oldSpeedInTens,
1692
      'fleet_group'    => $this->_group_id,
1693
1694
      'MAX_DURATION'          => $max_duration,
1695
1696
      // TODO - remove
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1697
//      'IS_TRANSPORT_MISSIONS' => !empty($this->allowed_missions[$this->_mission_type]['transport']),
1698
      'IS_TRANSPORT_MISSIONS' => true,
1699
1700
      'PLAYER_COLONIES_CURRENT' => get_player_current_colonies($this->dbOwnerRow),
1701
      'PLAYER_COLONIES_MAX'     => get_player_max_colonies($this->dbOwnerRow),
1702
    );
1703
1704
    $template = gettemplate('fleet2', true);
1705
    $template->assign_recursive($template_result);
1706
    display($template, classLocale::$lang['fl_title']);
1707
  }
1708
1709
  /**
1710
   *
1711
   */
1712
  public function fleetPage3() {
1713
    global $template_result;
1714
1715
    $this->isRealFlight = true;
1716
1717
    sn_db_transaction_start();
1718
1719
    DBStaticUser::db_user_lock_with_target_owner_and_acs($this->dbOwnerRow, $this->dbTargetRow);
1720
1721
    // Checking for group
1722
    $this->groupCheck();
1723
1724
    $this->dbOwnerRow = DBStaticUser::db_user_by_id($this->dbOwnerRow['id'], true);
0 ignored issues
show
Documentation Bug introduced by
It seems like \DBStatic\DBStaticUser::...dbOwnerRow['id'], true) can also be of type false. However, the property $dbOwnerRow is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
1725
    $this->dbSourcePlanetRow = DBStaticPlanet::db_planet_by_id($this->dbSourcePlanetRow['id'], true);
0 ignored issues
show
Documentation Bug introduced by
It seems like \DBStatic\DBStaticPlanet...ePlanetRow['id'], true) can be null. However, the property $dbSourcePlanetRow is declared as array. Maybe change the type of the property to array|null or add a type check?

Our type inference engine has found an assignment of a scalar value (like a string, an integer or null) to a property which is an array.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.

To type hint that a parameter can be either an array or null, you can set a type hint of array and a default value of null. The PHP interpreter will then accept both an array or null for that parameter.

function aContainsB(array $needle = null, array  $haystack) {
    if (!$needle) {
        return false;
    }

    return array_intersect($haystack, $needle) == $haystack;
}

The function can be called with either null or an array for the parameter $needle but will only accept an array as $haystack.

Loading history...
1726
    if (!empty($this->dbTargetRow['id'])) {
1727
      $this->dbTargetRow = DBStaticPlanet::db_planet_by_id($this->dbTargetRow['id'], true);
0 ignored issues
show
Documentation Bug introduced by
It seems like \DBStatic\DBStaticPlanet...bTargetRow['id'], true) can be null. However, the property $dbTargetRow is declared as array. Maybe change the type of the property to array|null or add a type check?

Our type inference engine has found an assignment of a scalar value (like a string, an integer or null) to a property which is an array.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.

To type hint that a parameter can be either an array or null, you can set a type hint of array and a default value of null. The PHP interpreter will then accept both an array or null for that parameter.

function aContainsB(array $needle = null, array  $haystack) {
    if (!$needle) {
        return false;
    }

    return array_intersect($haystack, $needle) == $haystack;
}

The function can be called with either null or an array for the parameter $needle but will only accept an array as $haystack.

Loading history...
1728
    }
1729
    // TODO - deprecated! Filled in populateTargetPlanetAndOwner
1730 View Code Duplication
    if (!empty($this->dbTargetRow['id_owner'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1731
      $this->dbTargetOwnerRow = DBStaticUser::db_user_by_id($this->dbTargetRow['id_owner'], true);
0 ignored issues
show
Documentation Bug introduced by
It seems like \DBStatic\DBStaticUser::...tRow['id_owner'], true) can also be of type false. However, the property $dbTargetOwnerRow is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
1732
    }
1733
1734
    $this->resource_list = array(
1735
      RES_METAL     => max(0, floor(sys_get_param_float('resource0'))),
1736
      RES_CRYSTAL   => max(0, floor(sys_get_param_float('resource1'))),
1737
      RES_DEUTERIUM => max(0, floor(sys_get_param_float('resource2'))),
1738
    );
1739
1740
    $this->captainGet();
1741
1742
    $this->travelData = $this->flt_travel_data($this->oldSpeedInTens);
1743
1744
    $planetResourcesTotal = DBStaticPlanet::getResources($this->dbOwnerRow, $this->dbSourcePlanetRow);
0 ignored issues
show
Security Bug introduced by
It seems like $this->dbOwnerRow can also be of type false; however, DBStatic\DBStaticPlanet::getResources() does only seem to accept array, did you maybe forget to handle an error condition?
Loading history...
Bug introduced by
It seems like $this->dbSourcePlanetRow can also be of type null; however, DBStatic\DBStaticPlanet::getResources() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1745
    $planetResourcesWithoutConsumption = $this->resourcesSubstractConsumption($planetResourcesTotal);
1746
1747
    try {
1748
      $this->fleetPage3Prepare($planetResourcesWithoutConsumption);
1749
    } catch (Exception $e) {
1750
      // TODO - MESSAGE BOX
1751 View Code Duplication
      if ($e instanceof ExceptionFleetInvalid) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1752
        sn_db_transaction_rollback();
1753
        pdie(classLocale::$lang['fl_attack_error'][$e->getCode()]);
1754
      } else {
1755
        throw $e;
1756
      }
1757
    }
1758
1759
//    try {
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1760
//      $validator = new FleetValidator($this);
1761
//      $validator->validate();
1762
//    } catch (Exception $e) {
1763
//      // TODO - MESSAGE BOX
1764
//      if($e instanceof Exception\ExceptionFleetInvalid) {
1765
//        sn_db_transaction_rollback();
1766
//        pdie(classLocale::$lang['fl_attack_error'][$e->getCode()]);
1767
//      } else {
1768
//        throw $e;
1769
//      }
1770
//    }
1771
1772
    // TODO - check if mission is not 0 and in ALLOWED_MISSIONS
1773
1774
    // Flight allowed here
1775
    pdump('FLIGHT_ALLOWED', FLIGHT_ALLOWED);
1776
//    pdump('// TODO - Сделать flletvalidator DI - внутре контейнер для методов, а методы - анонимные функции, вызывающие другие методы же', FLIGHT_ALLOWED);
0 ignored issues
show
Unused Code Comprehensibility introduced by
56% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1777
1778
1779
    $timeMissionJob = 0;
1780
    // TODO check for empty mission AKA mission allowed
1781
    /*
1782
        if ($this->_mission_type == MT_ACS && $aks) {
1783
          $acsTimeToArrive = $aks['ankunft'] - SN_TIME_NOW;
1784
          if ($acsTimeToArrive < $this->travelData['duration']) {
1785
            message(classLocale::$lang['fl_aks_too_slow'] . 'Fleet arrival: ' . date(FMT_DATE_TIME, SN_TIME_NOW + $this->travelData['duration']) . " AKS arrival: " . date(FMT_DATE_TIME, $aks['ankunft']), classLocale::$lang['fl_error']);
1786
          }
1787
          // Set time to travel to ACS' TTT
1788
          $this->travelData['duration'] = $acsTimeToArrive;
1789
    */
1790
    if ($this->_mission_type != MT_ACS) {
1791
      if ($this->_mission_type == MT_EXPLORE || $this->_mission_type == MT_HOLD) {
1792
        $max_duration = $this->_mission_type == MT_EXPLORE ? get_player_max_expedition_duration($this->dbOwnerRow) : ($this->_mission_type == MT_HOLD ? 12 : 0);
1793
        if ($max_duration) {
1794
          $mission_time_in_hours = sys_get_param_id('missiontime');
1795
          if ($mission_time_in_hours > $max_duration || $mission_time_in_hours < 1) {
1796
            classSupernova::$debug->warning('Supplying wrong mission time', 'Hack attempt', 302, array('base_dump' => true));
1797
            die();
1798
          }
1799
          $timeMissionJob = ceil($mission_time_in_hours * 3600 / ($this->_mission_type == MT_EXPLORE && classSupernova::$config->game_speed_expedition ? classSupernova::$config->game_speed_expedition : 1));
1800
        }
1801
      }
1802
    }
1803
1804
    //
1805
    //
1806
    //
1807
    //
1808
    //
1809
    //
1810
    //
1811
    //
1812
    // ---------------- END OF CHECKS ------------------------------------------------------
1813
1814
    $this->set_times($this->travelData['duration'], $timeMissionJob);
1815
    $this->dbInsert();
1816
    $this->unitList->dbSubstractUnitsFromPlanet($this->dbOwnerRow, $this->dbSourcePlanetRow['id']);
1817
1818
    DBStaticPlanet::db_planet_update_adjust_by_id(
1819
      $this->dbSourcePlanetRow['id'],
1820
      array(
1821
        'metal'     => -$this->resource_list[RES_METAL],
1822
        'crystal'   => -$this->resource_list[RES_CRYSTAL],
1823
        'deuterium' => -$this->resource_list[RES_DEUTERIUM] - $this->travelData['consumption'],
1824
      )
1825
    );
1826
1827
    if (!empty($this->captain['unit_id'])) {
1828
      DBStaticUnit::db_unit_set_by_id(
1829
        $this->captain['unit_id'],
1830
        array(
1831
          'unit_location_type' => LOC_FLEET,
1832
          'unit_location_id'   => $this->_dbId,
1833
        ),
1834
        array()
1835
      );
1836
    }
1837
1838
//    return $this->fleet->acs['ankunft'] - $this->fleet->time_launch >= $this->fleet->travelData['duration'];
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1839
//
1840
//    // Set time to travel to ACS' TTT
1841
//    $this->fleet->travelData['duration'] = $acsTimeToArrive;
1842
1843
1844
    $template_result['.']['fleets'][] = $this->renderFleet(SN_TIME_NOW, $timeMissionJob);
1845
1846
    $template_result += array(
1847
      'mission'         => classLocale::$lang['type_mission'][$this->_mission_type] . ($this->_mission_type == MT_EXPLORE || $this->_mission_type == MT_HOLD ? ' ' . pretty_time($timeMissionJob) : ''),
1848
      'dist'            => pretty_number($this->travelData['distance']),
1849
      'speed'           => pretty_number($this->travelData['fleet_speed']),
1850
      'deute_need'      => pretty_number($this->travelData['consumption']),
1851
      'from'            => "{$this->dbSourcePlanetRow['galaxy']}:{$this->dbSourcePlanetRow['system']}:{$this->dbSourcePlanetRow['planet']}",
1852
      'time_go'         => date(FMT_DATE_TIME, $this->_time_arrive_to_target),
1853
      'time_go_local'   => date(FMT_DATE_TIME, $this->_time_arrive_to_target + SN_CLIENT_TIME_DIFF),
1854
      'time_back'       => date(FMT_DATE_TIME, $this->_time_return_to_source),
1855
      'time_back_local' => date(FMT_DATE_TIME, $this->_time_return_to_source + SN_CLIENT_TIME_DIFF),
1856
    );
1857
1858
    $this->dbSourcePlanetRow = DBStaticPlanet::db_planet_by_id($this->dbSourcePlanetRow['id']);
0 ignored issues
show
Documentation Bug introduced by
It seems like \DBStatic\DBStaticPlanet...bSourcePlanetRow['id']) can be null. However, the property $dbSourcePlanetRow is declared as array. Maybe change the type of the property to array|null or add a type check?

Our type inference engine has found an assignment of a scalar value (like a string, an integer or null) to a property which is an array.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.

To type hint that a parameter can be either an array or null, you can set a type hint of array and a default value of null. The PHP interpreter will then accept both an array or null for that parameter.

function aContainsB(array $needle = null, array  $haystack) {
    if (!$needle) {
        return false;
    }

    return array_intersect($haystack, $needle) == $haystack;
}

The function can be called with either null or an array for the parameter $needle but will only accept an array as $haystack.

Loading history...
1859
1860
    pdie('Stop for debug');
1861
1862
    sn_db_transaction_commit();
1863
1864
    $template = gettemplate('fleet3', true);
1865
    $template->assign_recursive($template_result);
1866
    display($template, classLocale::$lang['fl_title']);
1867
  }
1868
1869
  protected function groupCheck() {
1870
    if (empty($this->_group_id)) {
1871
      return;
1872
    }
1873
1874
    // ACS attack must exist (if acs fleet has arrived this will also return false (2 checks in 1!!!)
1875
    $this->acs = DBStaticFleetACS::db_acs_get_by_group_id($this->_group_id);
1876
    if (empty($this->acs)) {
1877
      $this->_group_id = 0;
1878
    } else {
1879
      $this->targetVector->convertToVector($this->acs);
1880
    }
1881
  }
1882
1883
  /**
1884
   * @param array $planetResources
1885
   *
1886
   * @return array
1887
   */
1888
  protected function resourcesSubstractConsumption($planetResources) {
1889
    !isset($planetResources[RES_DEUTERIUM]) ? $planetResources[RES_DEUTERIUM] = 0 : false;
1890
1891
    if ($this->travelData['consumption'] >= 0) {
1892
      $planetResources[RES_DEUTERIUM] -= ceil($this->travelData['consumption']);
1893
    }
1894
1895
    return $planetResources;
1896
  }
1897
1898
  /**
1899
   */
1900
  public function captainGet() {
1901
    $this->captain = array();
1902
1903
    /**
1904
     * @var unit_captain $moduleCaptain
1905
     */
1906
    if (sn_module::isModuleActive('unit_captain')) {
1907
      $moduleCaptain = sn_module::getModule('unit_captain');
1908
      $this->captain = $moduleCaptain->unit_captain_get($this->dbSourcePlanetRow['id']);
0 ignored issues
show
Bug introduced by
The method unit_captain_get() does not seem to exist on object<sn_module>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1909
    }
1910
  }
1911
1912
  /**
1913
   * @return array
1914
   */
1915
  protected function renderCaptain() {
1916
    $result = array();
1917
1918
    if (!empty($this->captain['unit_id']) && $this->captain['unit_location_type'] == LOC_PLANET) {
1919
      $result = array(
1920
        'CAPTAIN_ID'     => $this->captain['unit_id'],
1921
        'CAPTAIN_LEVEL'  => $this->captain['captain_level'],
1922
        'CAPTAIN_SHIELD' => $this->captain['captain_shield'],
1923
        'CAPTAIN_ARMOR'  => $this->captain['captain_armor'],
1924
        'CAPTAIN_ATTACK' => $this->captain['captain_attack'],
1925
      );
1926
    }
1927
1928
    return $result;
1929
  }
1930
1931
}
1932
1933
if (empty(Fleet::$snGroupFleet)) {
1934
  Fleet::$snGroupFleet = sn_get_groups('fleet');
1935
  Fleet::$snGroupFleetAndMissiles = sn_get_groups(array('fleet', GROUP_STR_MISSILES));
1936
  Fleet::$snGroupRecyclers = sn_get_groups('flt_recyclers');
1937
}
1938