Completed
Push — work-fleets ( 0d1d7f...d58328 )
by SuperNova.WS
06:06
created

Fleet   F

Complexity

Total Complexity 203

Size/Duplication

Total Lines 1798
Duplicated Lines 1 %

Coupling/Cohesion

Components 1
Dependencies 21

Test Coverage

Coverage 0%

Importance

Changes 50
Bugs 5 Features 0
Metric Value
c 50
b 5
f 0
dl 18
loc 1798
rs 0.6314
ccs 0
cts 866
cp 0
wmc 203
lcom 1
cbo 21

75 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 10 2
B renderAvailableShips() 0 30 4
A isEmpty() 0 3 2
A dbInsert() 0 9 2
C dbLockFlying() 0 39 13
B dbGetLockById() 0 112 1
A dbRowParse() 0 6 1
B commandReturn() 0 22 4
A target_coordinates_without_type() 0 7 1
A target_coordinates_typed() 0 8 1
A launch_coordinates_typed() 0 8 1
A markReturned() 0 4 1
A isReturning() 0 3 1
A markReturnedAndSave() 0 4 1
B unitsSetFromArray() 0 19 7
A set_times() 0 7 3
B parse_missile_db_row() 0 39 5
A set_start_planet() 0 7 2
A set_end_planet() 0 8 3
A setTargetFromVectorObject() 0 6 1
A ownerExtract() 0 5 1
A ownerInject() 0 3 1
A isShip() 0 3 1
A shipSetCount() 0 4 1
A shipAdjustCount() 0 3 1
A shipGetCount() 0 3 1
A shipsCountApplyLossMultiplier() 0 3 1
A shipsCostInMetal() 0 3 1
A shipsIterator() 0 3 1
A shipsGetTotal() 0 3 1
A shipsGetCapacity() 0 3 1
A shipsGetHoldFree() 0 3 1
A shipsGetTotalById() 0 3 1
A shipsGetCapacityRecyclers() 0 10 4
A shipsIsEnoughOnPlanet() 0 3 1
A shipsAllPositive() 0 3 1
A shipsAllFlying() 0 3 1
A shipsAllMovable() 0 3 1
C shipsLand() 0 52 8
A resourcesExtract() 0 7 4
A resourcesInject() 0 5 1
A resourcesSet() 0 6 2
C resourcesAdjust() 0 25 7
A resourcesGetTotal() 0 3 3
A resourcesGetTotalInMetal() 0 6 1
A resourcesGetList() 0 3 1
A resourcesReset() 0 7 1
B resourcesUnload() 0 37 5
A isResource() 0 3 1
A flt_travel_data() 0 5 1
B initDefaults() 0 32 1
B restrictTargetTypeByMission() 0 14 6
A populateTargetPlanet() 0 14 3
A printErrorIfNoShips() 0 5 2
A renderParamCoordinates() 0 18 2
A renderFleetCoordinates() 0 20 3
A renderFleet() 0 8 1
A renderAllowedMissions() 0 18 4
B renderDuration() 0 17 5
A renderPlanetResources() 0 15 2
A renderAllowedPlanetTypes() 0 13 2
B renderFleet1TargetSelect() 0 29 4
A renderFleetShortcuts() 0 11 2
A renderOwnPlanets() 0 18 4
A renderACSList() 0 15 4
A renderShipSortOptions() 0 12 2
B fleetPage0() 0 46 2
B fleetPage1() 0 24 1
B fleetSpeed() 0 11 5
B fleetPage2() 6 60 5
F fleetPage3() 12 130 18
A groupCheck() 0 13 3
A resourcesGetOnPlanet() 0 10 3
A captainGet() 0 16 4
A renderCaptain() 0 15 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Fleet often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Fleet, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * Class Fleet
5
 *
6
 * @property int dbId
7
 * @property int playerOwnerId
8
 * @property int group_id
9
 * @property int mission_type
10
 * @property int target_owner_id
11
 * @property int is_returning
12
 *
13
 * @property int time_launch
14
 * @property int time_arrive_to_target
15
 * @property int time_mission_job_complete
16
 * @property int time_return_to_source
17
 *
18
 * @property int fleet_start_planet_id
19
 * @property int fleet_start_galaxy
20
 * @property int fleet_start_system
21
 * @property int fleet_start_planet
22
 * @property int fleet_start_type
23
 *
24
 * @property int fleet_end_planet_id
25
 * @property int fleet_end_galaxy
26
 * @property int fleet_end_system
27
 * @property int fleet_end_planet
28
 * @property int fleet_end_type
29
 *
30
 */
