Completed
Push — work-fleets ( d1f99e...fc0000 )
by SuperNova.WS
06:40
created

Fleet::renderShipSortOptions()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 8
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 12
rs 9.4285
ccs 0
cts 12
cp 0
crap 6
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
  /**
167
   * `fleet_owner`
168
   *
169
   * @var int
170
   */
171
  protected $_playerOwnerId = 0;
172
  /**
173
   * `fleet_group`
174
   *
175
   * @var int
176
   */
177
  protected $_group_id = 0;
178
  public $acs = array();
179
180
  /**
181
   * `fleet_mission`
182
   *
183
   * @var int
184
   */
185
  protected $_mission_type = 0;
186
187
  /**
188
   * `fleet_target_owner`
189
   *
190
   * @var int
191
   */
192
  protected $_target_owner_id = null;
193
194
  /**
195
   * @var array
196
   */
197
  public $resource_list = array(
198
    RES_METAL     => 0,
199
    RES_CRYSTAL   => 0,
200
    RES_DEUTERIUM => 0,
201
  );
202
203
204
  /**
205
   * `fleet__mess` - Флаг возвращающегося флота
206
   *
207
   * @var int
208
   */
209
  protected $_is_returning = 0;
210
  /**
211
   * `start_time` - Время отправления - таймштамп взлёта флота из точки отправления
212
   *
213
   * @var int $_time_launch
214
   */
215
  protected $_time_launch = 0; // `start_time` = SN_TIME_NOW
216
  /**
217
   * `fleet_start_time` - Время прибытия в точку миссии/время начала выполнения миссии
218
   *
219
   * @var int $_time_arrive_to_target
220
   */
221
  protected $_time_arrive_to_target = 0; // `fleet_start_time` = SN_TIME_NOW + $time_travel
222
  /**
223
   * `fleet_end_stay` - Время окончания миссии в точке назначения
224
   *
225
   * @var int $_time_mission_job_complete
226
   */
227
  protected $_time_mission_job_complete = 0; // `fleet_end_stay`
228
  /**
229
   * `fleet_end_time` - Время возвращения флота после окончания миссии
230
   *
231
   * @var int $_time_return_to_source
232
   */
233
  protected $_time_return_to_source = 0; // `fleet_end_time`
234
235
236
  protected $_fleet_start_planet_id = null;
237
  protected $_fleet_start_galaxy = 0;
238
  protected $_fleet_start_system = 0;
239
  protected $_fleet_start_planet = 0;
240
  protected $_fleet_start_type = PT_ALL;
241
242
  protected $_fleet_end_planet_id = null;
243
  protected $_fleet_end_galaxy = 0;
244
  protected $_fleet_end_system = 0;
245
  protected $_fleet_end_planet = 0;
246
  protected $_fleet_end_type = PT_ALL;
247
248
  // Missile properties
249
  public $missile_target = 0;
250
251
  // Fleet event properties
252
  public $fleet_start_name = '';
253
  public $fleet_end_name = '';
254
  public $ov_label = '';
255
  public $ov_this_planet = '';
256
  public $event_time = 0;
257
258
  protected $resource_delta = array();
259
  protected $resource_replace = array();
260
261
262
//
263
264
265
  /**
266
   * @var array $allowed_missions
267
   */
268
  public $allowed_missions = array();
269
  /**
270
   * @var array $exists_missions
271
   */
272
  public $exists_missions = array();
273
  public $allowed_planet_types = array(
274
    // PT_NONE => PT_NONE,
275
    PT_PLANET => PT_PLANET,
276
    PT_MOON   => PT_MOON,
277
    PT_DEBRIS => PT_DEBRIS
278
  );
279
280
  // TODO - Move to Player
281
  public $dbOwnerRow = array();
282
  public $dbSourcePlanetRow = array();
283
284
  /**
285
   * GSPT coordinates of target
286
   *
287
   * @var Vector
288
   */
289
  public $targetVector = array();
290
  /**
291
   * Target planet row
292
   *
293
   * @var array
294
   */
295
  public $dbTargetRow = array();
296
  public $dbTargetOwnerRow = array();
297
298
  /**
299
   * Fleet speed - old in 1/10 of 100%
300
   *
301
   * @var int
302
   */
303
  public $oldSpeedInTens = 0;
304
305
  public $tempPlayerMaxFleets = 0;
306
  public $travelData = array();
307
308
  public $isRealFlight = false;
309
310
  /**
311
   * @var int $targetedUnitId
312
   */
313
  public $targetedUnitId = 0;
314
315
  /**
316
   * @var array $captain
317
   */
318
  public $captain = array();
319
  /**
320
   * @var int $captainId
321
   */
322
  public $captainId = 0;
323
324
  /**
325
   * @var FleetValidator $validator
326
   */
327
  public $validator;
328
329
330
  /**
331
   * @var UnitList $unitList
332
   */
333
  protected $unitList = null;
334
335
336
  /**
337
   * Fleet constructor.
338
   */
339
  public function __construct() {
340
    parent::__construct();
341
    $this->exists_missions = sn_get_groups('missions');
342
    $this->validator = new FleetValidator($this);
343
  }
344
345
  /**
346
   * @param array $playerRow
347
   * @param array $planetRow
348
   *
349
   * @return array
350
   */
351
  // TODO - redo to unit/unitlist renderer
352
  public function renderAvailableShips($playerRow, $planetRow) {
353
    $record_index = 0;
354
    $ship_list = array();
355
    foreach (classSupernova::$gc->groupFleet as $n => $unit_id) {
0 ignored issues
show
Bug introduced by
The expression \classSupernova::$gc->groupFleet of type array|object<Closure> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
356
      $unit_level = mrc_get_level($playerRow, $planetRow, $unit_id, false, true);
357
      if ($unit_level <= 0) {
358
        continue;
359
      }
360
      $ship_data = get_ship_data($unit_id, $playerRow);
361
      $ship_list[$unit_id] = array(
362
        '__INDEX'          => $record_index++,
363
        'ID'               => $unit_id,
364
        'NAME'             => classLocale::$lang['tech'][$unit_id],
365
        'AMOUNT'           => $unit_level,
366
        'AMOUNT_TEXT'      => pretty_number($unit_level),
367
        'CONSUMPTION'      => $ship_data['consumption'],
368
        'CONSUMPTION_TEXT' => pretty_number($ship_data['consumption']),
369
        'SPEED'            => $ship_data['speed'],
370
        'SPEED_TEXT'       => pretty_number($ship_data['speed']),
371
        'CAPACITY'         => $ship_data['capacity'],
372
        'CAPACITY_TEXT'    => pretty_number($ship_data['capacity']),
373
      );
374
    }
375
376
    sortUnitRenderedList($ship_list, classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_SORT], classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_SORT_INVERSE]);
377
378
    return $ship_list;
379
  }
380
381
  public function isEmpty() {
382
    return !$this->resourcesGetTotal() && !$this->shipsGetTotal();
383
  }
384
385
//  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...
386
//    return $this->playerOwnerId;
387
//  }
388
389
  /**
390
   * Initializes Fleet from user params and posts it to DB
391
   */
392
  public function dbInsert() {
393
    // WARNING! MISSION TIMES MUST BE SET WITH set_times() method!
394
    // TODO - more checks!
395
    if (empty($this->_time_launch)) {
396
      die('Fleet time not set!');
397
    }
398
399
    parent::dbInsert();
400
  }
401
402
403
  /* FLEET DB ACCESS =================================================================================================*/
404
405
  /**
406
   * LOCK - Lock all records which can be used with mission
407
   *
408
   * @param $mission_data
409
   *
410
   * @return array|bool|mysqli_result|null
411
   */