31
class Fleet extends UnitContainer {
32
33
  // DBRow inheritance *************************************************************************************************
34
35
  /**
36
   * Table name in DB
37
   *
38
   * @var string
39
   */
40
  protected static $_table = 'fleets';
41
  /**
42
   * Name of ID field in DB
43
   *
44
   * @var string
45
   */
46
  protected static $_dbIdFieldName = 'fleet_id';
47
  /**
48
   * DB_ROW to Class translation scheme
49
   *
50
   * @var array
51
   */
52
  protected static $_properties = array(
53
    'dbId'          => array(
54
      P_DB_FIELD => 'fleet_id',
55
    ),
56
    'playerOwnerId' => array(
57
      P_METHOD_EXTRACT => 'ownerExtract',
58
      P_METHOD_INJECT  => 'ownerInject',
59
//      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...
60
    ),
61
    'mission_type'  => array(
62
      P_DB_FIELD   => 'fleet_mission',
63
      P_FUNC_INPUT => 'intval',
64
    ),
65
66
    'target_owner_id' => array(
67
      P_DB_FIELD => 'fleet_target_owner',
68
    ),
69
    'group_id'        => array(
70
      P_DB_FIELD => 'fleet_group',
71
    ),
72
    'is_returning'    => array(
73
      P_DB_FIELD   => 'fleet_mess',
74
      P_FUNC_INPUT => 'intval',
75
    ),
76
77
    'shipCount' => array(
78
      P_DB_FIELD  => 'fleet_amount',
79
// 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...
80
//      P_FUNC_OUTPUT => 'get_ship_count',
81
//      P_DB_FIELDS_LINKED => array(
82
//        'fleet_amount',
83
//      ),
84
      P_READ_ONLY => true,
85
    ),
86
87
    'time_launch' => array(
88
      P_DB_FIELD => 'start_time',
89
    ),
90
91
    'time_arrive_to_target'     => array(
92
      P_DB_FIELD => 'fleet_start_time',
93
    ),
94
    'time_mission_job_complete' => array(
95
      P_DB_FIELD => 'fleet_end_stay',
96
    ),
97
    'time_return_to_source'     => array(
98
      P_DB_FIELD => 'fleet_end_time',
99
    ),
100
101
    'fleet_start_planet_id' => array(
102
      P_DB_FIELD   => 'fleet_start_planet_id',
103
      P_FUNC_INPUT => 'nullIfEmpty',
104
    ),
105
106
    'fleet_start_galaxy' => array(
107
      P_DB_FIELD => 'fleet_start_galaxy',
108
    ),
109
    'fleet_start_system' => array(
110
      P_DB_FIELD => 'fleet_start_system',
111
    ),
112
    'fleet_start_planet' => array(
113
      P_DB_FIELD => 'fleet_start_planet',
114
    ),
115
    'fleet_start_type'   => array(
116
      P_DB_FIELD => 'fleet_start_type',
117
    ),
118
119
    'fleet_end_planet_id' => array(
120
      P_DB_FIELD   => 'fleet_end_planet_id',
121
      P_FUNC_INPUT => 'nullIfEmpty',
122
    ),
123
    'fleet_end_galaxy'    => array(
124
      P_DB_FIELD => 'fleet_end_galaxy',
125
    ),
126
    'fleet_end_system'    => array(
127
      P_DB_FIELD => 'fleet_end_system',
128
    ),
129
    'fleet_end_planet'    => array(
130
      P_DB_FIELD => 'fleet_end_planet',
131
    ),
132
    'fleet_end_type'      => array(
133
      P_DB_FIELD => 'fleet_end_type',
134
    ),
135
136
    'resource_list' => array(
137
      P_METHOD_EXTRACT   => 'resourcesExtract',
138
      P_METHOD_INJECT    => 'resourcesInject',
139
      P_DB_FIELDS_LINKED => array(
140
        'fleet_resource_metal',
141
        'fleet_resource_crystal',
142
        'fleet_resource_deuterium',
143
      ),
144
    ),
145
  );
146
147
148
  // UnitContainer inheritance *****************************************************************************************
149
  /**
150
   * Type of this location
151
   *
152
   * @var int $locationType
153
   */
154
  protected static $locationType = LOC_FLEET;
155
156
157
  // New properties ****************************************************************************************************
158
  public static $snGroupFleet = array();
159
  public static $snGroupFleetAndMissiles = array();
160
  public static $snGroupRecyclers = array();
161
162
  /**
163
   * `fleet_owner`
164
   *
165
   * @var int
166
   */
167
  protected $_playerOwnerId = 0;
168
  /**
169
   * `fleet_group`
170
   *
171
   * @var int
172
   */
173
  protected $_group_id = 0;
174
  public $acs = array();
175
176
  /**
177
   * `fleet_mission`
178
   *
179
   * @var int
180
   */
181
  protected $_mission_type = 0;
182
183
  /**
184
   * `fleet_target_owner`
185
   *
186
   * @var int
187
   */
188
  protected $_target_owner_id = null;
189
190
  /**
191
   * @var array
192
   */
193
  public $resource_list = array(
194
    RES_METAL     => 0,
195
    RES_CRYSTAL   => 0,
196
    RES_DEUTERIUM => 0,
197
  );
198
199
200
  /**
201
   * `fleet__mess` - Флаг возвращающегося флота
202
   *
203
   * @var int
204
   */
205
  protected $_is_returning = 0;
206
  /**
207
   * `start_time` - Время отправления - таймштамп взлёта флота из точки отправления
208
   *
209
   * @var int $_time_launch
210
   */
211
  protected $_time_launch = 0; // `start_time` = SN_TIME_NOW
212
  /**
213
   * `fleet_start_time` - Время прибытия в точку миссии/время начала выполнения миссии
214
   *
215
   * @var int $_time_arrive_to_target
216
   */
217
  protected $_time_arrive_to_target = 0; // `fleet_start_time` = SN_TIME_NOW + $time_travel
218
  /**
219
   * `fleet_end_stay` - Время окончания миссии в точке назначения
220
   *
221
   * @var int $_time_mission_job_complete
222
   */
223
  protected $_time_mission_job_complete = 0; // `fleet_end_stay`
224
  /**
225
   * `fleet_end_time` - Время возвращения флота после окончания миссии
226
   *
227
   * @var int $_time_return_to_source
228
   */
229
  protected $_time_return_to_source = 0; // `fleet_end_time`
230
231
232
  protected $_fleet_start_planet_id = null;
233
  protected $_fleet_start_galaxy = 0;
234
  protected $_fleet_start_system = 0;
235
  protected $_fleet_start_planet = 0;
236
  protected $_fleet_start_type = PT_ALL;
237
238
  protected $_fleet_end_planet_id = null;
239
  protected $_fleet_end_galaxy = 0;
240
  protected $_fleet_end_system = 0;
241
  protected $_fleet_end_planet = 0;
242
  protected $_fleet_end_type = PT_ALL;
243
244
  // Missile properties
245
  public $missile_target = 0;
246
247
  // Fleet event properties
248
  public $fleet_start_name = '';
249
  public $fleet_end_name = '';
250
  public $ov_label = '';
251
  public $ov_this_planet = '';
252
  public $event_time = 0;
253
254
  protected $resource_delta = array();
255
  protected $resource_replace = array();
256
257
258
//
259
260
261
  /**
262
   * @var array $allowed_missions
263
   */
264
  public $allowed_missions = array();
265
  /**
266
   * @var array $exists_missions
267
   */
268
  public $exists_missions = array();
269
  public $allowed_planet_types = array(
270
    // PT_NONE => PT_NONE,
271
    PT_PLANET => PT_PLANET,
272
    PT_MOON   => PT_MOON,
273
    PT_DEBRIS => PT_DEBRIS
274
  );
275
276
  // TODO - Move to Player
277
  public $dbOwnerRow = array();
278
  public $dbSourcePlanetRow = array();
279
280
  /**
281
   * GSPT coordinates of target
282
   *
283
   * @var Vector
284
   */
285
  public $targetVector = array();
286
  /**
287
   * Target planet row
288
   *
289
   * @var array
290
   */
291
  public $dbTargetRow = array();
292
  public $dbTargetOwnerRow = array();
293
294
  /**
295
   * Fleet speed - old in 1/10 of 100%
296
   *
297
   * @var int
298
   */
299
  public $oldSpeedInTens = 0;
300
301
  public $tempPlayerMaxFleets = 0;
302
  public $travelData = array();
303
304
  public $isRealFlight = false;
305
306
  /**
307
   * @var int $targetedUnitId
308
   */
309
  public $targetedUnitId = 0;
310
311
  /**
312
   * @var array $captain
313
   */
314
  public $captain = array();
315
  /**
316
   * @var int $captainId
317
   */
318
  public $captainId = 0;
319
320
  /**
321
   * Fleet constructor.
322
   */
323
  public function __construct() {
324
    parent::__construct();
325
    $this->exists_missions = sn_get_groups('missions');
326
    $this->allowed_missions = $this->exists_missions;
327
    if(empty(static::$snGroupFleet)) {
328
      static::$snGroupFleet = sn_get_groups('fleet');
329
      static::$snGroupFleetAndMissiles = sn_get_groups(array('fleet', 'missile'));
330
      static::$snGroupRecyclers = sn_get_groups('flt_recyclers');
331
    }
332
  }
333
334
  /**
335
   * @param array $template_result
336
   * @param array $playerRow
337
   * @param array $planetRow
338
   */
339
  // TODO - redo to unit/unitlist renderer
340
  public function renderAvailableShips(&$template_result, $playerRow, $planetRow) {
341
    $record_index = 0;
342
    $ship_list = array();
343
    foreach (Fleet::$snGroupFleet as $n => $unit_id) {
344
      $unit_level = mrc_get_level($playerRow, $planetRow, $unit_id, false, true);
345
      if ($unit_level <= 0) {
346
        continue;
347
      }
348
      $ship_data = get_ship_data($unit_id, $playerRow);
349
      $ship_list[$unit_id] = array(
350
        '__INDEX'          => $record_index++,
351
        'ID'               => $unit_id,
352
        'NAME'             => classLocale::$lang['tech'][$unit_id],
353
        'AMOUNT'           => $unit_level,
354
        'AMOUNT_TEXT'      => pretty_number($unit_level),
355
        'CONSUMPTION'      => $ship_data['consumption'],
356
        'CONSUMPTION_TEXT' => pretty_number($ship_data['consumption']),
357
        'SPEED'            => $ship_data['speed'],
358
        'SPEED_TEXT'       => pretty_number($ship_data['speed']),
359
        'CAPACITY'         => $ship_data['capacity'],
360
        'CAPACITY_TEXT'    => pretty_number($ship_data['capacity']),
361
      );
362
    }
363
364
    sortUnitRenderedList($ship_list, classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_SORT], classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_SORT_INVERSE]);
365
366
    foreach ($ship_list as $ship_data) {
367
      $template_result['.']['ships'][] = $ship_data;
368
    }
369
  }
370
371
  public function isEmpty() {
372
    return !$this->resourcesGetTotal() && !$this->shipsGetTotal();
373
  }
374
375
//  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...
376
//    return $this->playerOwnerId;
377
//  }
378
379
  /**
380
   * Initializes Fleet from user params and posts it to DB
381
   */
382
  public function dbInsert() {
383
    // WARNING! MISSION TIMES MUST BE SET WITH set_times() method!
384
    // TODO - more checks!
385
    if (empty($this->_time_launch)) {
386
      die('Fleet time not set!');
387
    }
388
389
    parent::dbInsert();
390
  }
391
392
393
  /* FLEET DB ACCESS =================================================================================================*/
394
395
  /**
396
   * LOCK - Lock all records which can be used with mission
397
   *
398
   * @param $mission_data
399
   *
400
   * @return array|bool|mysqli_result|null
401
   */
402
  public function dbLockFlying(&$mission_data) {
403
    // Тупо лочим всех юзеров, чьи флоты летят или улетают с координат отбытия/прибытия $fleet_row
404
    // Что бы делать это умно - надо учитывать fleet__mess во $fleet_row и в таблице fleets
405
406
    $fleet_id_safe = idval($this->_dbId);
407
408
    return doquery(
409
    // Блокировка самого флота
410
      "SELECT 1 FROM {{fleets}} AS f " .
411
412
      // Блокировка всех юнитов, принадлежащих этому флоту
413
      "LEFT JOIN {{unit}} as unit ON unit.unit_location_type = " . static::$locationType . " AND unit.unit_location_id = f.fleet_id " .
414
415
      // Блокировка всех прилетающих и улетающих флотов, если нужно
416
      // TODO - lock fleets by COORDINATES
417
      ($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 " : '') .
418
      // Блокировка всех юнитов, принадлежащих прилетающим и улетающим флотам - ufd = unit_fleet_destination
419
      ($mission_data['dst_fleets'] ? "LEFT JOIN {{unit}} AS ufd ON ufd.unit_location_type = " . static::$locationType . " AND ufd.unit_location_id = fd.fleet_id " : '') .
420
421
      ($mission_data['dst_user'] || $mission_data['dst_planet'] ? "LEFT JOIN {{users}} AS ud ON ud.id = f.fleet_target_owner " : '') .
422
      // Блокировка всех юнитов, принадлежащих владельцу планеты-цели
423
      ($mission_data['dst_user'] || $mission_data['dst_planet'] ? "LEFT JOIN {{unit}} AS unit_player_dest ON unit_player_dest.unit_player_id = ud.id " : '') .
424
      // Блокировка планеты-цели
425
      ($mission_data['dst_planet'] ? "LEFT JOIN {{planets}} AS pd ON pd.id = f.fleet_end_planet_id " : '') .
426
      // Блокировка всех юнитов, принадлежащих планете-цели - НЕ НУЖНО. Уже залочили ранее, как принадлежащие игроку-цели
427
//      ($mission_data['dst_planet'] ? "LEFT JOIN {{unit}} AS upd ON upd.unit_location_type = " . LOC_PLANET . " AND upd.unit_location_id = pd.id " : '') .
428
429
430
      ($mission_data['src_user'] || $mission_data['src_planet'] ? "LEFT JOIN {{users}} AS us ON us.id = f.fleet_owner " : '') .
431
      // Блокировка всех юнитов, принадлежащих владельцу флота
432
      ($mission_data['src_user'] || $mission_data['src_planet'] ? "LEFT JOIN {{unit}} AS unit_player_src ON unit_player_src.unit_player_id = us.id " : '') .
433
      // Блокировка планеты отправления
434
      ($mission_data['src_planet'] ? "LEFT JOIN {{planets}} AS ps ON ps.id = f.fleet_start_planet_id " : '') .
435
      // Блокировка всех юнитов, принадлежащих планете с которой юниты были отправлены - НЕ НУЖНО. Уже залочили ранее, как принадлежащие владельцу флота
436
//      ($mission_data['src_planet'] ? "LEFT JOIN {{unit}} AS ups ON ups.unit_location_type = " . LOC_PLANET . " AND ups.unit_location_id = ps.id " : '') .
437
438
      "WHERE f.fleet_id = {$fleet_id_safe} GROUP BY 1 FOR UPDATE"
439
    );
440
  }
441
442
  /**
443
   * Lock all fields that belongs to operation
444
   *
445
   * @param $dbId
446
   */
447
  // TODO = make static
448
  public function dbGetLockById($dbId) {
449
    doquery(
450
    // Блокировка самого флота
451
      "SELECT 1 FROM {{fleets}} AS FLEET0 " .
452
      // Lock fleet owner
453
      "LEFT JOIN {{users}} as USER0 on USER0.id = FLEET0.fleet_owner " .
454
      // Блокировка всех юнитов, принадлежащих этому флоту
455
      "LEFT JOIN {{unit}} as UNIT0 ON UNIT0.unit_location_type = " . LOC_FLEET . " AND UNIT0.unit_location_id = FLEET0.fleet_id " .
456
457
      // Без предварительной выборки неизвестно - куда летит этот флот.
458
      // Поэтому надо выбирать флоты, чьи координаты прибытия ИЛИ отбытия совпадают с координатами прибытия ИЛИ отбытия текущего флота.
459
      // Получаем матрицу 2х2 - т.е. 4 подзапроса.
460
      // При блокировке всегда нужно выбирать И лпанету, И луну - поскольку при бое на орбите луны обломки падают на орбиту планеты.
461
      // Поэтому тип планеты не указывается
462
463
      // Lock fleet heading to destination planet. Only if FLEET0.fleet_mess == 0
464
      "LEFT JOIN {{fleets}} AS FLEET1 ON
465
        FLEET1.fleet_mess = 0 AND FLEET0.fleet_mess = 0 AND
466
        FLEET1.fleet_end_galaxy = FLEET0.fleet_end_galaxy AND
467
        FLEET1.fleet_end_system = FLEET0.fleet_end_system AND
468
        FLEET1.fleet_end_planet = FLEET0.fleet_end_planet
469
      " .
470
      // Блокировка всех юнитов, принадлежащих этим флотам
471
      "LEFT JOIN {{unit}} as UNIT1 ON UNIT1.unit_location_type = " . LOC_FLEET . " AND UNIT1.unit_location_id = FLEET1.fleet_id " .
472
      // Lock fleet owner
473
      "LEFT JOIN {{users}} as USER1 on USER1.id = FLEET1.fleet_owner " .
474
475
      "LEFT JOIN {{fleets}} AS FLEET2 ON
476
        FLEET2.fleet_mess = 1   AND FLEET0.fleet_mess = 0 AND
477
        FLEET2.fleet_start_galaxy = FLEET0.fleet_end_galaxy AND
478
        FLEET2.fleet_start_system = FLEET0.fleet_end_system AND
479
        FLEET2.fleet_start_planet = FLEET0.fleet_end_planet
480
      " .
481
      // Блокировка всех юнитов, принадлежащих этим флотам
482
      "LEFT JOIN {{unit}} as UNIT2 ON
483
        UNIT2.unit_location_type = " . LOC_FLEET . " AND
484
        UNIT2.unit_location_id = FLEET2.fleet_id
485
      " .
486
      // Lock fleet owner
487
      "LEFT JOIN {{users}} as USER2 on
488
        USER2.id = FLEET2.fleet_owner
489
      " .
490
491
      // Lock fleet heading to source planet. Only if FLEET0.fleet_mess == 1
492
      "LEFT JOIN {{fleets}} AS FLEET3 ON
493
        FLEET3.fleet_mess = 0 AND FLEET0.fleet_mess = 1 AND
494
        FLEET3.fleet_end_galaxy = FLEET0.fleet_start_galaxy AND
495
        FLEET3.fleet_end_system = FLEET0.fleet_start_system AND
496
        FLEET3.fleet_end_planet = FLEET0.fleet_start_planet
497
      " .
498
      // Блокировка всех юнитов, принадлежащих этим флотам
499
      "LEFT JOIN {{unit}} as UNIT3 ON
500
        UNIT3.unit_location_type = " . LOC_FLEET . " AND
501
        UNIT3.unit_location_id = FLEET3.fleet_id
502
      " .
503
      // Lock fleet owner
504
      "LEFT JOIN {{users}} as USER3 on USER3.id = FLEET3.fleet_owner " .
505
506
      "LEFT JOIN {{fleets}} AS FLEET4 ON
507
        FLEET4.fleet_mess = 1   AND FLEET0.fleet_mess = 1 AND
508
        FLEET4.fleet_start_galaxy = FLEET0.fleet_start_galaxy AND
509
        FLEET4.fleet_start_system = FLEET0.fleet_start_system AND
510
        FLEET4.fleet_start_planet = FLEET0.fleet_start_planet
511
      " .
512
      // Блокировка всех юнитов, принадлежащих этим флотам
513
      "LEFT JOIN {{unit}} as UNIT4 ON
514
        UNIT4.unit_location_type = " . LOC_FLEET . " AND
515
        UNIT4.unit_location_id = FLEET4.fleet_id
516
      " .
517
      // Lock fleet owner
518
      "LEFT JOIN {{users}} as USER4 on
519
        USER4.id = FLEET4.fleet_owner
520
      " .
521
522
523
      // Locking start planet
524
      "LEFT JOIN {{planets}} AS PLANETS5 ON
525
        FLEET0.fleet_mess = 1 AND
526
        PLANETS5.galaxy = FLEET0.fleet_start_galaxy AND
527
        PLANETS5.system = FLEET0.fleet_start_system AND
528
        PLANETS5.planet = FLEET0.fleet_start_planet
529
      " .
530
      // Lock planet owner
531
      "LEFT JOIN {{users}} as USER5 on
532
        USER5.id = PLANETS5.id_owner
533
      " .
534
      // Блокировка всех юнитов, принадлежащих этой планете
535
      "LEFT JOIN {{unit}} as UNIT5 ON
536
        UNIT5.unit_location_type = " . LOC_PLANET . " AND
537
        UNIT5.unit_location_id = PLANETS5.id
538
      " .
539
540
541
      // Locking destination planet
542
      "LEFT JOIN {{planets}} AS PLANETS6 ON
543
        FLEET0.fleet_mess = 0 AND
544
        PLANETS6.galaxy = FLEET0.fleet_end_galaxy AND
545
        PLANETS6.system = FLEET0.fleet_end_system AND
546
        PLANETS6.planet = FLEET0.fleet_end_planet
547
      " .
548
      // Lock planet owner
549
      "LEFT JOIN {{users}} as USER6 on
550
        USER6.id = PLANETS6.id_owner
551
      " .
552
      // Блокировка всех юнитов, принадлежащих этой планете
553
      "LEFT JOIN {{unit}} as UNIT6 ON
554
        UNIT6.unit_location_type = " . LOC_PLANET . " AND
555
        UNIT6.unit_location_id = PLANETS6.id
556
      " .
557
      "WHERE FLEET0.fleet_id = {$dbId} GROUP BY 1 FOR UPDATE"
558
    );
559
  }
560
561
562
  public function dbRowParse($db_row) {
563
    parent::dbRowParse($db_row); // TODO: Change the autogenerated stub
564
    $player = new Player();
565
    $player->dbLoad($db_row['fleet_owner']);
566
    $this->setLocatedAt($player);
567
  }
568
569
  /* FLEET HELPERS =====================================================================================================*/
570
  /**
571
   * Forcibly returns fleet before time outs
572
   */
573
  public function commandReturn() {
574
    $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;
575
576
    $this->markReturned();
577
578
    // Считаем, что флот уже долетел TODO
579
    $this->time_arrive_to_target = SN_TIME_NOW;
580
    // Убираем флот из группы
581
    $this->group_id = 0;
582
    // Отменяем работу в точке назначения
583
    $this->time_mission_job_complete = 0;
584
    // TODO - правильно вычслять время возвращения - по проделанному пути, а не по старому времени возвращения
585
    $this->time_return_to_source = $ReturnFlyingTime;
586
587
    // Записываем изменения в БД
588
    $this->dbSave();
589
590
    if ($this->_group_id) {
591
      // TODO: Make here to delete only one AKS - by adding aks_fleet_count to AKS table
592
      DBStaticFleetACS::db_fleet_aks_purge();
593
    }
594
  }
595
596
597
  /**
598
   * @return array
599
   */
600
  public function target_coordinates_without_type() {
601
    return array(
602
      'galaxy' => $this->_fleet_end_galaxy,
603
      'system' => $this->_fleet_end_system,
604
      'planet' => $this->_fleet_end_planet,
605
    );
606
  }
607
608
  /**
609
   * @return array
610
   */
611
  public function target_coordinates_typed() {
612
    return array(
613
      'galaxy' => $this->_fleet_end_galaxy,
614
      'system' => $this->_fleet_end_system,
615
      'planet' => $this->_fleet_end_planet,
616
      'type'   => $this->_fleet_end_type,
617
    );
618
  }
619
620
  /**
621
   * @return array
622
   */
623
  public function launch_coordinates_typed() {
624
    return array(
625
      'galaxy' => $this->_fleet_start_galaxy,
626
      'system' => $this->_fleet_start_system,
627
      'planet' => $this->_fleet_start_planet,
628
      'type'   => $this->_fleet_start_type,
629
    );
630
  }
631
632
633
  /**
634
   * Sets object fields for fleet return
635
   */
636
  public function markReturned() {
637
    // TODO - Проверка - а не возвращается ли уже флот?
638
    $this->is_returning = 1;
639
  }
640
641
  public function isReturning() {
642
    return 1 == $this->_is_returning;
643
  }
644
645
  public function markReturnedAndSave() {
646
    $this->markReturned();
647
    $this->dbSave();
648
  }
649
650
  /**
651
   * Parses extended unit_array which can include not only ships but resources, captains etc
652
   *
653
   * @param $unit_array
654
   *
655
   * @throws Exception
656
   */
657
  // TODO - separate shipList and unitList
658
  public function unitsSetFromArray($unit_array) {
659
    if (empty($unit_array) || !is_array($unit_array)) {
660
      return;
661
    }
662
    foreach ($unit_array as $unit_id => $unit_count) {
663
      $unit_count = floatval($unit_count);
664
      if (!$unit_count) {
665
        continue;
666
      }
667
668
      if ($this->isShip($unit_id)) {
669
        $this->unitList->unitSetCount($unit_id, $unit_count);
670
      } elseif ($this->isResource($unit_id)) {
671
        $this->resource_list[$unit_id] = $unit_count;
672
      } else {
673
        throw new Exception('Trying to pass to fleet non-resource and non-ship ' . var_export($unit_array, true), ERR_ERROR);
674
      }
675
    }
676
  }
677
678
679
  /**
680
   * Sets fleet timers based on flight duration, time on mission (HOLD/EXPLORE) and fleet departure time.
681
   *
682
   * @param int $time_to_travel - flight duration in seconds
683
   * @param int $time_on_mission - time on mission in seconds
684
   * @param int $flight_departure - fleet departure from source planet timestamp. Allows to send fleet in future or in past
685
   */
686
  public function set_times($time_to_travel, $time_on_mission = 0, $flight_departure = SN_TIME_NOW) {
687
    $this->_time_launch = $flight_departure;
688
689
    $this->_time_arrive_to_target = $this->_time_launch + $time_to_travel;
690
    $this->_time_mission_job_complete = $time_on_mission ? $this->_time_arrive_to_target + $time_on_mission : 0;
691
    $this->_time_return_to_source = ($this->_time_mission_job_complete ? $this->_time_mission_job_complete : $this->_time_arrive_to_target) + $time_to_travel;
692
  }
693
694
695
  public function parse_missile_db_row($missile_db_row) {
696
//    $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...
697
698
    if (empty($missile_db_row) || !is_array($missile_db_row)) {
699
      return;
700
    }
701
702
//      $planet_start = db_planet_by_vector($irak_original, 'fleet_start_', false, 'name');
0 ignored issues
show
Unused Code Comprehensibility introduced by
61% 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...
703
//      $irak_original['fleet_start_name'] = $planet_start['name'];
704
    $this->missile_target = $missile_db_row['primaer'];
705
706
    $this->_dbId = -$missile_db_row['id'];
707
    $this->_playerOwnerId = $missile_db_row['fleet_owner'];
708
    $this->_mission_type = MT_MISSILE;
709
710
    $this->_target_owner_id = $missile_db_row['fleet_target_owner'];
711
712
    $this->_group_id = 0;
713
    $this->_is_returning = 0;
714
715
    $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...
716
    $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...
717
    $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...
718
    $this->_time_return_to_source = $missile_db_row['fleet_end_time'];
719
720
    $this->_fleet_start_planet_id = !empty($missile_db_row['fleet_start_planet_id']) ? $missile_db_row['fleet_start_planet_id'] : null;
721
    $this->_fleet_start_galaxy = $missile_db_row['fleet_start_galaxy'];
722
    $this->_fleet_start_system = $missile_db_row['fleet_start_system'];
723
    $this->_fleet_start_planet = $missile_db_row['fleet_start_planet'];
724
    $this->_fleet_start_type = $missile_db_row['fleet_start_type'];
725
726
    $this->_fleet_end_planet_id = !empty($missile_db_row['fleet_end_planet_id']) ? $missile_db_row['fleet_end_planet_id'] : null;
727
    $this->_fleet_end_galaxy = $missile_db_row['fleet_end_galaxy'];
728
    $this->_fleet_end_system = $missile_db_row['fleet_end_system'];
729
    $this->_fleet_end_planet = $missile_db_row['fleet_end_planet'];
730
    $this->_fleet_end_type = $missile_db_row['fleet_end_type'];
731
732
    $this->unitList->unitSetCount(UNIT_DEF_MISSILE_INTERPLANET, $missile_db_row['fleet_amount']);
733
  }
734
735
736
  /**
737
   * @param $from
738
   */
739
  public function set_start_planet($from) {
740
    $this->fleet_start_planet_id = intval($from['id']) ? $from['id'] : null;
741
    $this->fleet_start_galaxy = $from['galaxy'];
742
    $this->fleet_start_system = $from['system'];
743
    $this->fleet_start_planet = $from['planet'];
744
    $this->fleet_start_type = $from['planet_type'];
745
  }
746
747
  /**
748
   * @param $to
749
   */
750
  public function set_end_planet($to) {
751
    $this->target_owner_id = intval($to['id_owner']) ? $to['id_owner'] : 0;
752
    $this->fleet_end_planet_id = intval($to['id']) ? $to['id'] : null;
753
    $this->fleet_end_galaxy = $to['galaxy'];
754
    $this->fleet_end_system = $to['system'];
755
    $this->fleet_end_planet = $to['planet'];
756
    $this->fleet_end_type = $to['planet_type'];
757
  }
758
759
  /**
760
   * @param Vector $to
761
   */
762
  public function setTargetFromVectorObject($to) {
763
    $this->_fleet_end_galaxy = $to->galaxy;
764
    $this->_fleet_end_system = $to->system;
765
    $this->_fleet_end_planet = $to->planet;
766
    $this->_fleet_end_type = $to->type;
767
  }
768
769
  /**
770
   * @param array $db_row
771
   */
772
  protected function ownerExtract(array &$db_row) {
773
    $player = new Player();
774
    $player->dbLoad($db_row['fleet_owner']);
775
    $this->setLocatedAt($player);
776
  }
777
778
  /**
779
   * @param array $db_row
780
   */
781
  protected function ownerInject(array &$db_row) {
782
    $db_row['fleet_owner'] = $this->getPlayerOwnerId();
783
  }
784
785
786
787
788
  // UnitList/Ships access ***************************************************************************************************
789
790
  // TODO - перекрывать пожже - для миссайл-флотов и дефенс-флотов
791
  protected function isShip($unit_id) {
792
    return UnitShip::is_in_group($unit_id);
793
  }
794
795
  /**
796
   * Set unit count of $unit_id to $unit_count
797
   * If there is no $unit_id - it will be created and saved to DB on dbSave
798
   *
799
   * @param int $unit_id
800
   * @param int $unit_count
801
   */
802
  public function shipSetCount($unit_id, $unit_count = 0) {
803
pdump(__CLASS__ . '->' . __FUNCTION__);
804
    $this->shipAdjustCount($unit_id, $unit_count, true);
805
  }
806
807
  /**
808
   * Adjust unit count of $unit_id by $unit_count - or just replace value
809
   * If there is no $unit_id - it will be created and saved to DB on dbSave
810
   *
811
   * @param int  $unit_id
812
   * @param int  $unit_count
813
   * @param bool $replace_value
814
   */
815
  public function shipAdjustCount($unit_id, $unit_count = 0, $replace_value = false) {
816
    $this->unitList->unitAdjustCount($unit_id, $unit_count, $replace_value);
817
  }
818
819
  public function shipGetCount($unit_id) {
820
    return $this->unitList->unitGetCount($unit_id);
821
  }
822
823
  public function shipsCountApplyLossMultiplier($ships_lost_multiplier) {
824
    $this->unitList->unitsCountApplyLossMultiplier($ships_lost_multiplier);
825
  }
826
827
  /**
828
   * Returns fleet ships cost in metal
829
   *
830
   * @param array $shipCostInMetalPerPiece
831
   *
832
   * @return float[]
833
   */
834
  public function shipsCostInMetal($shipCostInMetalPerPiece) {
835
    return $this->unitList->unitsCostInMetal($shipCostInMetalPerPiece);
836
  }
837
838
  /**
839
   * @return UnitIterator
840
   */
841
  public function shipsIterator() {
842
    return $this->unitList->getUnitIterator();
843
  }
844
845
  public function shipsGetTotal() {
846
    return $this->unitList->unitsCount();
847
  }
848
849
  public function shipsGetCapacity() {
850
    return $this->unitList->shipsCapacity();
851
  }
852
853
  public function shipsGetHoldFree() {
854
    return max(0, $this->shipsGetCapacity() - $this->resourcesGetTotal());
855
  }
856
857
  /**
858
   * Get count of ships with $ship_id
859
   *
860
   * @param int $ship_id
861
   *
862
   * @return int
863
   */
864
  public function shipsGetTotalById($ship_id) {
865
    return $this->unitList->unitsCountById($ship_id);
866
  }
867
868
  /**
869
   * Возвращает ёмкость переработчиков во флоте
870
   *
871
   * @param array $recycler_info
872
   *
873
   * @return int
874
   *
875
   * @version 41a50.14
876
   */
877
  public function shipsGetCapacityRecyclers($recycler_info) {
878
    $recyclers_incoming_capacity = 0;
879
    foreach($this->shipsIterator() as $unitId => $unit) {
880
      if(!empty(static::$snGroupRecyclers[$unitId]) && $unit->count >= 1) {
881
        $recyclers_incoming_capacity += $unit->count * $recycler_info[$unitId]['capacity'];
882
      }
883
    }
884
885
    return $recyclers_incoming_capacity;
886
  }
887
888
  /**
889
   * @return bool
890
   */
891
  // TODO - А если не на планете????
892
  public function shipsIsEnoughOnPlanet() {
893
    return $this->unitList->shipsIsEnoughOnPlanet($this->dbOwnerRow, $this->dbSourcePlanetRow);
894
  }
895
896
  /**
897
   * @return bool
898
   */
899
  public function shipsAllPositive() {
900
    return $this->unitList->unitsPositive();
901
  }
902
903
  /**
904
   * @return bool
905
   */
906
  public function shipsAllFlying() {
907
    return $this->unitList->unitsInGroup(static::$snGroupFleetAndMissiles);
908
  }
909
910
  /**
911
   * @return bool
912
   */
913
  public function shipsAllMovable() {
914
    return $this->unitList->unitsIsAllMovable($this->dbOwnerRow);
915
  }
916
917
  /**
918
   * Restores fleet or resources to planet
919
   *
920
   * @param bool $start
921
   * @param int  $result
922
   *
923
   * @return int
924
   */
925
  // TODO - split to functions
926
  public function shipsLand($start = true, &$result = CACHE_NOTHING) {
927
    sn_db_transaction_check(true);
928
929
    // Если флот уже обработан - не существует или возращается - тогда ничего не делаем
930
    if ($this->isEmpty()) {
931
      return $result;
932
    }
933
934
    $coordinates = $start ? $this->launch_coordinates_typed() : $this->target_coordinates_typed();
935
936
    // Поскольку эта функция может быть вызвана не из обработчика флотов - нам надо всё заблокировать вроде бы НЕ МОЖЕТ!!!
937
    // TODO Проверить от многократного срабатывания !!!
938
    // Тут не блокируем пока - сначала надо заблокировать пользователя, что бы не было дедлока
939
    // TODO поменять на владельца планеты - когда его будут возвращать всегда !!!
940
941
    // Узнаем ИД владельца планеты.
942
    // С блокировкой, поскольку эта функция может быть вызвана только из менеджера летящих флотов.
943
    // А там уже всё заблокировано как надо и повторная блокировка не вызовет дедлок.
944
    $planet_arrival = DBStaticPlanet::db_planet_by_vector($coordinates, '', true);
945
    // Блокируем пользователя
946
    // TODO - вообще-то нам уже известен пользователь в МЛФ - так что можно просто передать его сюда
947
    $user = DBStaticUser::db_user_by_id($planet_arrival['id_owner'], true);
948
949
    // TODO - Проверка, что планета всё еще существует на указанных координатах, а не телепортировалась, не удалена хозяином, не уничтожена врагом
950
    // Флот, который возвращается на захваченную планету, пропадает
951
    // Ship landing is possible only to fleet owner's planet
952
    if ($this->getPlayerOwnerId() == $planet_arrival['id_owner']) {
953
      $db_changeset = array();
954
955
      foreach ($this->shipsIterator() as $ship_id => $ship) {
956
        if ($ship->count) {
957
          $db_changeset['unit'][] = sn_db_unit_changeset_prepare($ship_id, $ship->count, $user, $planet_arrival['id']);
958
        }
959
      }
960
961
      // Adjusting ship amount on planet
962
      if (!empty($db_changeset)) {
963
        db_changeset_apply($db_changeset);
964
      }
965
966
      // Restoring resources to planet
967
      $this->resourcesUnload($start, $result);
968
    }
969
970
    $result = CACHE_FLEET | ($start ? CACHE_PLANET_SRC : CACHE_PLANET_DST);
971
972
    $result = RestoreFleetToPlanet($this, $start, $result);
973
974
    $this->dbDelete();
975
976
    return $result;
977
  }
978
979
980
  // Resources access ***************************************************************************************************
981
982
  /**
983
   * Extracts resources value from db_row
984
   *
985
   * @param array $db_row
986
   *
987
   * @internal param Fleet $that
988
   * @version 41a50.14
989
   */
990
  protected function resourcesExtract(array &$db_row) {
991
    $this->resource_list = array(
992
      RES_METAL     => !empty($db_row['fleet_resource_metal']) ? floor($db_row['fleet_resource_metal']) : 0,
993
      RES_CRYSTAL   => !empty($db_row['fleet_resource_crystal']) ? floor($db_row['fleet_resource_crystal']) : 0,
994
      RES_DEUTERIUM => !empty($db_row['fleet_resource_deuterium']) ? floor($db_row['fleet_resource_deuterium']) : 0,
995
    );
996
  }
997
998
  protected function resourcesInject(array &$db_row) {
999
    $db_row['fleet_resource_metal'] = $this->resource_list[RES_METAL];
1000
    $db_row['fleet_resource_crystal'] = $this->resource_list[RES_CRYSTAL];
1001
    $db_row['fleet_resource_deuterium'] = $this->resource_list[RES_DEUTERIUM];
1002
  }
1003
1004
  /**
1005
   * Set current resource list from array of units
1006
   *
1007
   * @param array $resource_list
1008
   */
1009
  public function resourcesSet($resource_list) {
1010
    if (!empty($this->propertiesAdjusted['resource_list'])) {
1011
      throw new PropertyAccessException('Property "resource_list" already was adjusted so no SET is possible until dbSave in ' . get_called_class() . '::unitSetResourceList', ERR_ERROR);
1012
    }
1013
    $this->resourcesAdjust($resource_list, true);
1014
  }
1015
1016
  /**
1017
   * Updates fleet resource list with deltas
1018
   *
1019
   * @param array $resource_delta_list
1020
   * @param bool  $replace_value
1021
   *
1022
   * @throws Exception
1023
   */
1024
  public function resourcesAdjust($resource_delta_list, $replace_value = false) {
1025
    !is_array($resource_delta_list) ? $resource_delta_list = array() : false;
1026
1027
    foreach ($resource_delta_list as $resource_id => $unit_delta) {
1028
      if (!UnitResourceLoot::is_in_group($resource_id) || !($unit_delta = floor($unit_delta))) {
1029
        // Not a resource or no resources - continuing
1030
        continue;
1031
      }
1032
1033
      if ($replace_value) {
1034
        $this->resource_list[$resource_id] = $unit_delta;
1035
      } else {
1036
        $this->resource_list[$resource_id] += $unit_delta;
1037
        // Preparing changes
1038
        $this->resource_delta[$resource_id] += $unit_delta;
1039
        $this->propertiesAdjusted['resource_list'] = 1;
1040
      }
1041
1042
      // Check for negative unit value
1043
      if ($this->resource_list[$resource_id] < 0) {
1044
        // TODO
1045
        throw new Exception('Resource ' . $resource_id . ' will become negative in ' . get_called_class() . '::unitAdjustResourceList', ERR_ERROR);
1046
      }
1047
    }
1048
  }
1049
1050
  public function resourcesGetTotal() {
1051
    return empty($this->resource_list) || !is_array($this->resource_list) ? 0 : array_sum($this->resource_list);
1052
  }
1053
1054
  /**
1055
   * @param array $rate
1056
   *
1057
   * @return float
1058
   */
1059
  public function resourcesGetTotalInMetal(array $rate) {
1060
    return
1061
      $this->resource_list[RES_METAL] * $rate[RES_METAL]
1062
      + $this->resource_list[RES_CRYSTAL] * $rate[RES_CRYSTAL] / $rate[RES_METAL]
1063
      + $this->resource_list[RES_DEUTERIUM] * $rate[RES_DEUTERIUM] / $rate[RES_METAL];
1064
  }
1065
1066
  /**
1067
   * Returns resource list in fleet
1068
   */
1069
  // TODO
1070
  public function resourcesGetList() {
1071
    return $this->resource_list;
1072
  }
1073
1074
  public function resourcesReset() {
1075
    $this->resourcesSet(array(
1076
      RES_METAL     => 0,
1077
      RES_CRYSTAL   => 0,
1078
      RES_DEUTERIUM => 0,
1079
    ));
1080
  }
1081
1082
  /**
1083
   * Restores fleet or resources to planet
1084
   *
1085
   * @param bool $start
1086
   * @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...
1087
   * @param int  $result
1088
   *
1089
   * @return int
1090
   */
1091
  public function resourcesUnload($start = true, &$result = CACHE_NOTHING) {
1092
    sn_db_transaction_check(true);
1093
1094
    // Если флот уже обработан - не существует или возращается - тогда ничего не делаем
1095
    if (!$this->resourcesGetTotal()) {
1096
      return $result;
1097
    }
1098
1099
    $coordinates = $start ? $this->launch_coordinates_typed() : $this->target_coordinates_typed();
1100
1101
    // Поскольку эта функция может быть вызвана не из обработчика флотов - нам надо всё заблокировать вроде бы НЕ МОЖЕТ!!!
1102
    // TODO Проверить от многократного срабатывания !!!
1103
    // Тут не блокируем пока - сначала надо заблокировать пользователя, что бы не было дедлока
1104
    // TODO поменять на владельца планеты - когда его будут возвращать всегда !!!
1105
1106
1107
    // Узнаем ИД владельца планеты.
1108
    // С блокировкой, поскольку эта функция может быть вызвана только из менеджера летящих флотов.
1109
    // А там уже всё заблокировано как надо и повторная блокировка не вызовет дедлок.
1110
    $planet_arrival = DBStaticPlanet::db_planet_by_vector($coordinates, '', true);
1111
1112
    // TODO - Проверка, что планета всё еще существует на указанных координатах, а не телепортировалась, не удалена хозяином, не уничтожена врагом
1113
1114
    // Restoring resources to planet
1115
    if ($this->resourcesGetTotal()) {
1116
      $fleet_resources = $this->resourcesGetList();
1117
      DBStaticPlanet::db_planet_set_by_id($planet_arrival['id'],
1118
        "`metal` = `metal` + '{$fleet_resources[RES_METAL]}', `crystal` = `crystal` + '{$fleet_resources[RES_CRYSTAL]}', `deuterium` = `deuterium` + '{$fleet_resources[RES_DEUTERIUM]}'");
1119
    }
1120
1121
    $this->resourcesReset();
1122
    $this->markReturned();
1123
1124
    $result = CACHE_FLEET | ($start ? CACHE_PLANET_SRC : CACHE_PLANET_DST);
1125
1126
    return $result;
1127
  }
1128
1129
1130
  protected function isResource($unit_id) {
1131
    return UnitResourceLoot::is_in_group($unit_id);
1132
  }
1133
1134
  /**
1135
   * @param int $speed_percent
1136
   *
1137
   * @return array
1138
   */
1139
  protected function flt_travel_data($speed_percent = 10) {
1140
    $distance = $this->targetVector->distanceFromCoordinates($this->dbSourcePlanetRow);
1141
1142
    return $this->unitList->travelData($speed_percent, $distance, $this->dbOwnerRow);
1143
  }
1144
1145
1146
  /**
1147
   * @param array  $dbPlayerRow
1148
   * @param array  $dbPlanetRow
1149
   * @param Vector $targetVector
1150
   *
1151
   */
1152
  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...
1153
    $objFleet5Player = new Player();
1154
    $objFleet5Player->dbRowParse($dbPlayerRow);
1155
    $this->setLocatedAt($objFleet5Player);
1156
1157
    $this->mission_type = $mission;
1158
1159
    $this->dbOwnerRow = $dbPlayerRow;
1160
1161
    $this->set_start_planet($dbPlanetRow);
1162
    $this->dbSourcePlanetRow = $dbPlanetRow;
1163
1164
    $this->setTargetFromVectorObject($targetVector);
1165
    $this->targetVector = $targetVector;
1166
1167
    $this->populateTargetPlanet();
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 populateTargetPlanet() {
1201
    $targetPlanetCoords = $this->targetVector;
1202
    if ($this->mission_type != MT_NONE) {
1203
      $this->restrictTargetTypeByMission();
1204
1205
      // TODO - Нельзя тут просто менять тип планеты или координат!
1206
      // If current planet type is not allowed on mission - switch planet type
1207
      if (empty($this->allowed_planet_types[$this->targetVector->type])) {
1208
        $targetPlanetCoords->type = reset($this->allowed_planet_types);
1209
      }
1210
    }
1211
1212
    $this->dbTargetRow = DBStaticPlanet::db_planet_by_vector_object($targetPlanetCoords);
1213
  }
1214
1215
1216
  protected function printErrorIfNoShips() {
1217
    if ($this->unitList->unitsCount() <= 0) {
1218
      message(classLocale::$lang['fl_err_no_ships'], classLocale::$lang['fl_error'], 'fleet' . DOT_PHP_EX, 5);
1219
    }
1220
  }
1221
1222
  /**
1223
   */
1224
  public function renderParamCoordinates() {
1225
    global $template_result;
1226
    $template_result += array(
1227
      'thisgalaxy'      => $this->dbSourcePlanetRow['galaxy'],
1228
      'thissystem'      => $this->dbSourcePlanetRow['system'],
1229
      'thisplanet'      => $this->dbSourcePlanetRow['planet'],
1230
      'thisplanet_type' => $this->dbSourcePlanetRow['planet_type'],
1231
1232
      'galaxy'         => $this->targetVector->galaxy,
1233
      'system'         => $this->targetVector->system,
1234
      'planet'         => $this->targetVector->planet,
1235
      'planet_type'    => $this->targetVector->type,
1236
      'target_mission' => $this->_mission_type,
1237
      'MISSION_NAME'   => $this->_mission_type ? classLocale::$lang['type_mission'][$this->_mission_type] : '',
1238
1239
      'MT_COLONIZE' => MT_COLONIZE,
1240
    );
1241
  }
1242
1243
1244
  protected function renderFleetCoordinates($missionStartTimeStamp = SN_TIME_NOW, $timeMissionJob = 0) {
1245
    $timeToReturn = $this->travelData['duration'] * 2 + $timeMissionJob;
1246
1247
    return array(
1248
      'ID'                 => 1,
1249
      'START_TYPE_TEXT_SH' => classLocale::$lang['sys_planet_type_sh'][$this->dbSourcePlanetRow['planet_type']],
1250
      'START_COORDS'       => uni_render_coordinates($this->dbSourcePlanetRow),
1251
      'START_NAME'         => $this->dbSourcePlanetRow['name'],
1252
      'START_TIME_TEXT'    => date(FMT_DATE_TIME, $missionStartTimeStamp + $timeToReturn + SN_CLIENT_TIME_DIFF),
1253
      'START_LEFT'         => floor($this->travelData['duration'] * 2 + $timeMissionJob),
1254
      'END_TYPE_TEXT_SH'   =>
1255
        !empty($this->targetVector->type)
1256
          ? classLocale::$lang['sys_planet_type_sh'][$this->targetVector->type]
1257
          : '',
1258
      'END_COORDS'         => uniRenderVector($this->targetVector),
1259
      'END_NAME'           => !empty($this->dbTargetRow['name']) ? $this->dbTargetRow['name'] : '',
1260
      'END_TIME_TEXT'      => date(FMT_DATE_TIME, $missionStartTimeStamp + $this->travelData['duration'] + SN_CLIENT_TIME_DIFF),
1261
      'END_LEFT'           => floor($this->travelData['duration']),
1262
    );
1263
  }
1264
1265
  /**
1266
   * @param int $missionStartTimeStamp
1267
   * @param int $timeMissionJob
1268
   *
1269
   * @return array
1270
   *
1271
   * @throws Exception
1272
   */
1273
  protected function renderFleet($missionStartTimeStamp = SN_TIME_NOW, $timeMissionJob = 0) {
1274
    $this->printErrorIfNoShips();
1275
1276
    $result = $this->renderFleetCoordinates($missionStartTimeStamp, $timeMissionJob);
1277
    $result['.']['ships'] = $this->unitList->unitsRender();
1278
1279
    return $result;
1280
  }
1281
1282
  /**
1283
   * @return array
1284
   */
1285
  protected function renderAllowedMissions() {
1286
    $result = array();
1287
1288
    ksort($this->allowed_missions);
1289
    // If mission is not set - setting first mission from allowed
1290
    if (empty($this->_mission_type) && is_array($this->allowed_missions)) {
1291
      reset($this->allowed_missions);
1292
      $this->_mission_type = key($this->allowed_missions);
1293
    }
1294
    foreach ($this->allowed_missions as $key => $value) {
1295
      $result[] = array(
1296
        'ID'   => $key,
1297
        'NAME' => classLocale::$lang['type_mission'][$key],
1298
      );
1299
    };
1300
1301
    return $result;
1302
  }
1303
1304
  /**
1305
   * @param $max_duration
1306
   *
1307
   * @return array
1308
   */
1309
  protected function renderDuration($max_duration) {
1310
    $result = array();
1311
1312
    if (!$max_duration) {
1313
      return $result;
1314
    }
1315
1316
    $config_game_speed_expedition = ($this->_mission_type == MT_EXPLORE && classSupernova::$config->game_speed_expedition ? classSupernova::$config->game_speed_expedition : 1);
1317
    for ($i = 1; $i <= $max_duration; $i++) {
1318
      $result[] = array(
1319
        'ID'   => $i,
1320
        'TIME' => pretty_time(ceil($i * 3600 / $config_game_speed_expedition)),
1321
      );
1322
    }
1323
1324
    return $result;
1325
  }
1326
1327
  /**
1328
   * @param array $planetResources
1329
   *
1330
   * @return array
1331
   */
1332
  // TODO - REDO to resource_id
1333
  protected function renderPlanetResources(&$planetResources) {
1334
    $result = array();
1335
1336
    $i = 0;
1337
    foreach ($planetResources as $resource_id => $resource_amount) {
1338
      $result[] = array(
1339
        'ID'        => $i++, // $resource_id,
1340
        'ON_PLANET' => $resource_amount,
1341
        'TEXT'      => pretty_number($resource_amount),
1342
        'NAME'      => classLocale::$lang['tech'][$resource_id],
1343
      );
1344
    }
1345
1346
    return $result;
1347
  }
1348
1349
  /**
1350
   * @return array
1351
   */
1352
  protected function renderAllowedPlanetTypes() {
1353
    $result = array();
1354
1355
    foreach ($this->allowed_planet_types as $possible_planet_type_id) {
1356
      $result[] = array(
1357
        'ID'         => $possible_planet_type_id,
1358
        'NAME'       => classLocale::$lang['sys_planet_type'][$possible_planet_type_id],
1359
        'NAME_SHORT' => classLocale::$lang['sys_planet_type_sh'][$possible_planet_type_id],
1360
      );
1361
    }
1362
1363
    return $result;
1364
  }
1365
1366
1367
  protected function renderFleet1TargetSelect(&$shortcut) {
1368
    global $note_priority_classes;
1369
1370
    $name = !empty($shortcut['title']) ? $shortcut['title'] : $shortcut['name'];
1371
1372
    $result = array(
1373
      'NAME'       => $name,
1374
      'GALAXY'     => $shortcut['galaxy'],
1375
      'SYSTEM'     => $shortcut['system'],
1376
      'PLANET'     => $shortcut['planet'],
1377
      'TYPE'       => $shortcut['planet_type'],
1378
      'TYPE_PRINT' => classLocale::$lang['fl_shrtcup'][$shortcut['planet_type']],
1379
    );
1380
1381
    if (isset($shortcut['priority'])) {
1382
      $result += array(
1383
        'PRIORITY'       => $shortcut['priority'],
1384
        'PRIORITY_CLASS' => $note_priority_classes[$shortcut['priority']],
1385
      );
1386
    }
1387
1388
    if (isset($shortcut['id'])) {
1389
      $result += array(
1390
        'ID' => $shortcut['id'],
1391
      );
1392
    }
1393
1394
    return $result;
1395
  }
1396
1397
  /**
1398
   * @return array
1399
   */
1400
  protected function renderFleetShortcuts() {
1401
    $result = array();
1402
1403
    // Building list of shortcuts
1404
    $query = DBStaticNote::db_note_list_select_by_owner_and_planet($this->dbOwnerRow);
1405
    while ($row = db_fetch($query)) {
1406
      $result[] = $this->renderFleet1TargetSelect($row);
1407
    }
1408
1409
    return $result;
1410
  }
1411
1412
  /**
1413
   * Building list of own planets & moons
1414
   *
1415
   * @return array
1416
   */
1417
  protected function renderOwnPlanets() {
1418
    $result = array();
1419
1420
    $colonies = DBStaticPlanet::db_planet_list_sorted($this->dbOwnerRow);
1421
    if (count($colonies) <= 1) {
1422
      return $result;
1423
    }
1424
1425
    foreach ($colonies as $row) {
1426
      if ($row['id'] == $this->dbSourcePlanetRow['id']) {
1427
        continue;
1428
      }
1429
1430
      $result[] = $this->renderFleet1TargetSelect($row);
1431
    }
1432
1433
    return $result;
1434
  }
1435
1436
  /**
1437
   * @return array
1438
   */
1439
  protected function renderACSList() {
1440
    $result = array();
1441
1442
    $query = DBStaticFleetACS::db_acs_get_list();
1443
    while ($row = db_fetch($query)) {
1444
      $members = explode(',', $row['eingeladen']);
1445
      foreach ($members as $a => $b) {
1446
        if ($b == $this->dbOwnerRow['id']) {
1447
          $result[] = $this->renderFleet1TargetSelect($row);
1448
        }
1449
      }
1450
    }
1451
1452
    return $result;
1453
  }
1454
1455
1456
  /**
1457
   * @param $template_result
1458
   */
1459
  protected function renderShipSortOptions(&$template_result) {
1460
    foreach (classLocale::$lang['player_option_fleet_ship_sort'] as $sort_id => $sort_text) {
1461
      $template_result['.']['ship_sort_list'][] = array(
1462
        'VALUE' => $sort_id,
1463
        'TEXT'  => $sort_text,
1464
      );
1465
    }
1466
    $template_result += array(
1467
      'FLEET_SHIP_SORT'         => classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_SORT],
1468
      'FLEET_SHIP_SORT_INVERSE' => classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_SORT_INVERSE],
1469
    );