412
  public function dbLockFlying(&$mission_data) {
413
    // Тупо лочим всех юзеров, чьи флоты летят или улетают с координат отбытия/прибытия $fleet_row
414
    // Что бы делать это умно - надо учитывать fleet__mess во $fleet_row и в таблице fleets
415
416
    $fleet_id_safe = idval($this->_dbId);
417
418
    return classSupernova::$db->doSelect(
419
    // Блокировка самого флота
420
      "SELECT 1 FROM {{fleets}} AS f " .
421
422
      // Блокировка всех юнитов, принадлежащих этому флоту
423
      "LEFT JOIN {{unit}} as unit ON unit.unit_location_type = " . static::$locationType . " AND unit.unit_location_id = f.fleet_id " .
424
425
      // Блокировка всех прилетающих и улетающих флотов, если нужно
426
      // TODO - lock fleets by COORDINATES
427
      ($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 " : '') .
428
      // Блокировка всех юнитов, принадлежащих прилетающим и улетающим флотам - ufd = unit_fleet_destination
429
      ($mission_data['dst_fleets'] ? "LEFT JOIN {{unit}} AS ufd ON ufd.unit_location_type = " . static::$locationType . " AND ufd.unit_location_id = fd.fleet_id " : '') .
430
431
      ($mission_data['dst_user'] || $mission_data['dst_planet'] ? "LEFT JOIN {{users}} AS ud ON ud.id = f.fleet_target_owner " : '') .
432
      // Блокировка всех юнитов, принадлежащих владельцу планеты-цели
433
      ($mission_data['dst_user'] || $mission_data['dst_planet'] ? "LEFT JOIN {{unit}} AS unit_player_dest ON unit_player_dest.unit_player_id = ud.id " : '') .
434
      // Блокировка планеты-цели
435
      ($mission_data['dst_planet'] ? "LEFT JOIN {{planets}} AS pd ON pd.id = f.fleet_end_planet_id " : '') .
436
      // Блокировка всех юнитов, принадлежащих планете-цели - НЕ НУЖНО. Уже залочили ранее, как принадлежащие игроку-цели
437
//      ($mission_data['dst_planet'] ? "LEFT JOIN {{unit}} AS upd ON upd.unit_location_type = " . LOC_PLANET . " AND upd.unit_location_id = pd.id " : '') .
438
439
440
      ($mission_data['src_user'] || $mission_data['src_planet'] ? "LEFT JOIN {{users}} AS us ON us.id = f.fleet_owner " : '') .
441
      // Блокировка всех юнитов, принадлежащих владельцу флота
442
      ($mission_data['src_user'] || $mission_data['src_planet'] ? "LEFT JOIN {{unit}} AS unit_player_src ON unit_player_src.unit_player_id = us.id " : '') .
443
      // Блокировка планеты отправления
444
      ($mission_data['src_planet'] ? "LEFT JOIN {{planets}} AS ps ON ps.id = f.fleet_start_planet_id " : '') .
445
      // Блокировка всех юнитов, принадлежащих планете с которой юниты были отправлены - НЕ НУЖНО. Уже залочили ранее, как принадлежащие владельцу флота
446
//      ($mission_data['src_planet'] ? "LEFT JOIN {{unit}} AS ups ON ups.unit_location_type = " . LOC_PLANET . " AND ups.unit_location_id = ps.id " : '') .
447
448
      "WHERE f.fleet_id = {$fleet_id_safe} GROUP BY 1 FOR UPDATE"
449
    );
450
  }
451
452
  /**
453
   * Lock all fields that belongs to operation
454
   *
455
   * @param $dbId
456
   */
457
  // TODO = make static
458
  public function dbGetLockById($dbId) {
459
    classSupernova::$db->doSelect(
460
    // Блокировка самого флота
461
      "SELECT 1 FROM {{fleets}} AS FLEET0 " .
462
      // Lock fleet owner
463
      "LEFT JOIN {{users}} as USER0 on USER0.id = FLEET0.fleet_owner " .
464
      // Блокировка всех юнитов, принадлежащих этому флоту
465
      "LEFT JOIN {{unit}} as UNIT0 ON UNIT0.unit_location_type = " . LOC_FLEET . " AND UNIT0.unit_location_id = FLEET0.fleet_id " .
466
467
      // Без предварительной выборки неизвестно - куда летит этот флот.
468
      // Поэтому надо выбирать флоты, чьи координаты прибытия ИЛИ отбытия совпадают с координатами прибытия ИЛИ отбытия текущего флота.
469
      // Получаем матрицу 2х2 - т.е. 4 подзапроса.
470
      // При блокировке всегда нужно выбирать И лпанету, И луну - поскольку при бое на орбите луны обломки падают на орбиту планеты.
471
      // Поэтому тип планеты не указывается
472
473
      // Lock fleet heading to destination planet. Only if FLEET0.fleet_mess == 0
474
      "LEFT JOIN {{fleets}} AS FLEET1 ON
475
        FLEET1.fleet_mess = 0 AND FLEET0.fleet_mess = 0 AND
476
        FLEET1.fleet_end_galaxy = FLEET0.fleet_end_galaxy AND
477
        FLEET1.fleet_end_system = FLEET0.fleet_end_system AND
478
        FLEET1.fleet_end_planet = FLEET0.fleet_end_planet
479
      " .
480
      // Блокировка всех юнитов, принадлежащих этим флотам
481
      "LEFT JOIN {{unit}} as UNIT1 ON UNIT1.unit_location_type = " . LOC_FLEET . " AND UNIT1.unit_location_id = FLEET1.fleet_id " .
482
      // Lock fleet owner
483
      "LEFT JOIN {{users}} as USER1 on USER1.id = FLEET1.fleet_owner " .
484
485
      "LEFT JOIN {{fleets}} AS FLEET2 ON
486
        FLEET2.fleet_mess = 1   AND FLEET0.fleet_mess = 0 AND
487
        FLEET2.fleet_start_galaxy = FLEET0.fleet_end_galaxy AND
488
        FLEET2.fleet_start_system = FLEET0.fleet_end_system AND
489
        FLEET2.fleet_start_planet = FLEET0.fleet_end_planet
490
      " .
491
      // Блокировка всех юнитов, принадлежащих этим флотам
492
      "LEFT JOIN {{unit}} as UNIT2 ON
493
        UNIT2.unit_location_type = " . LOC_FLEET . " AND
494
        UNIT2.unit_location_id = FLEET2.fleet_id
495
      " .
496
      // Lock fleet owner
497
      "LEFT JOIN {{users}} as USER2 on
498
        USER2.id = FLEET2.fleet_owner
499
      " .
500
501
      // Lock fleet heading to source planet. Only if FLEET0.fleet_mess == 1
502
      "LEFT JOIN {{fleets}} AS FLEET3 ON
503
        FLEET3.fleet_mess = 0 AND FLEET0.fleet_mess = 1 AND
504
        FLEET3.fleet_end_galaxy = FLEET0.fleet_start_galaxy AND
505
        FLEET3.fleet_end_system = FLEET0.fleet_start_system AND
506
        FLEET3.fleet_end_planet = FLEET0.fleet_start_planet
507
      " .
508
      // Блокировка всех юнитов, принадлежащих этим флотам
509
      "LEFT JOIN {{unit}} as UNIT3 ON
510
        UNIT3.unit_location_type = " . LOC_FLEET . " AND
511
        UNIT3.unit_location_id = FLEET3.fleet_id
512
      " .
513
      // Lock fleet owner
514
      "LEFT JOIN {{users}} as USER3 on USER3.id = FLEET3.fleet_owner " .
515
516
      "LEFT JOIN {{fleets}} AS FLEET4 ON
517
        FLEET4.fleet_mess = 1   AND FLEET0.fleet_mess = 1 AND
518
        FLEET4.fleet_start_galaxy = FLEET0.fleet_start_galaxy AND
519
        FLEET4.fleet_start_system = FLEET0.fleet_start_system AND
520
        FLEET4.fleet_start_planet = FLEET0.fleet_start_planet
521
      " .
522
      // Блокировка всех юнитов, принадлежащих этим флотам
523
      "LEFT JOIN {{unit}} as UNIT4 ON
524
        UNIT4.unit_location_type = " . LOC_FLEET . " AND
525
        UNIT4.unit_location_id = FLEET4.fleet_id
526
      " .
527
      // Lock fleet owner
528
      "LEFT JOIN {{users}} as USER4 on
529
        USER4.id = FLEET4.fleet_owner
530
      " .
531
532
533
      // Locking start planet
534
      "LEFT JOIN {{planets}} AS PLANETS5 ON
535
        FLEET0.fleet_mess = 1 AND
536
        PLANETS5.galaxy = FLEET0.fleet_start_galaxy AND
537
        PLANETS5.system = FLEET0.fleet_start_system AND
538
        PLANETS5.planet = FLEET0.fleet_start_planet
539
      " .
540
      // Lock planet owner
541
      "LEFT JOIN {{users}} as USER5 on
542
        USER5.id = PLANETS5.id_owner
543
      " .
544
      // Блокировка всех юнитов, принадлежащих этой планете
545
      "LEFT JOIN {{unit}} as UNIT5 ON
546
        UNIT5.unit_location_type = " . LOC_PLANET . " AND
547
        UNIT5.unit_location_id = PLANETS5.id
548
      " .
549
550
551
      // Locking destination planet
552
      "LEFT JOIN {{planets}} AS PLANETS6 ON
553
        FLEET0.fleet_mess = 0 AND
554
        PLANETS6.galaxy = FLEET0.fleet_end_galaxy AND
555
        PLANETS6.system = FLEET0.fleet_end_system AND
556
        PLANETS6.planet = FLEET0.fleet_end_planet
557
      " .
558
      // Lock planet owner
559
      "LEFT JOIN {{users}} as USER6 on
560
        USER6.id = PLANETS6.id_owner
561
      " .
562
      // Блокировка всех юнитов, принадлежащих этой планете
563
      "LEFT JOIN {{unit}} as UNIT6 ON
564
        UNIT6.unit_location_type = " . LOC_PLANET . " AND
565
        UNIT6.unit_location_id = PLANETS6.id
566
      " .
567
      "WHERE FLEET0.fleet_id = {$dbId} GROUP BY 1 FOR UPDATE"
568
    );
569
  }
570
571
572
  public function dbRowParse($db_row) {
573
    parent::dbRowParse($db_row); // TODO: Change the autogenerated stub
574
    $player = new Player();
575
    $player->dbLoad($db_row['fleet_owner']);
576
    $this->setLocatedAt($player);
577
  }
578
579
  /* FLEET HELPERS =====================================================================================================*/
580
  /**
581
   * Forcibly returns fleet before time outs
582
   */
583
  public function commandReturn() {
584
    $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;
585
586
    // Считаем, что флот уже долетел TODO
587
    $this->time_arrive_to_target = SN_TIME_NOW;
588
    // Убираем флот из группы
589
    $this->group_id = 0;
590
    // Отменяем работу в точке назначения
591
    $this->time_mission_job_complete = 0;
592
    // TODO - правильно вычслять время возвращения - по проделанному пути, а не по старому времени возвращения
593
    $this->time_return_to_source = $ReturnFlyingTime;
594
595
    // Записываем изменения в БД
596
    $this->markReturnedAndSave();
597
598
    if ($this->_group_id) {
599
      // TODO: Make here to delete only one AKS - by adding aks_fleet_count to AKS table
600
      DBStaticFleetACS::db_fleet_aks_purge();
601
    }
602
  }
603
604
605
  /**
606
   * @return array
607
   */
608
  public function target_coordinates_without_type() {
609
    return array(
610
      'galaxy' => $this->_fleet_end_galaxy,
611
      'system' => $this->_fleet_end_system,
612
      'planet' => $this->_fleet_end_planet,
613
    );
614
  }
615
616
  /**
617
   * @return array
618
   */
619
  public function target_coordinates_typed() {
620
    return array(
621
      'galaxy' => $this->_fleet_end_galaxy,
622
      'system' => $this->_fleet_end_system,
623
      'planet' => $this->_fleet_end_planet,
624
      'type'   => $this->_fleet_end_type,
625
    );
626
  }
627
628
  /**
629
   * @return array
630
   */
631
  public function launch_coordinates_typed() {
632
    return array(
633
      'galaxy' => $this->_fleet_start_galaxy,
634
      'system' => $this->_fleet_start_system,
635
      'planet' => $this->_fleet_start_planet,
636
      'type'   => $this->_fleet_start_type,
637
    );
638
  }
639
640
  public function isReturning() {
641
    return FLEET_FLAG_RETURNING == $this->_is_returning;
642
  }
643
644
  /**
645
   * Sets object fields for fleet return
646
   */
647
  public function markReturnedAndSave() {
648
    // TODO - Проверка - а не возвращается ли уже флот?
649
    $this->is_returning = FLEET_FLAG_RETURNING;
650
    $this->dbSave();
651
  }
652
653
  /**
654
   * Parses extended unit_array which can include not only ships but resources, captains etc
655
   *
656
   * @param $unit_array
657
   *
658
   * @throws Exception
659
   */
660
  // TODO - separate shipList and unitList
661
  public function unitsSetFromArray($unit_array) {
662
    if (empty($unit_array) || !is_array($unit_array)) {
663
      return;
664
    }
665
    foreach ($unit_array as $unit_id => $unit_count) {
666
      $unit_count = floatval($unit_count);
667
      if (!$unit_count) {
668
        continue;
669
      }
670
671
      if ($this->isShip($unit_id) || $this->isMissile($unit_id)) {
672
        $this->unitList->unitSetCount($unit_id, $unit_count);
673
      } elseif ($this->isResource($unit_id)) {
674
        $this->resource_list[$unit_id] = $unit_count;
675
      } else {
676
        throw new Exception('Trying to pass to fleet non-resource and non-ship ' . var_export($unit_array, true), FLIGHT_SHIPS_UNIT_WRONG);
677
      }
678
    }
679
  }
680
681
682
  /**
683
   * Sets fleet timers based on flight duration, time on mission (HOLD/EXPLORE) and fleet departure time.
684
   *
685
   * @param int $time_to_travel - flight duration in seconds
686
   * @param int $time_on_mission - time on mission in seconds
687
   * @param int $flight_departure - fleet departure from source planet timestamp. Allows to send fleet in future or in past
688
   */
689
  public function set_times($time_to_travel, $time_on_mission = 0, $flight_departure = SN_TIME_NOW) {
690
    $this->_time_launch = $flight_departure;
691
692
    $this->_time_arrive_to_target = $this->_time_launch + $time_to_travel;
693
    $this->_time_mission_job_complete = $time_on_mission ? $this->_time_arrive_to_target + $time_on_mission : 0;
694
    $this->_time_return_to_source = ($this->_time_mission_job_complete ? $this->_time_mission_job_complete : $this->_time_arrive_to_target) + $time_to_travel;
695
  }
696
697
698
  public function parse_missile_db_row($missile_db_row) {
699
//    $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...
700
701
    if (empty($missile_db_row) || !is_array($missile_db_row)) {
702
      return;
703
    }
704
705
//      $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...
706
//      $irak_original['fleet_start_name'] = $planet_start['name'];
707
    $this->missile_target = $missile_db_row['primaer'];
708
709
    $this->_dbId = -$missile_db_row['id'];
710
    $this->_playerOwnerId = $missile_db_row['fleet_owner'];
711
    $this->_mission_type = MT_MISSILE;
712
713
    $this->_target_owner_id = $missile_db_row['fleet_target_owner'];
714
715
    $this->_group_id = 0;
716
    $this->_is_returning = 0;
717
718
    $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...
719
    $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...
720
    $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...
721
    $this->_time_return_to_source = $missile_db_row['fleet_end_time'];
722
723
    $this->_fleet_start_planet_id = !empty($missile_db_row['fleet_start_planet_id']) ? $missile_db_row['fleet_start_planet_id'] : null;
724
    $this->_fleet_start_galaxy = $missile_db_row['fleet_start_galaxy'];
725
    $this->_fleet_start_system = $missile_db_row['fleet_start_system'];
726
    $this->_fleet_start_planet = $missile_db_row['fleet_start_planet'];
727
    $this->_fleet_start_type = $missile_db_row['fleet_start_type'];
728
729
    $this->_fleet_end_planet_id = !empty($missile_db_row['fleet_end_planet_id']) ? $missile_db_row['fleet_end_planet_id'] : null;
730
    $this->_fleet_end_galaxy = $missile_db_row['fleet_end_galaxy'];
731
    $this->_fleet_end_system = $missile_db_row['fleet_end_system'];
732
    $this->_fleet_end_planet = $missile_db_row['fleet_end_planet'];
733
    $this->_fleet_end_type = $missile_db_row['fleet_end_type'];
734
735
    $this->unitList->unitSetCount(UNIT_DEF_MISSILE_INTERPLANET, $missile_db_row['fleet_amount']);
736
  }
737
738
739
  /**
740
   * @param $from
741
   */
742
  public function set_start_planet($from) {
743
    $this->fleet_start_planet_id = intval($from['id']) ? $from['id'] : null;
744
    $this->fleet_start_galaxy = $from['galaxy'];
745
    $this->fleet_start_system = $from['system'];
746
    $this->fleet_start_planet = $from['planet'];
747
    $this->fleet_start_type = $from['planet_type'];
748
  }
749
750
  /**
751
   * @param $to
752
   */
753
  public function set_end_planet($to) {
754
    $this->target_owner_id = intval($to['id_owner']) ? $to['id_owner'] : 0;
755
    $this->fleet_end_planet_id = intval($to['id']) ? $to['id'] : null;
756
    $this->fleet_end_galaxy = $to['galaxy'];
757
    $this->fleet_end_system = $to['system'];
758
    $this->fleet_end_planet = $to['planet'];
759
    $this->fleet_end_type = $to['planet_type'];
760
  }
761
762
  /**
763
   * @param Vector $to
764
   */
765
  public function setTargetFromVectorObject($to) {
766
    $this->_fleet_end_galaxy = $to->galaxy;
767
    $this->_fleet_end_system = $to->system;
768
    $this->_fleet_end_planet = $to->planet;
769
    $this->_fleet_end_type = $to->type;
770
  }
771
772
  /**
773
   * @param array $db_row
774
   */
775
  protected function ownerExtract(array &$db_row) {
776
    $player = new Player();
777
    $player->dbLoad($db_row['fleet_owner']);
778
    $this->setLocatedAt($player);
779
  }
780
781
  /**
782
   * @param array $db_row
783
   */
784
  protected function ownerInject(array &$db_row) {
785
    $db_row['fleet_owner'] = $this->getPlayerOwnerId();
786
  }
787
788
789
790
791
  // UnitList/Ships access ***************************************************************************************************
792
793
  // TODO - перекрывать пожже - для миссайл-флотов и дефенс-флотов
794
  protected function isShip($unit_id) {
795
    return UnitShip::is_in_group($unit_id);
796
  }
797
798
  protected function isMissile($unit_id) {
799
    return isInGroup(GROUP_STR_MISSILES, $unit_id);
800
  }
801
802
  /**
803
   * Set unit count of $unit_id to $unit_count
804
   * If there is no $unit_id - it will be created and saved to DB on dbSave
805
   *
806
   * @param int $unit_id
807
   * @param int $unit_count
808
   */
809
  public function shipSetCount($unit_id, $unit_count = 0) {
810
    pdump(__CLASS__ . '->' . __FUNCTION__);
811
    $this->shipAdjustCount($unit_id, $unit_count, true);
812
  }
813
814
  /**
815
   * Adjust unit count of $unit_id by $unit_count - or just replace value
816
   * If there is no $unit_id - it will be created and saved to DB on dbSave
817
   *
818
   * @param int  $unit_id
819
   * @param int  $unit_count
820
   * @param bool $replace_value
821
   */
822
  public function shipAdjustCount($unit_id, $unit_count = 0, $replace_value = false) {
823
    $this->unitList->unitAdjustCount($unit_id, $unit_count, $replace_value);
824
  }
825
826
  public function shipGetCount($unit_id) {
827
    return $this->unitList->unitGetCount($unit_id);
828
  }
829
830
  public function shipsCountApplyLossMultiplier($ships_lost_multiplier) {
831
    $this->unitList->unitsCountApplyLossMultiplier($ships_lost_multiplier);
832
  }
833
834
  /**
835
   * Returns fleet ships cost in metal
836
   *
837
   * @param array $shipCostInMetalPerPiece
838
   *
839
   * @return float[]
840
   */
841
  public function shipsCostInMetal($shipCostInMetalPerPiece) {
842
    return $this->unitList->unitsCostInMetal($shipCostInMetalPerPiece);
843
  }
844
845
  /**
846
   * @return UnitIterator
847
   */
848
  public function shipsIterator() {
849
    return $this->unitList->getUnitIterator();
850
  }
851
852
  public function shipsGetTotal() {
853
    return $this->unitList->unitsCount();
854
  }
855
856
  public function shipsGetCapacity() {
857
    return $this->unitList->shipsCapacity();
858
  }
859
860
  public function shipsGetHoldFree() {
861
    return max(0, $this->shipsGetCapacity() - $this->resourcesGetTotal());
862
  }
863
864
  /**
865
   * Get count of ships with $ship_id
866
   *
867
   * @param int $ship_id
868
   *
869
   * @return int
870
   */
871
  public function shipsGetTotalById($ship_id) {
872
    return $this->unitList->unitsCountById($ship_id);
873
  }
874
875
  /**
876
   * Возвращает ёмкость переработчиков во флоте
877
   *
878
   * @param array $recycler_info
879
   *
880
   * @return int
881
   *
882
   */
883
  public function shipsGetCapacityRecyclers($recycler_info) {
884
    $recyclers_incoming_capacity = 0;
885
    foreach ($this->shipsIterator() as $unitId => $unit) {
886
      if (!empty(classSupernova::$gc->groupRecyclers[$unitId]) && $unit->count >= 1) {
887
        $recyclers_incoming_capacity += $unit->count * $recycler_info[$unitId]['capacity'];
888
      }
889
    }
890
891
    return $recyclers_incoming_capacity;
892
  }
893
894
  /**
895
   * @return bool
896
   */
897
  // TODO - А если не на планете????
898
  public function shipsIsEnoughOnPlanet() {
899
    return $this->unitList->shipsIsEnoughOnPlanet($this->dbOwnerRow, $this->dbSourcePlanetRow);
900
  }
901
902
  /**
903
   * @return bool
904
   */
905
  public function shipsAllPositive() {
906
    return $this->unitList->unitsPositive();
907
  }
908
909
  /**
910
   * @return bool
911
   */
912
  public function shipsAllFlying() {
913
    return $this->unitList->unitsInGroup(classSupernova::$gc->groupFleetAndMissiles);
914
  }
915
916
  /**
917
   * @return bool
918
   */
919
  public function shipsAllMovable() {
920
    return $this->unitList->unitsIsAllMovable($this->dbOwnerRow);
921
  }
922
923
  /**
924
   * Restores fleet or resources to planet
925
   *
926
   * @param bool $start
927
   * @param int  $result
928
   */
929
  // TODO - split to functions
930
  public function shipsLand($start = true) {
931
    sn_db_transaction_check(true);
932
933
    // Если флот уже обработан - не существует или возращается - тогда ничего не делаем
934
    if ($this->isEmpty()) {
935
      return;
936
    }
937
938
    $coordinates = $start ? $this->launch_coordinates_typed() : $this->target_coordinates_typed();
939
940
    // Поскольку эта функция может быть вызвана не из обработчика флотов - нам надо всё заблокировать вроде бы НЕ МОЖЕТ!!!
941
    // TODO Проверить от многократного срабатывания !!!
942
    // Тут не блокируем пока - сначала надо заблокировать пользователя, что бы не было дедлока
943
    // TODO поменять на владельца планеты - когда его будут возвращать всегда !!!
944
945
    // Узнаем ИД владельца планеты.
946
    // С блокировкой, поскольку эта функция может быть вызвана только из менеджера летящих флотов.
947
    // А там уже всё заблокировано как надо и повторная блокировка не вызовет дедлок.
948
    $planet_arrival = DBStaticPlanet::db_planet_by_vector($coordinates, '', true);
949
    // Блокируем пользователя
950
    // TODO - вообще-то нам уже известен пользователь в МЛФ - так что можно просто передать его сюда
951
    $user = DBStaticUser::db_user_by_id($planet_arrival['id_owner'], true);
952
953
    // TODO - Проверка, что планета всё еще существует на указанных координатах, а не телепортировалась, не удалена хозяином, не уничтожена врагом
954
    // Флот, который возвращается на захваченную планету, пропадает
955
    // Ship landing is possible only to fleet owner's planet
956
    if ($this->getPlayerOwnerId() == $planet_arrival['id_owner']) {
957
      // Adjusting ship amount on planet
958
      foreach ($this->shipsIterator() as $ship_id => $ship) {
959
        if ($ship->count) {
960
          DBStaticUnit::dbUpdateOrInsertUnit($ship_id, $ship->count, $user, $planet_arrival['id']);
961
        }
962
      }
963
964
      // Restoring resources to planet
965
      $this->resourcesUnload($start);
966
    }
967
968
    RestoreFleetToPlanet($this, $start);
969
970
    $this->dbDelete();
971
  }
972
973
974
  // Resources access ***************************************************************************************************
975
976
  /**
977
   * Extracts resources value from db_row
978
   *
979
   * @param array $db_row
980
   */
981
  protected function resourcesExtract(array &$db_row) {
982
    $this->resource_list = array(
983
      RES_METAL     => !empty($db_row['fleet_resource_metal']) ? floor($db_row['fleet_resource_metal']) : 0,
984
      RES_CRYSTAL   => !empty($db_row['fleet_resource_crystal']) ? floor($db_row['fleet_resource_crystal']) : 0,
985
      RES_DEUTERIUM => !empty($db_row['fleet_resource_deuterium']) ? floor($db_row['fleet_resource_deuterium']) : 0,
986
    );
987
  }
988
989
  protected function resourcesInject(array &$db_row) {
990
    $db_row['fleet_resource_metal'] = $this->resource_list[RES_METAL];
991
    $db_row['fleet_resource_crystal'] = $this->resource_list[RES_CRYSTAL];
992
    $db_row['fleet_resource_deuterium'] = $this->resource_list[RES_DEUTERIUM];
993
  }
994
995
  /**
996
   * Set current resource list from array of units
997
   *
998
   * @param array $resource_list
999
   */
1000
  public function resourcesSet($resource_list) {
1001
    if (!empty($this->propertiesAdjusted['resource_list'])) {
1002
      throw new ExceptionPropertyAccess('Property "resource_list" already was adjusted so no SET is possible until dbSave in ' . get_called_class() . '::unitSetResourceList', ERR_ERROR);
1003
    }
1004
    $this->resourcesAdjust($resource_list, true);
1005
  }
1006
1007
  /**
1008
   * Updates fleet resource list with deltas
1009
   *
1010
   * @param array $resource_delta_list
1011
   * @param bool  $replace_value
1012
   *
1013
   * @throws Exception
1014
   */
1015
  public function resourcesAdjust($resource_delta_list, $replace_value = false) {
1016
    !is_array($resource_delta_list) ? $resource_delta_list = array() : false;
1017
1018
    foreach ($resource_delta_list as $resource_id => $unit_delta) {
1019
      if (!UnitResourceLoot::is_in_group($resource_id) || !($unit_delta = floor($unit_delta))) {
1020
        // Not a resource or no resources - continuing
1021
        continue;
1022
      }
1023
1024
      if ($replace_value) {
1025
        $this->resource_list[$resource_id] = $unit_delta;
1026
      } else {
1027
        $this->resource_list[$resource_id] += $unit_delta;
1028
        // Preparing changes
1029
        $this->resource_delta[$resource_id] += $unit_delta;
1030
        $this->propertiesAdjusted['resource_list'] = 1;
1031
      }
1032
1033
      // Check for negative unit value
1034
      if ($this->resource_list[$resource_id] < 0) {
1035
        // TODO
1036
        throw new Exception('Resource ' . $resource_id . ' will become negative in ' . get_called_class() . '::unitAdjustResourceList', ERR_ERROR);
1037
      }
1038
    }
1039
  }
1040
1041
  public function resourcesGetTotal() {
1042
    return empty($this->resource_list) || !is_array($this->resource_list) ? 0 : array_sum($this->resource_list);
1043
  }
1044
1045
  /**
1046
   * @param array $rate
1047
   *
1048
   * @return float
1049
   */
1050
  public function resourcesGetTotalInMetal(array $rate) {
1051
    return
1052
      $this->resource_list[RES_METAL] * $rate[RES_METAL]
1053
      + $this->resource_list[RES_CRYSTAL] * $rate[RES_CRYSTAL] / $rate[RES_METAL]
1054
      + $this->resource_list[RES_DEUTERIUM] * $rate[RES_DEUTERIUM] / $rate[RES_METAL];
1055
  }
1056
1057
  /**
1058
   * Returns resource list in fleet
1059
   */
1060
  // TODO
1061
  public function resourcesGetList() {
1062
    return $this->resource_list;
1063
  }
1064
1065
  public function resourcesReset() {
1066
    $this->resourcesSet(array(
1067
      RES_METAL     => 0,
1068
      RES_CRYSTAL   => 0,
1069
      RES_DEUTERIUM => 0,
1070
    ));
1071
  }
1072
1073
  /**
1074
   * Restores fleet or resources to planet
1075
   *
1076
   * @param bool $start
1077
   * @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...
1078
   * @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...
1079
   */
1080
  public function resourcesUnload($start = true) {
1081
    sn_db_transaction_check(true);
1082
1083
    // Если флот уже обработан - не существует или возращается - тогда ничего не делаем
1084
    if (!$this->resourcesGetTotal()) {
1085
      return;
1086
    }
1087
1088
    $coordinates = $start ? $this->launch_coordinates_typed() : $this->target_coordinates_typed();
1089
1090
    // Поскольку эта функция может быть вызвана не из обработчика флотов - нам надо всё заблокировать вроде бы НЕ МОЖЕТ!!!
1091
    // TODO Проверить от многократного срабатывания !!!
1092
    // Тут не блокируем пока - сначала надо заблокировать пользователя, что бы не было дедлока
1093
    // TODO поменять на владельца планеты - когда его будут возвращать всегда !!!
1094
1095
1096
    // Узнаем ИД владельца планеты.
1097
    // С блокировкой, поскольку эта функция может быть вызвана только из менеджера летящих флотов.
1098
    // А там уже всё заблокировано как надо и повторная блокировка не вызовет дедлок.
1099
    $planet_arrival = DBStaticPlanet::db_planet_by_vector($coordinates, '', true);
1100
1101
    // TODO - Проверка, что планета всё еще существует на указанных координатах, а не телепортировалась, не удалена хозяином, не уничтожена врагом
1102
1103
    // Restoring resources to planet
1104
    if ($this->resourcesGetTotal()) {
1105
      $fleet_resources = $this->resourcesGetList();
1106
      DBStaticPlanet::db_planet_update_adjust_by_id(
1107
        $planet_arrival['id'],
1108
        array(
1109
          'metal'     => +$fleet_resources[RES_METAL],
1110
          'crystal'   => +$fleet_resources[RES_CRYSTAL],
1111
          'deuterium' => +$fleet_resources[RES_DEUTERIUM],
1112
        )
1113
      );
1114
    }
1115
1116
    $this->resourcesReset();
1117
  }
1118
1119
1120
  protected function isResource($unit_id) {
1121
    return UnitResourceLoot::is_in_group($unit_id);
1122
  }
1123
1124
  /**
1125
   * @param int $speed_percent
1126
   *
1127
   * @return array
1128
   */
1129
  protected function flt_travel_data($speed_percent = 10) {
1130
    $distance = $this->targetVector->distanceFromCoordinates($this->dbSourcePlanetRow);
1131
1132
    return $this->unitList->travelData($speed_percent, $distance, $this->dbOwnerRow);
1133
  }
1134
1135
1136
  /**
1137
   * @param array  $dbPlayerRow
1138
   * @param array  $dbPlanetRow
1139
   * @param Vector $targetVector
1140
   *
1141
   */
1142
  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...
1143
    $objFleet5Player = new Player();
1144
    $objFleet5Player->dbRowParse($dbPlayerRow);
1145
    $this->setLocatedAt($objFleet5Player);
1146
1147
    $this->mission_type = $mission;
1148
1149
    $this->dbOwnerRow = $dbPlayerRow;
1150
1151
    $this->set_start_planet($dbPlanetRow);
1152
    $this->dbSourcePlanetRow = $dbPlanetRow;
1153
1154
    $this->setTargetFromVectorObject($targetVector);
1155
    $this->targetVector = $targetVector;
1156
1157
//    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...
1158
//      $this->restrictTargetTypeByMission();
1159
//
1160
//      // TODO - Нельзя тут просто менять тип планеты или координат!
1161
//      // If current planet type is not allowed on mission - switch planet type
1162
//      if (empty($this->allowed_planet_types[$this->targetVector->type])) {
1163
//        $targetPlanetCoords->type = reset($this->allowed_planet_types);
1164
//      }
1165
//    }
1166
1167
    $this->populateTargetPlanetAndOwner();
1168
1169
    $this->unitsSetFromArray($ships);
1170
1171
    $this->_group_id = intval($fleet_group_mr);
1172
1173
    $this->oldSpeedInTens = $oldSpeedInTens;
1174
1175
    $this->targetedUnitId = $targetedUnitId;
1176
1177
    $this->captainId = $captainId;
1178
1179
    $this->_time_launch = SN_TIME_NOW;
1180
1181
    $this->renderParamCoordinates();
1182
1183
  }