1470
  }
1471
1472
1473
  /**
1474
   *
1475
   */
1476
  public function fleetPage0() {
1477
    global $template_result;
1478
1479
    lng_include('overview');
1480
1481
    if (empty($this->dbSourcePlanetRow)) {
1482
      message(classLocale::$lang['fl_noplanetrow'], classLocale::$lang['fl_error']);
1483
    }
1484
1485
    // TODO - redo to unitlist render/unit render
1486
    $this->renderAvailableShips($template_result, $this->dbOwnerRow, $this->dbSourcePlanetRow);
1487
1488
    $this->renderShipSortOptions($template_result);
1489
1490
    /**
1491
     * @var Player $playerOwner
1492
     */
1493
    $playerOwner = $this->getLocatedAt();
1494
1495
    $template_result += array(
1496
      'FLYING_FLEETS'      => $playerOwner->fleetsFlying(),
1497
      'MAX_FLEETS'         => $playerOwner->fleetsMax(),
1498
      'FREE_FLEETS'        => $playerOwner->fleetsMax() - $playerOwner->fleetsFlying(),
1499
      'FLYING_EXPEDITIONS' => $playerOwner->expeditionsFlying(),
1500
      'MAX_EXPEDITIONS'    => $playerOwner->expeditionsMax(),
1501
      'FREE_EXPEDITIONS'   => $playerOwner->expeditionsMax() - $playerOwner->expeditionsFlying(),
1502
      'COLONIES_CURRENT'   => $playerOwner->coloniesCurrent(),
1503
      'COLONIES_MAX'       => $playerOwner->coloniesMax(),
1504
1505
      'TYPE_NAME' => classLocale::$lang['fl_planettype'][$this->targetVector->type],
1506
1507
      'speed_factor' => flt_server_flight_speed_multiplier(),
1508
1509
      'PLANET_RESOURCES' => pretty_number($this->dbSourcePlanetRow['metal'] + $this->dbSourcePlanetRow['crystal'] + $this->dbSourcePlanetRow['deuterium']),
1510
      'PLANET_DEUTERIUM' => pretty_number($this->dbSourcePlanetRow['deuterium']),
1511
1512
      'PLAYER_OPTION_FLEET_SHIP_SELECT_OLD'       => classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_SELECT_OLD],
1513
      'PLAYER_OPTION_FLEET_SHIP_HIDE_SPEED'       => classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_HIDE_SPEED],