1184
1185
  protected function restrictTargetTypeByMission() {
1186
    if ($this->_mission_type == MT_MISSILE) {
1187
      $this->allowed_planet_types = array(PT_PLANET => PT_PLANET);
1188
    } elseif ($this->_mission_type == MT_COLONIZE || $this->_mission_type == MT_EXPLORE) {
1189
      // TODO - PT_NONE
1190
      $this->allowed_planet_types = array(PT_PLANET => PT_PLANET);
1191
    } elseif ($this->_mission_type == MT_RECYCLE) {
1192
      $this->allowed_planet_types = array(PT_DEBRIS => PT_DEBRIS);
1193
    } elseif ($this->_mission_type == MT_DESTROY) {
1194
      $this->allowed_planet_types = array(PT_MOON => PT_MOON);
1195
    } else {
1196
      $this->allowed_planet_types = array(PT_PLANET => PT_PLANET, PT_MOON => PT_MOON);
1197
    }
1198
  }
1199
1200
  protected function populateTargetPlanetAndOwner() {
1201
    // If vector points to no exact object OR debris - then getting planet on coordinates
1202
    $targetVector = clone $this->targetVector;
1203
    if ($targetVector->type == PT_DEBRIS || $targetVector == PT_NONE) {
1204
      $targetVector->type = PT_PLANET;
1205
    }
1206
1207
    $this->dbTargetRow = DBStaticPlanet::db_planet_by_vector_object($targetVector);
1208 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...
1209
      $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...
1210
    }