1514
      'PLAYER_OPTION_FLEET_SHIP_HIDE_CAPACITY'    => classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_HIDE_CAPACITY],
1515
      'PLAYER_OPTION_FLEET_SHIP_HIDE_CONSUMPTION' => classSupernova::$user_options[PLAYER_OPTION_FLEET_SHIP_HIDE_CONSUMPTION],
1516
    );
1517
1518
    $template = gettemplate('fleet0', true);
1519
    $template->assign_recursive($template_result);
1520
    display($template, classLocale::$lang['fl_title']);
1521
  }
1522
1523
  /**
1524
   *
1525
   */
1526
  public function fleetPage1() {
1527
    global $template_result;
1528
1529
    $template_result['.']['fleets'][] = $this->renderFleet(SN_TIME_NOW);
1530
    $template_result['.']['possible_planet_type_id'] = $this->renderAllowedPlanetTypes();
1531
    $template_result['.']['colonies'] = $this->renderOwnPlanets();
1532
    $template_result['.']['shortcut'] = $this->renderFleetShortcuts();
1533
    $template_result['.']['acss'] = $this->renderACSList();
1534
1535
    $template_result += array(
1536
      'speed_factor' => flt_server_flight_speed_multiplier(),
1537
1538
      'fleet_speed'    => $this->fleetSpeed(),
1539
      'fleet_capacity' => $this->shipsGetCapacity(),
1540
1541
      'PLANET_DEUTERIUM' => pretty_number($this->dbSourcePlanetRow['deuterium']),
1542
1543
      'PAGE_HINT' => classLocale::$lang['fl_page1_hint'],
1544
    );
1545
1546
    $template = gettemplate('fleet1', true);
1547
    $template->assign_recursive($template_result);
1548
    display($template, classLocale::$lang['fl_title']);
1549
  }