1211
  }
1212
1213
1214
  protected function printErrorIfNoShips() {
1215
    if ($this->unitList->unitsCount() <= 0) {
1216
      message(classLocale::$lang['fl_err_no_ships'], classLocale::$lang['fl_error'], 'fleet' . DOT_PHP_EX, 5);
1217
    }
1218
  }
1219
1220
  /**
1221
   */
1222
  public function renderParamCoordinates() {
1223
    global $template_result;
1224
    $template_result += array(
1225
      'thisgalaxy'      => $this->dbSourcePlanetRow['galaxy'],
1226
      'thissystem'      => $this->dbSourcePlanetRow['system'],
1227
      'thisplanet'      => $this->dbSourcePlanetRow['planet'],
1228
      'thisplanet_type' => $this->dbSourcePlanetRow['planet_type'],
1229
1230
      'galaxy'         => $this->targetVector->galaxy,
1231
      'system'         => $this->targetVector->system,
1232
      'planet'         => $this->targetVector->planet,
1233
      'planet_type'    => $this->targetVector->type,
1234
      'target_mission' => $this->_mission_type,
1235
      'MISSION_NAME'   => $this->_mission_type ? classLocale::$lang['type_mission'][$this->_mission_type] : '',
1236
1237
      'MT_COLONIZE' => MT_COLONIZE,
1238
    );
1239
  }
1240
1241
1242
  protected function renderFleetCoordinates($missionStartTimeStamp = SN_TIME_NOW, $timeMissionJob = 0) {
1243
    $timeToReturn = $this->travelData['duration'] * 2 + $timeMissionJob;
1244
1245
    return array(
1246
      'ID'                 => 1,
1247
      'START_TYPE_TEXT_SH' => classLocale::$lang['sys_planet_type_sh'][$this->dbSourcePlanetRow['planet_type']],
1248
      'START_COORDS'       => uni_render_coordinates($this->dbSourcePlanetRow),
1249
      'START_NAME'         => $this->dbSourcePlanetRow['name'],
1250
      'START_TIME_TEXT'    => date(FMT_DATE_TIME, $missionStartTimeStamp + $timeToReturn + SN_CLIENT_TIME_DIFF),
1251
      'START_LEFT'         => floor($timeToReturn),
1252
      'END_TYPE_TEXT_SH'   =>
1253
        !empty($this->targetVector->type)
1254
          ? classLocale::$lang['sys_planet_type_sh'][$this->targetVector->type]
1255
          : '',
1256
      'END_COORDS'         => uniRenderVector($this->targetVector),
1257
      'END_NAME'           => !empty($this->dbTargetRow['name']) ? $this->dbTargetRow['name'] : '',
1258
      'END_TIME_TEXT'      => date(FMT_DATE_TIME, $missionStartTimeStamp + $this->travelData['duration'] + SN_CLIENT_TIME_DIFF),
1259
      'END_LEFT'           => floor($this->travelData['duration']),
1260
    );
1261
  }