1550
1551
  public function fleetSpeed() {
1552
    $maxSpeed = PHP_INT_MAX;
1553
    foreach($this->shipsIterator() as $ship_id => $unit) {
1554
      if($unit->count > 0 && empty(static::$snGroupFleetAndMissiles[$ship_id])) {
1555
        $single_ship_data = get_ship_data($ship_id, $this->dbOwnerRow);
1556
        $maxSpeed = min($maxSpeed, $single_ship_data['speed']);
1557
      }
1558
    }
1559
1560
    return $maxSpeed == PHP_INT_MAX ? 0 : min($maxSpeed);
1561
  }
1562
1563
  /**
1564
   *
1565
   */
1566
  public function fleetPage2() {
1567
    global $template_result;
1568
1569
    $this->travelData = $this->flt_travel_data($this->oldSpeedInTens);
1570
    $planetResources = $this->resourcesGetOnPlanet();
1571
    try {
1572
      $validator = new FleetValidator($this);
1573
      $validator->validate();
1574
    } catch (Exception $e) {
1575
1576
      // TODO - MESSAGE BOX
1577 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...
1578
        sn_db_transaction_rollback();
1579
        pdie(classLocale::$lang['fl_attack_error'][$e->getCode()]);
1580
      } else {
1581
        throw $e;
1582
      }
1583
    }