1262
1263
  /**
1264
   * @param int $missionStartTimeStamp
1265
   * @param int $timeMissionJob
1266
   *
1267
   * @return array
1268
   *
1269
   * @throws Exception
1270
   */
1271
  protected function renderFleet($missionStartTimeStamp = SN_TIME_NOW, $timeMissionJob = 0) {
1272
    $this->printErrorIfNoShips();
1273
1274
    $result = $this->renderFleetCoordinates($missionStartTimeStamp, $timeMissionJob);
1275
    $result['.']['ships'] = $this->unitList->unitsRender();
1276
1277
    return $result;
1278
  }
1279
1280
  /**
1281
   * @return array
1282
   */
1283
  protected function renderAllowedMissions() {
1284
    $result = array();
1285
1286
    ksort($this->allowed_missions);
1287
    // If mission is not set - setting first mission from allowed
1288
    if (empty($this->_mission_type) && is_array($this->allowed_missions)) {
1289
      reset($this->allowed_missions);
1290
      $this->_mission_type = key($this->allowed_missions);
1291
    }
1292
    foreach ($this->allowed_missions as $key => $value) {
1293
      $result[] = array(
1294
        'ID'   => $key,
1295
        'NAME' => classLocale::$lang['type_mission'][$key],
1296
      );
1297
    };
1298
1299
    return $result;
1300
  }
1301
1302
  /**
1303
   * @param $max_duration
1304
   *
1305
   * @return array
1306
   */
1307
  protected function renderDuration($max_duration) {
1308
    $result = array();
1309
1310
    if (!$max_duration) {
1311
      return $result;
1312
    }
1313
1314
    $config_game_speed_expedition = ($this->_mission_type == MT_EXPLORE && classSupernova::$config->game_speed_expedition ? classSupernova::$config->game_speed_expedition : 1);
1315
    for ($i = 1; $i <= $max_duration; $i++) {
1316
      $result[] = array(
1317
        'ID'   => $i,
1318
        'TIME' => pretty_time(ceil($i * 3600 / $config_game_speed_expedition)),
1319
      );
1320
    }
1321
1322
    return $result;
1323
  }
1324
1325
  /**
1326
   * @param array $planetResources
1327
   *
1328
   * @return array
1329
   */
1330
  // TODO - REDO to resource_id
1331
  protected function renderPlanetResources(&$planetResources) {
1332
    $result = array();
1333
1334
    $i = 0;
1335
    foreach ($planetResources as $resource_id => $resource_amount) {
1336
      $result[] = array(
1337
        'ID'        => $i++, // $resource_id,
1338
        'ON_PLANET' => $resource_amount,
1339
        'TEXT'      => pretty_number($resource_amount),
1340
        'NAME'      => classLocale::$lang['tech'][$resource_id],
1341
      );
1342
    }
1343
1344
    return $result;
1345
  }
1346
1347
  /**
1348
   * @return array
1349
   */
1350
  protected function renderAllowedPlanetTypes() {
1351
    $result = array();
1352
1353
    foreach ($this->allowed_planet_types as $possible_planet_type_id) {
1354
      $result[] = array(
1355
        'ID'         => $possible_planet_type_id,
1356
        'NAME'       => classLocale::$lang['sys_planet_type'][$possible_planet_type_id],
1357
        'NAME_SHORT' => classLocale::$lang['sys_planet_type_sh'][$possible_planet_type_id],
1358
      );
1359
    }
1360
1361
    return $result;
1362
  }
1363
1364
1365
  protected function renderFleet1TargetSelect(&$shortcut) {
1366
    global $note_priority_classes;
1367
1368
    $name = !empty($shortcut['title']) ? $shortcut['title'] : $shortcut['name'];
1369
1370
    $result = array(
1371
      'NAME'       => $name,
1372
      'GALAXY'     => $shortcut['galaxy'],
1373
      'SYSTEM'     => $shortcut['system'],
1374
      'PLANET'     => $shortcut['planet'],
1375
      'TYPE'       => $shortcut['planet_type'],
1376
      'TYPE_PRINT' => classLocale::$lang['fl_shrtcup'][$shortcut['planet_type']],
1377
    );
1378
1379
    if (isset($shortcut['priority'])) {
1380
      $result += array(
1381
        'PRIORITY'       => $shortcut['priority'],
1382
        'PRIORITY_CLASS' => $note_priority_classes[$shortcut['priority']],
1383
      );
1384
    }
1385
1386
    if (isset($shortcut['id'])) {
1387
      $result += array(
1388
        'ID' => $shortcut['id'],
1389
      );
1390
    }
1391
1392
    return $result;
1393
  }
1394
1395
  /**
1396
   * @return array
1397
   */
1398
  protected function renderFleetShortcuts() {
1399
    $result = array();
1400
1401
    // Building list of shortcuts
1402
    $query = DBStaticNote::db_note_list_select_by_owner_and_planet($this->dbOwnerRow);
1403
    while ($row = db_fetch($query)) {
1404
      $result[] = $this->renderFleet1TargetSelect($row);
1405
    }
1406
1407
    return $result;
1408
  }
1409
1410
  /**
1411
   * Building list of own planets & moons
1412
   *
1413
   * @return array
1414
   */
1415
  protected function renderOwnPlanets() {
1416
    $result = array();
1417
1418
    $colonies = DBStaticPlanet::db_planet_list_sorted($this->dbOwnerRow);
1419
    if (count($colonies) <= 1) {
1420
      return $result;
1421
    }
1422
1423
    foreach ($colonies as $row) {
1424
      if ($row['id'] == $this->dbSourcePlanetRow['id']) {
1425
        continue;
1426
      }
1427
1428
      $result[] = $this->renderFleet1TargetSelect($row);
1429
    }
1430
1431
    return $result;
1432
  }
1433
1434
  /**
1435
   * @return array
1436
   */
1437
  protected function renderACSList() {
1438
    $result = array();
1439
1440
    $query = DBStaticFleetACS::db_acs_get_list();
1441
    while ($row = db_fetch($query)) {
1442
      $members = explode(',', $row['eingeladen']);
1443
      foreach ($members as $a => $b) {
1444
        if ($b == $this->dbOwnerRow['id']) {
1445
          $result[] = $this->renderFleet1TargetSelect($row);
1446
        }
1447
      }
1448
    }
1449
1450
    return $result;
1451
  }
1452
1453
1454
  /**
1455
   * @param $template_result
1456
   */
1457
  protected function renderShipSortOptions(&$template_result) {
1458
    foreach (classLocale::$lang['player_option_fleet_ship_sort'] as $sort_id => $sort_text) {
1459
      $template_result['.']['ship_sort_list'][] = array(
1460
        'VALUE' => $sort_id,
1461
        'TEXT'  => $sort_text,
1462
      );
1463
    }
1464
    $template_result += array(
1465
      'FLEET_SHIP_SORT'         => classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_SORT],
1466
      'FLEET_SHIP_SORT_INVERSE' => classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_SORT_INVERSE],
1467
    );
1468
  }
1469
1470
1471
  /**
1472
   *
1473
   */
1474
  public function fleetPage0() {
1475
    global $template_result;
1476
1477
    lng_include('overview');
1478
1479
    if (empty($this->dbSourcePlanetRow)) {
1480
      message(classLocale::$lang['fl_noplanetrow'], classLocale::$lang['fl_error']);
1481
    }
1482
1483
    // TODO - redo to unitlist render/unit render
1484
    $template_result['.']['ships'] = $this->renderAvailableShips($this->dbOwnerRow, $this->dbSourcePlanetRow);
1485
1486
    $this->renderShipSortOptions($template_result);
1487
1488
    /**
1489
     * @var Player $playerOwner
1490
     */
1491
    $playerOwner = $this->getLocatedAt();
1492
1493
    $template_result += array(
1494
      'FLYING_FLEETS'      => $playerOwner->fleetsFlying(),
1495
      'MAX_FLEETS'         => $playerOwner->fleetsMax(),
1496
      'FREE_FLEETS'        => $playerOwner->fleetsMax() - $playerOwner->fleetsFlying(),
1497
      'FLYING_EXPEDITIONS' => $playerOwner->expeditionsFlying(),
1498
      'MAX_EXPEDITIONS'    => $playerOwner->expeditionsMax(),
1499
      'FREE_EXPEDITIONS'   => $playerOwner->expeditionsMax() - $playerOwner->expeditionsFlying(),
1500
      'COLONIES_CURRENT'   => $playerOwner->coloniesCurrent(),
1501
      'COLONIES_MAX'       => $playerOwner->coloniesMax(),
1502
1503
      'TYPE_NAME' => classLocale::$lang['fl_planettype'][$this->targetVector->type],
1504
1505
      'speed_factor' => flt_server_flight_speed_multiplier(),
1506
1507
      'PLANET_RESOURCES' => pretty_number($this->dbSourcePlanetRow['metal'] + $this->dbSourcePlanetRow['crystal'] + $this->dbSourcePlanetRow['deuterium']),
1508
      'PLANET_DEUTERIUM' => pretty_number($this->dbSourcePlanetRow['deuterium']),
1509
1510
      'PLAYER_OPTION_FLEET_SHIP_SELECT_OLD'       => classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_SELECT_OLD],
1511
      'PLAYER_OPTION_FLEET_SHIP_HIDE_SPEED'       => classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_HIDE_SPEED],