1584
1585
    // Flight allowed here
1586
    pdump('FLIGHT_ALLOWED', FLIGHT_ALLOWED);
1587
1588
    $template_result['.']['missions'] = $this->renderAllowedMissions();
1589
1590
    $template_result['.']['fleets'][] = $this->renderFleet(SN_TIME_NOW);
1591
1592
    $max_duration =
1593
      $this->_mission_type == MT_EXPLORE
1594
        ? get_player_max_expedition_duration($this->dbOwnerRow)
1595
        : (isset($this->allowed_missions[MT_HOLD]) ? 12 : 0);
1596
    $template_result['.']['duration'] = $this->renderDuration($max_duration);
1597
1598
    $this->captainGet();
1599
    $template_result += $this->renderCaptain();
1600
1601
    $template_result['.']['resources'] = $this->renderPlanetResources($planetResources);
1602
1603
    $template_result += array(
1604
      'planet_metal'     => $planetResources[RES_METAL],
1605
      'planet_crystal'   => $planetResources[RES_CRYSTAL],
1606
      'planet_deuterium' => $planetResources[RES_DEUTERIUM],
1607
1608
      'fleet_capacity' => $this->shipsGetCapacity() - $this->travelData['consumption'],
1609
      'speed'          => $this->oldSpeedInTens,
1610
      'fleet_group'    => $this->_group_id,
1611
1612
      'MAX_DURATION'          => $max_duration,
1613
1614
      // 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...
1615
//      'IS_TRANSPORT_MISSIONS' => !empty($this->allowed_missions[$this->_mission_type]['transport']),
1616
      'IS_TRANSPORT_MISSIONS' => true,
1617
1618
      'PLAYER_COLONIES_CURRENT' => get_player_current_colonies($this->dbOwnerRow),
1619
      'PLAYER_COLONIES_MAX'     => get_player_max_colonies($this->dbOwnerRow),
1620
    );
1621
1622
    $template = gettemplate('fleet2', true);