1512
      'PLAYER_OPTION_FLEET_SHIP_HIDE_CAPACITY'    => classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_HIDE_CAPACITY],
1513
      'PLAYER_OPTION_FLEET_SHIP_HIDE_CONSUMPTION' => classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_HIDE_CONSUMPTION],
1514
    );
1515
1516
    $template = gettemplate('fleet0', true);
1517
    $template->assign_recursive($template_result);
1518
    display($template, classLocale::$lang['fl_title']);
1519
  }
1520
1521
  /**
1522
   *
1523
   */
1524
  public function fleetPage1() {
1525
    global $template_result;
1526
1527
    $template_result['.']['fleets'][] = $this->renderFleet(SN_TIME_NOW);
1528
    $template_result['.']['possible_planet_type_id'] = $this->renderAllowedPlanetTypes();
1529
    $template_result['.']['colonies'] = $this->renderOwnPlanets();
1530
    $template_result['.']['shortcut'] = $this->renderFleetShortcuts();
1531
    $template_result['.']['acss'] = $this->renderACSList();
1532
1533
    $template_result += array(
1534
      'speed_factor' => flt_server_flight_speed_multiplier(),
1535
1536
      'fleet_speed'    => $this->fleetSpeed(),
1537
      'fleet_capacity' => $this->shipsGetCapacity(),
1538
1539
      'PLANET_DEUTERIUM' => pretty_number($this->dbSourcePlanetRow['deuterium']),
1540
1541
      'PAGE_HINT' => classLocale::$lang['fl_page1_hint'],
1542
    );
1543
1544
    $template = gettemplate('fleet1', true);
1545
    $template->assign_recursive($template_result);
1546
    display($template, classLocale::$lang['fl_title']);
1547
  }
1548
1549
  public function fleetSpeed() {
1550
    $maxSpeed = array();
1551
    foreach ($this->shipsIterator() as $ship_id => $unit) {
1552 View Code Duplication
      if ($unit->count > 0 && !empty(classSupernova::$gc->groupFleetAndMissiles[$ship_id])) {
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...
1553
        $single_ship_data = get_ship_data($ship_id, $this->dbOwnerRow);
1554
        $maxSpeed[$ship_id] = $single_ship_data['speed'];
1555
      }
1556
    }
1557
1558
    return empty($maxSpeed) ? 0 : min($maxSpeed);
1559
  }
1560
1561
  /**
1562
   * @param array $planetResourcesWithoutConsumption
1563
   */
1564
  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...
1565
    $this->travelData = $this->flt_travel_data($this->oldSpeedInTens);
1566
1567
//    /**
1568
//     * @var array $allowed_missions
1569
//     */
1570
//    public $allowed_missions = array();
1571
//    /**
1572
//     * @var array $exists_missions
1573
//     */
1574
//    public $exists_missions = array();
1575
//    public $allowed_planet_types = array(
1576
//      // PT_NONE => PT_NONE,
1577
//      PT_PLANET => PT_PLANET,
1578
//      PT_MOON   => PT_MOON,
1579
//      PT_DEBRIS => PT_DEBRIS
1580
//    );
1581
1582
//    $this->exists_missions = array(
1583
////      MT_EXPLORE => MT_EXPLORE,
1584
////      MT_MISSILE => MT_MISSILE,
1585
//      MT_COLONIZE => MT_COLONIZE,
1586
//    );  // TODO
1587
    $this->allowed_missions = array();
1588
1589
    if ($this->mission_type != MT_NONE && empty($this->exists_missions[$this->mission_type])) {
1590
      throw new ExceptionFleetInvalid(FLIGHT_MISSION_UNKNOWN, FLIGHT_MISSION_UNKNOWN);
1591
    }
1592
1593
    $this->validator->validateGlobals();
1594
1595
    $validateResult = array();
1596
    foreach ($this->exists_missions as $missionType => $missionData) {
1597
//print('qwe');
1598
      $mission = \Mission\MissionFactory::build($missionType, $this);
1599
//print('wer');
1600
      $validateResult[$missionType] = $mission->validate();
1601
      if (FLIGHT_ALLOWED == $validateResult[$missionType]) {
1602
        $this->allowed_missions[$missionType] = $mission;
1603
      } else {
1604
        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...
1605
        }
1606
        unset($this->allowed_missions[$missionType]);
1607
      }
1608
    }
1609
1610
    if(empty($this->allowed_missions)) {
1611
      if($this->mission_type != MT_NONE && isset($validateResult[$this->mission_type])) {
1612
        throw new ExceptionFleetInvalid($validateResult[$this->mission_type], $validateResult[$this->mission_type]);
1613
      } else {
1614
        throw new ExceptionFleetInvalid(FLIGHT_MISSION_IMPOSSIBLE, FLIGHT_MISSION_IMPOSSIBLE);
1615
      }
1616
    }
1617
1618
//    $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...
1619
  }
1620
1621
  /**
1622
   * @param array $planetResourcesWithoutConsumption
1623
   */
1624
  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...
1625
    $this->travelData = $this->flt_travel_data($this->oldSpeedInTens);
1626
1627
    if (empty($this->exists_missions[$this->mission_type])) {
1628
      throw new ExceptionFleetInvalid(FLIGHT_MISSION_UNKNOWN, FLIGHT_MISSION_UNKNOWN);
1629
    }
1630
1631
    $this->validator->validateGlobals();
1632
1633
    $mission = \Mission\MissionFactory::build($this->mission_type, $this);
1634
    $result = $mission->validate();
1635
    if (FLIGHT_ALLOWED != $result) {
1636
      throw new ExceptionFleetInvalid($result, $result);
1637
    }
1638
1639
  }
1640
1641
  /**
1642
   *
1643
   */
1644
  public function fleetPage2() {
1645
    global $template_result;
1646
1647
    $planetResourcesTotal = DBStaticPlanet::getResources($this->dbOwnerRow, $this->dbSourcePlanetRow);
1648
    $planetResourcesWithoutConsumption = $this->resourcesSubstractConsumption($planetResourcesTotal);
1649
1650
    try {
1651
      $this->fleetPage2Prepare($planetResourcesWithoutConsumption);
1652
    } catch (Exception $e) {
1653
      // TODO - MESSAGE BOX
1654 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...
1655
        sn_db_transaction_rollback();
1656
        pdie(classLocale::$lang['fl_attack_error'][$e->getCode()]);
1657
      } else {
1658
        throw $e;
1659
      }
1660
    }
1661
1662
    // Flight allowed here
1663
    pdump('FLIGHT_ALLOWED', FLIGHT_ALLOWED);
1664
//    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...
1665
1666
    $template_result['.']['missions'] = $this->renderAllowedMissions();
1667
1668
    $template_result['.']['fleets'][] = $this->renderFleet(SN_TIME_NOW);
1669
1670
    $max_duration =
1671
      $this->_mission_type == MT_EXPLORE
1672
        ? get_player_max_expedition_duration($this->dbOwnerRow)
1673
        : (isset($this->allowed_missions[MT_HOLD]) ? 12 : 0);
1674
    $template_result['.']['duration'] = $this->renderDuration($max_duration);
1675
1676
    $this->captainGet();
1677
    $template_result += $this->renderCaptain();
1678
1679
    $template_result['.']['resources'] = $this->renderPlanetResources($planetResourcesWithoutConsumption);
1680
1681
    $template_result += array(
1682
      'planet_metal'     => $planetResourcesWithoutConsumption[RES_METAL],
1683
      'planet_crystal'   => $planetResourcesWithoutConsumption[RES_CRYSTAL],
1684
      'planet_deuterium' => $planetResourcesWithoutConsumption[RES_DEUTERIUM],
1685
1686
      'fleet_capacity' => $this->shipsGetCapacity() - $this->travelData['consumption'],
1687
      'speed'          => $this->oldSpeedInTens,
1688
      'fleet_group'    => $this->_group_id,
1689
1690
      'MAX_DURATION'          => $max_duration,
1691
1692
      // 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...
1693
//      'IS_TRANSPORT_MISSIONS' => !empty($this->allowed_missions[$this->_mission_type]['transport']),
1694
      'IS_TRANSPORT_MISSIONS' => true,
1695
1696
      'PLAYER_COLONIES_CURRENT' => get_player_current_colonies($this->dbOwnerRow),
1697
      'PLAYER_COLONIES_MAX'     => get_player_max_colonies($this->dbOwnerRow),
1698
    );
1699
1700
    $template = gettemplate('fleet2', true);
1701
    $template->assign_recursive($template_result);
1702
    display($template, classLocale::$lang['fl_title']);
1703
  }
1704
1705
  /**
1706
   *
1707
   */
1708
  public function fleetPage3() {
1709
    global $template_result;
1710
1711
    $this->isRealFlight = true;
1712
1713
    sn_db_transaction_start();
1714
1715
    DBStaticUser::db_user_lock_with_target_owner_and_acs($this->dbOwnerRow, $this->dbTargetRow);
1716
1717
    // Checking for group
1718
    $this->groupCheck();
1719
1720
    $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...
1721
    $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...
1722
    if (!empty($this->dbTargetRow['id'])) {
1723
      $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...
1724
    }
1725
    // TODO - deprecated! Filled in populateTargetPlanetAndOwner
1726 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...
1727
      $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...
1728
    }
1729
1730
    $this->resource_list = array(
1731
      RES_METAL     => max(0, floor(sys_get_param_float('resource0'))),
1732
      RES_CRYSTAL   => max(0, floor(sys_get_param_float('resource1'))),
1733
      RES_DEUTERIUM => max(0, floor(sys_get_param_float('resource2'))),
1734
    );
1735
1736
    $this->captainGet();
1737
1738
    $this->travelData = $this->flt_travel_data($this->oldSpeedInTens);
1739
1740
    $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...
1741
    $planetResourcesWithoutConsumption = $this->resourcesSubstractConsumption($planetResourcesTotal);
1742
1743
    try {
1744
      $this->fleetPage3Prepare($planetResourcesWithoutConsumption);
1745
    } catch (Exception $e) {
1746
      // TODO - MESSAGE BOX
1747 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...
1748
        sn_db_transaction_rollback();
1749
        pdie(classLocale::$lang['fl_attack_error'][$e->getCode()]);
1750
      } else {
1751
        throw $e;
1752
      }
1753
    }
1754
1755
//    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...
1756
//      $validator = new FleetValidator($this);
1757
//      $validator->validate();
1758
//    } catch (Exception $e) {
1759
//      // TODO - MESSAGE BOX
1760
//      if($e instanceof Exception\ExceptionFleetInvalid) {
1761
//        sn_db_transaction_rollback();
1762
//        pdie(classLocale::$lang['fl_attack_error'][$e->getCode()]);
1763
//      } else {
1764
//        throw $e;
1765
//      }
1766
//    }
1767
1768
    // TODO - check if mission is not 0 and in ALLOWED_MISSIONS
1769
1770
    // Flight allowed here
1771
    pdump('FLIGHT_ALLOWED', FLIGHT_ALLOWED);
1772
//    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...
1773
1774
1775
    $timeMissionJob = 0;
1776
    // TODO check for empty mission AKA mission allowed
1777
    /*
1778
        if ($this->_mission_type == MT_ACS && $aks) {
1779
          $acsTimeToArrive = $aks['ankunft'] - SN_TIME_NOW;
1780
          if ($acsTimeToArrive < $this->travelData['duration']) {
1781
            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']);
1782
          }
1783
          // Set time to travel to ACS' TTT
1784
          $this->travelData['duration'] = $acsTimeToArrive;
1785
    */
1786
    if ($this->_mission_type != MT_ACS) {
1787
      if ($this->_mission_type == MT_EXPLORE || $this->_mission_type == MT_HOLD) {
1788
        $max_duration = $this->_mission_type == MT_EXPLORE ? get_player_max_expedition_duration($this->dbOwnerRow) : ($this->_mission_type == MT_HOLD ? 12 : 0);
1789
        if ($max_duration) {
1790
          $mission_time_in_hours = sys_get_param_id('missiontime');
1791
          if ($mission_time_in_hours > $max_duration || $mission_time_in_hours < 1) {
1792
            classSupernova::$debug->warning('Supplying wrong mission time', 'Hack attempt', 302, array('base_dump' => true));
1793
            die();
1794
          }
1795
          $timeMissionJob = ceil($mission_time_in_hours * 3600 / ($this->_mission_type == MT_EXPLORE && classSupernova::$config->game_speed_expedition ? classSupernova::$config->game_speed_expedition : 1));
1796
        }
1797
      }
1798
    }
1799
1800
    //
1801
    //
1802
    //
1803
    //
1804
    //
1805
    //
1806
    //
1807
    //
1808
    // ---------------- END OF CHECKS ------------------------------------------------------
1809
1810
    $this->set_times($this->travelData['duration'], $timeMissionJob);
1811
    $this->dbInsert();
1812
    $this->unitList->dbSubstractUnitsFromPlanet($this->dbOwnerRow, $this->dbSourcePlanetRow['id']);
1813
1814
    DBStaticPlanet::db_planet_update_adjust_by_id(
1815
      $this->dbSourcePlanetRow['id'],
1816
      array(
1817
        'metal'     => -$this->resource_list[RES_METAL],
1818
        'crystal'   => -$this->resource_list[RES_CRYSTAL],
1819
        'deuterium' => -$this->resource_list[RES_DEUTERIUM] - $this->travelData['consumption'],
1820
      )
1821
    );
1822
1823
    if (!empty($this->captain['unit_id'])) {
1824
      DBStaticUnit::db_unit_set_by_id(
1825
        $this->captain['unit_id'],
1826
        array(
1827
          'unit_location_type' => LOC_FLEET,
1828
          'unit_location_id'   => $this->_dbId,
1829
        ),
1830
        array()
1831
      );
1832
    }
1833
1834
//    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...
1835
//
1836
//    // Set time to travel to ACS' TTT
1837
//    $this->fleet->travelData['duration'] = $acsTimeToArrive;
1838
1839
1840
    $template_result['.']['fleets'][] = $this->renderFleet(SN_TIME_NOW, $timeMissionJob);
1841
1842
    $template_result += array(
1843
      'mission'         => classLocale::$lang['type_mission'][$this->_mission_type] . ($this->_mission_type == MT_EXPLORE || $this->_mission_type == MT_HOLD ? ' ' . pretty_time($timeMissionJob) : ''),
1844
      'dist'            => pretty_number($this->travelData['distance']),
1845
      'speed'           => pretty_number($this->travelData['fleet_speed']),
1846
      'deute_need'      => pretty_number($this->travelData['consumption']),
1847
      'from'            => "{$this->dbSourcePlanetRow['galaxy']}:{$this->dbSourcePlanetRow['system']}:{$this->dbSourcePlanetRow['planet']}",
1848
      'time_go'         => date(FMT_DATE_TIME, $this->_time_arrive_to_target),
1849
      'time_go_local'   => date(FMT_DATE_TIME, $this->_time_arrive_to_target + SN_CLIENT_TIME_DIFF),
1850
      'time_back'       => date(FMT_DATE_TIME, $this->_time_return_to_source),
1851
      'time_back_local' => date(FMT_DATE_TIME, $this->_time_return_to_source + SN_CLIENT_TIME_DIFF),
1852
    );
1853
1854
    $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...
1855
1856
    pdie('Stop for debug');
1857
1858
    sn_db_transaction_commit();
1859
1860
    $template = gettemplate('fleet3', true);
1861
    $template->assign_recursive($template_result);
1862
    display($template, classLocale::$lang['fl_title']);
1863
  }
1864
1865
  protected function groupCheck() {
1866
    if (empty($this->_group_id)) {
1867
      return;
1868
    }
1869
1870
    // ACS attack must exist (if acs fleet has arrived this will also return false (2 checks in 1!!!)
1871
    $this->acs = DBStaticFleetACS::db_acs_get_by_group_id($this->_group_id);
1872
    if (empty($this->acs)) {
1873
      $this->_group_id = 0;
1874
    } else {
1875
      $this->targetVector->convertToVector($this->acs);
1876
    }
1877
  }
1878
1879
  /**
1880
   * @param array $planetResources
1881
   *
1882
   * @return array
1883
   */
1884
  protected function resourcesSubstractConsumption($planetResources) {
1885
    !isset($planetResources[RES_DEUTERIUM]) ? $planetResources[RES_DEUTERIUM] = 0 : false;
1886
1887
    if ($this->travelData['consumption'] >= 0) {
1888
      $planetResources[RES_DEUTERIUM] -= ceil($this->travelData['consumption']);
1889
    }
1890
1891
    return $planetResources;
1892
  }
1893
1894
  /**
1895
   */
1896
  public function captainGet() {
1897
    $this->captain = array();
1898
1899
    /**
1900
     * @var unit_captain $moduleCaptain
1901
     */
1902
    if (sn_module::isModuleActive('unit_captain')) {
1903
      $moduleCaptain = sn_module::getModule('unit_captain');
1904
      $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...
1905
    }
1906
  }
1907
1908
  /**
1909
   * @return array
1910
   */
1911
  protected function renderCaptain() {
1912
    $result = array();
1913
1914
    if (!empty($this->captain['unit_id']) && $this->captain['unit_location_type'] == LOC_PLANET) {
1915
      $result = array(
1916
        'CAPTAIN_ID'     => $this->captain['unit_id'],
1917
        'CAPTAIN_LEVEL'  => $this->captain['captain_level'],
1918
        'CAPTAIN_SHIELD' => $this->captain['captain_shield'],
1919
        'CAPTAIN_ARMOR'  => $this->captain['captain_armor'],
1920
        'CAPTAIN_ATTACK' => $this->captain['captain_attack'],
1921
      );
1922
    }
1923
1924
    return $result;
1925
  }
1926
1927
}
1928