1623
    $template->assign_recursive($template_result);
1624
    display($template, classLocale::$lang['fl_title']);
1625
  }
1626
1627
  /**
1628
   *
1629
   */
1630
  public function fleetPage3() {
1631
    global $template_result;
1632
1633
    $this->isRealFlight = true;
1634
1635
    sn_db_transaction_start();
1636
1637
    DBStaticUser::db_user_lock_with_target_owner_and_acs($this->dbOwnerRow, $this->dbTargetRow);
1638
1639
    // Checking for group
1640
    $this->groupCheck();
1641
1642
    $this->dbOwnerRow = DBStaticUser::db_user_by_id($this->dbOwnerRow['id'], true);
0 ignored issues
show
Documentation Bug introduced by
It seems like \DBStaticUser::db_user_b...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...
1643
    $this->dbSourcePlanetRow = DBStaticPlanet::db_planet_by_id($this->dbSourcePlanetRow['id'], true);
1644 View Code Duplication
    if (!empty($this->dbTargetRow['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...
1645
      $this->dbTargetRow = DBStaticPlanet::db_planet_by_id($this->dbTargetRow['id'], true);
1646
    }
1647 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...
1648
      $this->dbTargetOwnerRow = DBStaticPlanet::db_planet_by_id($this->dbTargetRow['id_owner'], true);
1649
    }
1650
1651
    $this->resource_list = array(
1652
      RES_METAL     => max(0, floor(sys_get_param_float('resource0'))),
1653
      RES_CRYSTAL   => max(0, floor(sys_get_param_float('resource1'))),
1654
      RES_DEUTERIUM => max(0, floor(sys_get_param_float('resource2'))),
1655
    );
1656
1657
    $this->captainGet();
1658
1659
    $this->travelData = $this->flt_travel_data($this->oldSpeedInTens);
1660
1661
    try {
1662
      $validator = new FleetValidator($this);
1663
      $validator->validate();
1664
    } catch (Exception $e) {
1665
      // TODO - MESSAGE BOX
1666 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...
1667
        sn_db_transaction_rollback();
1668
        pdie(classLocale::$lang['fl_attack_error'][$e->getCode()]);
1669
      } else {
1670
        throw $e;
1671
      }
1672
    }
1673
1674
    // Flight allowed here
1675
    pdump('FLIGHT_ALLOWED', FLIGHT_ALLOWED);
1676
1677
1678
    $timeMissionJob = 0;
1679
    // TODO check for empty mission AKA mission allowed
1680
/*
1681
    if ($this->_mission_type == MT_ACS && $aks) {
1682
      $acsTimeToArrive = $aks['ankunft'] - SN_TIME_NOW;
1683
      if ($acsTimeToArrive < $this->travelData['duration']) {
1684
        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']);
1685
      }
1686
      // Set time to travel to ACS' TTT
1687
      $this->travelData['duration'] = $acsTimeToArrive;
1688
*/
1689
      if ($this->_mission_type != MT_ACS) {
1690
      if ($this->_mission_type == MT_EXPLORE || $this->_mission_type == MT_HOLD) {
1691
        $max_duration = $this->_mission_type == MT_EXPLORE ? get_player_max_expedition_duration($this->dbOwnerRow) : ($this->_mission_type == MT_HOLD ? 12 : 0);
1692
        if ($max_duration) {
1693
          $mission_time_in_hours = sys_get_param_id('missiontime');
1694
          if ($mission_time_in_hours > $max_duration || $mission_time_in_hours < 1) {
1695
            classSupernova::$debug->warning('Supplying wrong mission time', 'Hack attempt', 302, array('base_dump' => true));
0 ignored issues
show
Documentation introduced by
array('base_dump' => true) is of type array<string,boolean,{"base_dump":"boolean"}>, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1696
            die();
1697
          }
1698
          $timeMissionJob = ceil($mission_time_in_hours * 3600 / ($this->_mission_type == MT_EXPLORE && classSupernova::$config->game_speed_expedition ? classSupernova::$config->game_speed_expedition : 1));
1699
        }
1700
      }
1701
    }
1702
1703
    //
1704
    //
1705
    //
1706
    //
1707
    //
1708
    //
1709
    //
1710
    //
1711
    // ---------------- END OF CHECKS ------------------------------------------------------
1712
1713
    $this->set_times($this->travelData['duration'], $timeMissionJob);
1714
    $this->dbInsert();
1715
1716
    DBStaticPlanet::db_planet_set_by_id($this->dbSourcePlanetRow['id'],
1717
      "`metal` = `metal` - {$this->resource_list[RES_METAL]},
1718
      `crystal` = `crystal` - {$this->resource_list[RES_CRYSTAL]},
1719
      `deuterium` = `deuterium` - {$this->resource_list[RES_DEUTERIUM]} - {$this->travelData['consumption']}"
1720
    );
1721
1722
    $db_changeset = $this->unitList->db_prepare_old_changeset_for_planet($this->dbOwnerRow, $this->dbSourcePlanetRow['id']);
1723
    db_changeset_apply($db_changeset);
1724
1725
1726
    if (!empty($this->captain['unit_id'])) {
1727
      DBStaticUnit::db_unit_set_by_id($this->captain['unit_id'], "`unit_location_type` = " . LOC_FLEET . ", `unit_location_id` = {$this->_dbId}");
1728
    }
1729
1730
//    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...
1731
//
1732
//    // Set time to travel to ACS' TTT
1733
//    $this->fleet->travelData['duration'] = $acsTimeToArrive;
1734
1735
1736
    $template_result['.']['fleets'][] = $this->renderFleet(SN_TIME_NOW, $timeMissionJob);
1737
1738
    $template_result += array(
1739
      'mission'         => classLocale::$lang['type_mission'][$this->_mission_type] . ($this->_mission_type == MT_EXPLORE || $this->_mission_type == MT_HOLD ? ' ' . pretty_time($timeMissionJob) : ''),
1740
      'dist'            => pretty_number($this->travelData['distance']),
1741
      'speed'           => pretty_number($this->travelData['fleet_speed']),
1742
      'deute_need'      => pretty_number($this->travelData['consumption']),
1743
      'from'            => "{$this->dbSourcePlanetRow['galaxy']}:{$this->dbSourcePlanetRow['system']}:{$this->dbSourcePlanetRow['planet']}",
1744
      'time_go'         => date(FMT_DATE_TIME, $this->_time_arrive_to_target),
1745
      'time_go_local'   => date(FMT_DATE_TIME, $this->_time_arrive_to_target + SN_CLIENT_TIME_DIFF),
1746
      'time_back'       => date(FMT_DATE_TIME, $this->_time_return_to_source),
1747
      'time_back_local' => date(FMT_DATE_TIME, $this->_time_return_to_source + SN_CLIENT_TIME_DIFF),
1748
    );
1749
1750
    $this->dbSourcePlanetRow = DBStaticPlanet::db_planet_by_id($this->dbSourcePlanetRow['id']);
1751
1752
    pdie('Stop for debug');
1753
1754
    sn_db_transaction_commit();
1755
1756
    $template = gettemplate('fleet3', true);
1757
    $template->assign_recursive($template_result);
1758
    display($template, classLocale::$lang['fl_title']);
1759
  }
1760
1761
  protected function groupCheck() {
1762
    if (empty($this->_group_id)) {
1763
      return;
1764
    }
1765
1766
    // ACS attack must exist (if acs fleet has arrived this will also return false (2 checks in 1!!!)
1767
    $this->acs = DBStaticFleetACS::db_acs_get_by_group_id($this->_group_id);
1768
    if (empty($this->acs)) {
1769
      $this->_group_id = 0;
1770
    } else {
1771
      $this->targetVector->convertToVector($this->acs);
1772
    }
1773
  }
1774
1775
1776
  /**
1777
   * @return array
1778
   */
1779
  protected function resourcesGetOnPlanet() {
1780
    $planetResources = array();
1781
1782
    $sn_group_resources = sn_get_groups('resources_loot');
1783
    foreach ($sn_group_resources as $resource_id) {
1784
      $planetResources[$resource_id] = floor(mrc_get_level($this->dbOwnerRow, $this->dbSourcePlanetRow, $resource_id) - ($resource_id == RES_DEUTERIUM ? $this->travelData['consumption'] : 0));
1785
    }
1786
1787
    return $planetResources;
1788
  }
1789
1790
  /**
1791
   */
1792
  public function captainGet() {
1793
    $this->captain = array();
1794
1795
    /**
1796
     * @var unit_captain $moduleCaptain
1797
     */
1798
    $moduleCaptain = !empty(sn_module::$sn_module['unit_captain']) ? sn_module::$sn_module['unit_captain'] : null;
1799
1800
    if (
1801
      !empty($moduleCaptain)
1802
      &&
1803
      $moduleCaptain->manifest['active']
1804
    ) {
1805
      $this->captain = $moduleCaptain->unit_captain_get($this->dbSourcePlanetRow['id']);
1806
    }
1807
  }
1808
1809
  /**
1810
   * @return array
1811
   */
1812
  protected function renderCaptain() {
1813
    $result = array();
1814
1815
    if (!empty($this->captain['unit_id']) && $this->captain['unit_location_type'] == LOC_PLANET) {
1816
      $result = array(
1817
        'CAPTAIN_ID'     => $this->captain['unit_id'],
1818
        'CAPTAIN_LEVEL'  => $this->captain['captain_level'],
1819
        'CAPTAIN_SHIELD' => $this->captain['captain_shield'],
1820
        'CAPTAIN_ARMOR'  => $this->captain['captain_armor'],
1821
        'CAPTAIN_ATTACK' => $this->captain['captain_attack'],
1822
      );
1823
    }
1824
1825
    return $result;
1826
  }
1827
1828
}
1829