Completed
Push — trunk ( 76e427...0e7f64 )
by SuperNova.WS
05:41
created

flt_t_send_fleet()   B

Complexity

Conditions 7
Paths 20

Size

Total Lines 56
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 24
nc 20
nop 7
dl 0
loc 56
rs 7.7489
c 1
b 0
f 0

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
use DBAL\OldDbChangeSet;
4
use Fleet\DbFleetStatic;
5
use Fleet\Fleet;
6
use Planet\DBStaticPlanet;
7
8
function flt_fleet_speed($user, $fleet, $shipData = []) {
9
  if (!is_array($fleet)) {
10
    $fleet = array($fleet => 1);
11
  }
12
13
  $speeds = array();
14
  if (!empty($fleet)) {
15
    foreach ($fleet as $ship_id => $amount) {
16
      if ($amount && in_array($ship_id, sn_get_groups(array('fleet', 'missile')))) {
17
        $single_ship_data = !empty($shipData[$ship_id]) ? $shipData[$ship_id] : get_ship_data($ship_id, $user);
18
        $speeds[] = $single_ship_data['speed'];
19
      }
20
    }
21
  }
22
23
  return empty($speeds) ? 0 : min($speeds);
24
}
25
26
function flt_get_galaxy_distance() {
27
  return SN::$config->uni_galaxy_distance ? SN::$config->uni_galaxy_distance : UNIVERSE_GALAXY_DISTANCE;
28
}
29
30
function flt_travel_distance($from, $to) {
31
  if ($from['galaxy'] != $to['galaxy']) {
32
    $distance = abs($from['galaxy'] - $to['galaxy']) * flt_get_galaxy_distance();
33
  } elseif ($from['system'] != $to['system']) {
34
    $distance = abs($from['system'] - $to['system']) * 5 * 19 + 2700;
35
  } elseif ($from['planet'] != $to['planet']) {
36
    $distance = abs($from['planet'] - $to['planet']) * 5 + 1000;
37
  } else {
38
    $distance = 5;
39
  }
40
41
  return $distance;
42
}
43
44
45
function fltDistanceAsGalaxy($distance) {
46
  return $distance ? $distance / flt_get_galaxy_distance() : 0;
47
}
48
49
function fltDistanceAsSystem($distance) {
50
  return $distance ? ($distance - 2700) / 5 / 19 : 0;
51
}
52
53
/**
54
 * @param int   $ship_id
55
 * @param int   $speed_percent
56
 * @param array $shipsData
57
 *
58
 * @return float|int
59
 */
60
function flt_get_max_distance($ship_id, $speed_percent = 100, $shipsData = []) {
61
  $single_ship_data = $shipsData[$ship_id];
62
63
  if (!$single_ship_data['capacity'] || !$single_ship_data['consumption']) {
64
    return 0;
65
  }
66
67
  return $distance = floor(($single_ship_data['capacity'] - 1) / $single_ship_data['consumption'] / pow($speed_percent / 100 + 1, 2) * 35000);
0 ignored issues
show
Unused Code introduced by
The assignment to $distance is dead and can be removed.
Loading history...
68
}
69
70
71
/**
72
 * @param         $user_row
73
 * @param         $from
74
 * @param         $to
75
 * @param         $fleet_array
76
 * @param int     $speed_percent
77
 * @param array[] $shipsData - prepared ships data to use in calculations
78
 *
79
 * @return array
80
 */
81
function flt_travel_data($user_row, $from, $to, $fleet_array, $speed_percent = 10, $shipsData = [], $distance = null) {
82
  $distance = $distance === null ? flt_travel_distance($from, $to) : $distance;
83
84
  $consumption = 0;
85
  $capacity = 0;
86
  $duration = 0;
87
88
  $game_fleet_speed = flt_server_flight_speed_multiplier();
89
  $fleet_speed = flt_fleet_speed($user_row, $fleet_array, $shipsData);
90
  if (!empty($fleet_array) && $fleet_speed && $game_fleet_speed) {
91
    $speed_percent = $speed_percent ? max(min($speed_percent, 10), 1) : 10;
92
    $real_speed = $speed_percent * sqrt($fleet_speed);
93
94
    $duration = max(1, round((35000 / $speed_percent * sqrt($distance * 10 / $fleet_speed) + 10) / $game_fleet_speed));
95
96
    foreach ($fleet_array as $ship_id => $ship_count) {
97
      if (!$ship_id || !$ship_count) {
98
        continue;
99
      }
100
101
      $single_ship_data = !empty($shipsData[$ship_id]) ? $shipsData[$ship_id] : get_ship_data($ship_id, $user_row);
102
      $single_ship_data['speed'] = $single_ship_data['speed'] < 1 ? 1 : $single_ship_data['speed'];
103
104
      $consumption += $single_ship_data['consumption'] * $ship_count * pow($real_speed / sqrt($single_ship_data['speed']) / 10 + 1, 2);
105
      $capacity += $single_ship_data['capacity'] * $ship_count;
106
    }
107
108
    $consumption = ceil($distance * $consumption / 35000) + 1;
109
  }
110
111
  return array(
112
    'fleet_speed'            => $fleet_speed,
113
    'distance'               => $distance,
114
    'duration'               => $duration,
115
    'consumption'            => $consumption,
116
    'capacity'               => $capacity,
117
    'hold'                   => $capacity - $consumption,
118
    'transport_effectivness' => $consumption ? $capacity / $consumption : 0,
119
  );
120
}
121
122
function flt_bashing_check($user, $enemy, $planet_dst, $mission, $flight_duration, $fleet_group = 0) {
123
  global $config;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
124
125
  $config_bashing_attacks = $config->fleet_bashing_attacks;
126
  $config_bashing_interval = $config->fleet_bashing_interval;
127
  if (!$config_bashing_attacks) {
128
    // Bashing allowed - protection disabled
129
    return ATTACK_ALLOWED;
130
  }
131
132
  $bashing_result = ATTACK_BASHING;
133
  if ($user['ally_id'] && $enemy['ally_id']) {
134
    $relations = ali_relations($user['ally_id'], $enemy['ally_id']);
135
    if (!empty($relations)) {
136
      $relations = $relations[$enemy['ally_id']];
137
      switch ($relations['alliance_diplomacy_relation']) {
138
        case ALLY_DIPLOMACY_WAR:
139
          if (SN_TIME_NOW - $relations['alliance_diplomacy_time'] <= $config->fleet_bashing_war_delay) {
140
            $bashing_result = ATTACK_BASHING_WAR_DELAY;
141
          } else {
142
            return ATTACK_ALLOWED;
143
          }
144
        break;
145
        // Here goes other relations
146
147
        /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% 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...
148
                default:
149
                  return ATTACK_ALLOWED;
150
                break;
151
        */
152
      }
153
    }
154
  }
155
156
  $time_limit = SN_TIME_NOW + $flight_duration - $config->fleet_bashing_scope;
157
  $bashing_list = array(SN_TIME_NOW);
158
159
  // Retrieving flying fleets
160
  $bashing_fleet_list = DbFleetStatic::fleet_list_bashing($user['id'], $planet_dst);
161
  foreach ($bashing_fleet_list as $fleet_row) {
162
    // Checking for ACS - each ACS count only once
163
    if ($fleet_row['fleet_group']) {
164
      $bashing_list["{$user['id']}_{$fleet_row['fleet_group']}"] = $fleet_row['fleet_start_time'];
165
    } else {
166
      $bashing_list[] = $fleet_row['fleet_start_time'];
167
    }
168
  }
169
170
  // Check for joining to ACS - if there are already fleets in ACS no checks should be done
171
  if ($mission == MT_AKS && $bashing_list["{$user['id']}_{$fleet_group}"]) {
172
    return ATTACK_ALLOWED;
173
  }
174
175
  $query = doquery("SELECT bashing_time FROM `{{bashing}}` WHERE bashing_user_id = {$user['id']} AND bashing_planet_id = {$planet_dst['id']} AND bashing_time >= {$time_limit};");
176
  while ($bashing_row = db_fetch($query)) {
177
    $bashing_list[] = $bashing_row['bashing_time'];
178
  }
179
180
  sort($bashing_list);
181
182
  $last_attack = 0;
183
  $wave = 0;
184
  $attack = 1;
185
  foreach ($bashing_list as &$bash_time) {
186
    $attack++;
187
    if ($bash_time - $last_attack > $config_bashing_interval || $attack > $config_bashing_attacks) {
188
      $attack = 1;
189
      $wave++;
190
    }
191
192
    $last_attack = $bash_time;
193
  }
194
195
  return ($wave > $config->fleet_bashing_waves ? $bashing_result : ATTACK_ALLOWED);
196
}
197
198
/**
199
 * @param array $planet_src - source planet record/vector
200
 * @param array $planet_dst - destination planet record/vector
201
 * @param array $fleet      - array of ship amount [(int)shipId => (float)shipAmount]
202
 * @param int   $mission    - Mission ID
203
 * @param array $options    - [
204
 *                          'resources' => (float),
205
 *                          'fleet_speed_percent' => (int)1..10
206
 *                          'fleet_group' => (int|string)
207
 *                          'flying_fleets' => (int)
208
 *                          'target_structure' => (int) - targeted defense structure snID for MISSILE missions
209
 *                          'stay_time' => (int) - stay HOURS
210
 *                          ]
211
 *
212
 * @return int
213
 */
214
function flt_can_attack($planet_src, $planet_dst, $fleet = [], $mission, $options = []) {
215
  $result = null;
216
217
  return sn_function_call('flt_can_attack', [$planet_src, $planet_dst, $fleet, $mission, $options, &$result]);
218
}
219
220
/**
221
 * @param array $planet_src
222
 * @param array $planet_dst
223
 * @param array $fleet
224
 * @param int   $mission
225
 * @param array $options
226
 * @param int   $result
227
 *
228
 * @return int
229
 * @see flt_can_attack()
230
 */
231
function sn_flt_can_attack($planet_src, $planet_dst, $fleet = [], $mission, $options = [], &$result) {
232
  //TODO: try..catch
233
  global $config, $user;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
234
235
  if ($user['vacation']) {
236
    return $result = ATTACK_OWN_VACATION;
237
  }
238
239
  if (empty($fleet) || !is_array($fleet)) {
240
    return $result = ATTACK_NO_FLEET;
241
  }
242
243
  !is_array($options) ? $options = [] : false;
0 ignored issues
show
introduced by
The condition is_array($options) is always true.
Loading history...
244
245
  $sn_groups_mission = sn_get_groups('missions');
246
  if (!isset($sn_groups_mission[$mission])) {
247
    return $result = ATTACK_MISSION_ABSENT;
248
  }
249
  $sn_data_mission = $sn_groups_mission[$mission];
250
251
//TODO: Проверка на отстуствие ресурсов в нетранспортных миссиях (Транспорт, Передислокация, Колонизация)
252
253
  //TODO: Проверка на наличие ресурсов при Транспорте
254
  // TODO: Проверка на отрицательные ресурсы при транспорте
255
  // TODO: Проверка на перегрузку при транспорте
256
257
  // TODO: В ракетных миссиях могут лететь только ракеты
258
  // TODO: В неракетных миссиях ракеты должны отсутствовать
259
  $ships = 0;
260
  $recyclers = 0;
261
  $spies = 0;
262
  $resources = 0;
263
  $ship_ids = sn_get_groups('fleet');
264
  $resource_ids = sn_get_groups('resources_loot');
265
  foreach ($fleet as $ship_id => $ship_count) {
266
    $is_ship = in_array($ship_id, $ship_ids);
267
    $is_resource = in_array($ship_id, $resource_ids);
268
    if (!$is_ship && !$is_resource) {
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...
269
      // TODO Спецобработчик для Капитана и модулей
270
//      return ATTACK_WRONG_UNIT;
271
    }
272
273
    if ($ship_count < 0) {
274
      return $result = $is_ship ? ATTACK_SHIP_COUNT_WRONG : ATTACK_RESOURCE_COUNT_WRONG;
275
    }
276
277
    if ($ship_count > mrc_get_level($user, $planet_src, $ship_id)) {
278
      // TODO ATTACK_NO_MISSILE
279
      return $result = $is_ship ? ATTACK_NO_SHIPS : ATTACK_NO_RESOURCES;
280
    }
281
282
    if ($is_ship) {
283
      $single_ship_data = get_ship_data($ship_id, $user);
284
      if ($single_ship_data[P_SPEED] <= 0) {
285
        return $result = ATTACK_ZERO_SPEED;
286
      }
287
      $ships += $ship_count;
288
      $recyclers += in_array($ship_id, sn_get_groups('flt_recyclers')) ? $ship_count : 0;
289
      $spies += $ship_id == SHIP_SPY ? $ship_count : 0;
290
    } elseif ($is_resource) {
291
      $resources += $ship_count;
292
    }
293
  }
294
  /*
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...
295
    if($ships <= 0)
296
    {
297
      return ATTACK_NO_FLEET;
298
    }
299
  */
300
301
  if (isset($options['resources']) && $options['resources'] > 0 && !(isset($sn_data_mission['transport']) && $sn_data_mission['transport'])) {
302
    return $result = ATTACK_RESOURCE_FORBIDDEN;
303
  }
304
305
  /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% 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...
306
    elseif($mission == MT_TRANSPORT)
307
    {
308
      return ATTACK_TRANSPORT_EMPTY;
309
    }
310
  */
311
312
  $speed = $options['fleet_speed_percent'];
313
  if ($speed && ($speed != intval($speed) || $speed < 1 || $speed > 10)) {
314
    return $result = ATTACK_WRONG_SPEED;
315
  }
316
317
  $travel_data = flt_travel_data($user, $planet_src, $planet_dst, $fleet, $options['fleet_speed_percent']);
318
319
320
  if (mrc_get_level($user, $planet_src, RES_DEUTERIUM) < $fleet[RES_DEUTERIUM] + $travel_data['consumption']) {
321
    return $result = ATTACK_NO_FUEL;
322
  }
323
324
  if ($travel_data['consumption'] > $travel_data['capacity']) {
325
    return $result = ATTACK_TOO_FAR;
326
  }
327
328
  if ($travel_data['hold'] < $resources) {
329
    return $result = ATTACK_OVERLOADED;
330
  }
331
332
  $fleet_start_time = SN_TIME_NOW + $travel_data['duration'];
333
334
  $fleet_group = $options['fleet_group'];
335
  if ($fleet_group) {
336
    if ($mission != MT_AKS) {
337
      return $result = ATTACK_WRONG_MISSION;
338
    };
339
340
    $acs = doquery("SELECT * FROM `{{aks}}` WHERE id = '{$fleet_group}' LIMIT 1;", '', true);
341
    if (!$acs['id']) {
342
      return $result = ATTACK_NO_ACS;
343
    }
344
345
    if ($planet_dst['galaxy'] != $acs['galaxy'] || $planet_dst['system'] != $acs['system'] || $planet_dst['planet'] != $acs['planet'] || $planet_dst['planet_type'] != $acs['planet_type']) {
346
      return $result = ATTACK_ACS_WRONG_TARGET;
347
    }
348
349
    if ($fleet_start_time > $acs['ankunft']) {
350
      return $result = ATTACK_ACS_TOO_LATE;
351
    }
352
  }
353
354
  $flying_fleets = $options['flying_fleets'];
355
  if (!$flying_fleets) {
356
//    $flying_fleets = doquery("SELECT COUNT(fleet_id) AS `flying_fleets` FROM {{fleets}} WHERE `fleet_owner` = '{$user['id']}';", '', true);
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...
357
//    $flying_fleets = $flying_fleets['flying_fleets'];
358
    $flying_fleets = DbFleetStatic::fleet_count_flying($user['id']);
359
  }
360
  if (GetMaxFleets($user) <= $flying_fleets && $mission != MT_MISSILE) {
361
    return $result = ATTACK_NO_SLOTS;
362
  }
363
364
  // В одиночку шпионские зонды могут летать только в миссии Шпионаж, Передислокация и Транспорт
365
  if ($ships && $spies && $spies == $ships && !($mission == MT_SPY || $mission == MT_RELOCATE || $mission == MT_TRANSPORT)) {
366
    return $result = ATTACK_SPIES_LONLY;
367
  }
368
369
  // Checking for no planet
370
  if (!$planet_dst['id_owner']) {
371
    if ($mission == MT_COLONIZE && !$fleet[SHIP_COLONIZER]) {
372
      return $result = ATTACK_NO_COLONIZER;
373
    }
374
375
    if ($mission == MT_EXPLORE || $mission == MT_COLONIZE) {
376
      return $result = ATTACK_ALLOWED;
377
    }
378
379
    return $result = ATTACK_NO_TARGET;
380
  }
381
382
  if ($mission == MT_RECYCLE) {
383
    if ($planet_dst['debris_metal'] + $planet_dst['debris_crystal'] <= 0) {
384
      return $result = ATTACK_NO_DEBRIS;
385
    }
386
    if ($recyclers <= 0) {
387
      return $result = ATTACK_NO_RECYCLERS;
388
    }
389
390
    return $result = ATTACK_ALLOWED;
391
  }
392
393
  // Got planet. Checking if it is ours
394
  if ($planet_dst['id_owner'] == $user['id']) {
395
    if ($mission == MT_TRANSPORT || $mission == MT_RELOCATE) {
396
      return $result = ATTACK_ALLOWED;
397
    }
398
399
    return $planet_src['id'] == $planet_dst['id'] ? ATTACK_SAME : ATTACK_OWN;
400
  }
401
402
  // No, planet not ours. Cutting mission that can't be send to not-ours planet
403
  if ($mission == MT_RELOCATE || $mission == MT_COLONIZE || $mission == MT_EXPLORE) {
404
    return $result = ATTACK_WRONG_MISSION;
405
  }
406
407
  $enemy = db_user_by_id($planet_dst['id_owner']);
0 ignored issues
show
Deprecated Code introduced by
The function db_user_by_id() has been deprecated. ( Ignorable by Annotation )

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

407
  $enemy = /** @scrutinizer ignore-deprecated */ db_user_by_id($planet_dst['id_owner']);
Loading history...
408
  // We cannot attack or send resource to users in VACATION mode
409
  if ($enemy['vacation'] && $mission != MT_RECYCLE) {
410
    return $result = ATTACK_VACATION;
411
  }
412
413
  // Multi IP protection
414
  // TODO: Here we need a procedure to check proxies
415
  if (sys_is_multiaccount($user, $enemy)) {
416
    return $result = ATTACK_SAME_IP;
417
  }
418
419
  $user_points = $user['total_points'];
420
  $enemy_points = $enemy['total_points'];
421
422
  // Is it transport? If yes - checking for buffing to prevent mega-alliance destroyer
423
  if ($mission == MT_TRANSPORT) {
424
    if ($user_points >= $enemy_points || $config->allow_buffing) {
425
      return $result = ATTACK_ALLOWED;
426
    } else {
427
      return $result = ATTACK_BUFFING;
428
    }
429
  }
430
431
  // Only aggresive missions passed to this point. HOLD counts as passive but aggresive
432
433
  // Is it admin with planet protection?
434
  if ($planet_dst['id_level'] > $user['authlevel']) {
435
    return $result = ATTACK_ADMIN;
436
  }
437
438
  // Okay. Now skipping protection checks for inactive longer then 1 week
439
  if (!$enemy['onlinetime'] || $enemy['onlinetime'] >= (SN_TIME_NOW - 60 * 60 * 24 * 7)) {
440
    if (
441
      (SN::$gc->general->playerIsNoobByPoints($enemy_points) && !SN::$gc->general->playerIsNoobByPoints($user_points))
442
      ||
443
      (SN::$gc->general->playerIs1stStrongerThen2nd($user_points, $enemy_points))
444
    ) {
445
      if ($mission != MT_HOLD) {
446
        return $result = ATTACK_NOOB;
447
      }
448
      if ($mission == MT_HOLD && !($user['ally_id'] && $user['ally_id'] == $enemy['ally_id'] && $config->ally_help_weak)) {
449
        return $result = ATTACK_NOOB;
450
      }
451
    }
452
  }
453
454
  // Is it HOLD mission? If yes - there should be ally deposit
455
  if ($mission == MT_HOLD) {
456
    if (mrc_get_level($user, $planet_dst, STRUC_ALLY_DEPOSIT)) {
457
      return $result = ATTACK_ALLOWED;
458
    }
459
460
    return $result = ATTACK_NO_ALLY_DEPOSIT;
461
  }
462
463
  if ($mission == MT_SPY) {
464
    return $result = $spies >= 1 ? ATTACK_ALLOWED : ATTACK_NO_SPIES;
465
  }
466
467
  // Is it MISSILE mission?
468
  if ($mission == MT_MISSILE) {
469
    $sn_data_mip = get_unit_param(UNIT_DEF_MISSILE_INTERPLANET);
470
    if (mrc_get_level($user, $planet_src, STRUC_SILO) < $sn_data_mip[P_REQUIRE][STRUC_SILO]) {
471
      return $result = ATTACK_NO_SILO;
472
    }
473
474
    if (!$fleet[UNIT_DEF_MISSILE_INTERPLANET]) {
475
      return $result = ATTACK_NO_MISSILE;
476
    }
477
478
    $distance = abs($planet_dst['system'] - $planet_src['system']);
479
    $mip_range = flt_get_missile_range($user);
480
    if ($distance > $mip_range || $planet_dst['galaxy'] != $planet_src['galaxy']) {
481
      return $result = ATTACK_MISSILE_TOO_FAR;
482
    }
483
484
    if (isset($options['target_structure']) && $options['target_structure'] && !in_array($options['target_structure'], sn_get_groups('defense_active'))) {
485
      return $result = ATTACK_WRONG_STRUCTURE;
486
    }
487
  }
488
489
  if ($mission == MT_DESTROY && $planet_dst['planet_type'] != PT_MOON) {
490
    return $result = ATTACK_WRONG_MISSION;
491
  }
492
493
  if ($mission == MT_ATTACK || $mission == MT_AKS || $mission == MT_DESTROY) {
494
    return $result = flt_bashing_check($user, $enemy, $planet_dst, $mission, $travel_data['duration'], $fleet_group);
495
  }
496
497
  return $result = ATTACK_ALLOWED;
498
}
499
500
/**
501
 * @param array $user    - actual user record
502
 * @param array $from    - actual planet record
503
 * @param array $to      - actual planet record
504
 * @param array $fleet   - array of records $unit_id -> $amount
505
 * @param int   $mission - fleet mission
506
 * @param array $options
507
 *
508
 * @return int
509
 * @throws Exception
510
 * @see flt_can_attack()
511
 */
512
function flt_t_send_fleet($user, &$from, $to, $fleet, $resources, $mission, $options = array()) {
513
  $internal_transaction = !sn_db_transaction_check(false) ? sn_db_transaction_start() : false;
514
515
  // TODO Потенциальный дедлок - если успела залочится запись пользователя - хозяина планеты
516
  $user = db_user_by_id($user['id'], true);
0 ignored issues
show
Deprecated Code introduced by
The function db_user_by_id() has been deprecated. ( Ignorable by Annotation )

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

516
  $user = /** @scrutinizer ignore-deprecated */ db_user_by_id($user['id'], true);
Loading history...
517
  $from = sys_o_get_updated($user, $from['id'], SN_TIME_NOW);
518
  $from = $from['planet'];
519
520
//  $fleet = [
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...
521
//    202 => 1,
522
//  ];
523
//  $resources = [
524
//    901 => 1,
525
//  ];
526
//  var_dump($fleet);
527
//  var_dump($resources);
528
//  var_dump(mrc_get_level($user, $from, 202));
529
//  var_dump($from['metal']);
530
//  var_dump($from['deuterium']);
531
//  die();
532
533
534
  $can_attack = flt_can_attack($from, $to, $fleet, $mission, $options);
535
  if ($can_attack != ATTACK_ALLOWED) {
536
    $internal_transaction ? sn_db_transaction_rollback() : false;
537
538
    return $can_attack;
539
  }
540
541
  empty($options['fleet_speed_percent']) ? $options['fleet_speed_percent'] = 10 : false;
542
  $options['stay_time'] = !empty($options['stay_time']) ? $options['stay_time'] * PERIOD_HOUR : 0;
543
544
  $fleetObj = new Fleet();
545
  $travel_data = $fleetObj
546
    ->setMission($mission)
547
    ->setSourceFromPlanetRecord($from)
548
    ->setDestinationFromPlanetRecord($to)
549
    ->setUnits($fleet)
550
    ->setSpeedPercentInTenth($options['fleet_speed_percent'])
551
    ->calcTravelTimes(SN_TIME_NOW, $options['stay_time']);
552
  $fleetObj->save();
553
554
  $result = fltSendFleetAdjustPlanetResources($from['id'], $resources, $travel_data['consumption']);
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
555
556
  $result = fltSendFleetAdjustPlanetUnits($user, $from['id'], $fleet);
557
558
  $internal_transaction ? sn_db_transaction_commit() : false;
559
560
  $from = DBStaticPlanet::db_planet_by_id($from['id']);
561
562
//  var_dump(mrc_get_level($user, $from, 202));
0 ignored issues
show
Unused Code Comprehensibility introduced by
69% 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...
563
//  var_dump($from['metal']);
564
//  var_dump($from['deuterium']);
565
//  die();
566
567
  return ATTACK_ALLOWED;
568
}
569
570
/**
571
 * @param array      $user
572
 * @param int|string $fromId
573
 * @param float[]    $fleet - [(int)shipId => (float)count]
574
 *
575
 * @return bool
576
 */
577
function fltSendFleetAdjustPlanetUnits($user, $fromId, $fleet) {
578
  $result = [];
579
580
  foreach ($fleet as $unit_id => $amount) {
581
    if (floatval($amount) >= 1 && intval($unit_id) && in_array($unit_id, sn_get_groups('fleet'))) {
582
      $result[] = OldDbChangeSet::db_changeset_prepare_unit($unit_id, -$amount, $user, $fromId);
0 ignored issues
show
Deprecated Code introduced by
The function DBAL\OldDbChangeSet::db_changeset_prepare_unit() has been deprecated. ( Ignorable by Annotation )

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

582
      $result[] = /** @scrutinizer ignore-deprecated */ OldDbChangeSet::db_changeset_prepare_unit($unit_id, -$amount, $user, $fromId);
Loading history...
583
    }
584
  }
585
586
  return OldDbChangeSet::db_changeset_apply(['unit' => $result]);
0 ignored issues
show
Deprecated Code introduced by
The function DBAL\OldDbChangeSet::db_changeset_apply() has been deprecated. ( Ignorable by Annotation )

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

586
  return /** @scrutinizer ignore-deprecated */ OldDbChangeSet::db_changeset_apply(['unit' => $result]);
Loading history...
587
}
588
589
/**
590
 * @param int|string $fromId      - Source planet ID
591
 * @param array      $resources   - Array of resources to transfer [(int)resourceId => (float)amount]
592
 * @param int|float  $consumption - Fleet consumption
593
 *
594
 * @return bool
595
 *
596
 * @throws Exception
597
 */
598
function fltSendFleetAdjustPlanetResources($fromId, $resources, $consumption) {
599
  $planetObj = SN::$gc->repoV2->getPlanet($fromId);
600
601
  $planetObj->changeResource(RES_DEUTERIUM, -$consumption);
602
603
  foreach ($resources as $resource_id => $amount) {
604
    if (floatval($amount) >= 1 && intval($resource_id) && in_array($resource_id, sn_get_groups('resources_loot'))) {
605
      $planetObj->changeResource($resource_id, -$amount);
606
    }
607
  }
608
609
  return $planetObj->save();
610
}
611
612
function flt_calculate_ship_to_transport_sort($a, $b) {
613
  return $a['transport_effectivness'] == $b['transport_effectivness'] ? 0 : ($a['transport_effectivness'] > $b['transport_effectivness'] ? -1 : 1);
614
}
615
616
// flt_calculate_ship_to_transport - calculates how many ships need to transport pointed amount of resources
617
// $ship_list - list of available ships
618
// $resource_amount - how much amount of resources need to be transported
619
// $from - transport from
620
// $to - transport to
621
function flt_calculate_fleet_to_transport($ship_list, $resource_amount, $from, $to) {
622
  global $user;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
623
624
  $ship_data = array();
625
  $fleet_array = array();
626
  foreach ($ship_list as $transport_id => $cork) {
627
    $ship_data[$transport_id] = flt_travel_data($user, $from, $to, array($transport_id => 1), 10);
628
  }
629
  uasort($ship_data, 'flt_calculate_ship_to_transport_sort');
630
631
  $fleet_hold = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $fleet_hold is dead and can be removed.
Loading history...
632
  $fleet_capacity = 0;
633
  $fuel_total = $fuel_left = mrc_get_level($user, $from, RES_DEUTERIUM);
634
  foreach ($ship_data as $transport_id => &$ship_info) {
635
    $ship_loaded = min($ship_list[$transport_id], ceil($resource_amount / $ship_info['hold']), floor($fuel_left / $ship_info['consumption']));
636
    if ($ship_loaded) {
637
      $fleet_array[$transport_id] = $ship_loaded;
638
      $resource_amount -= min($resource_amount, $ship_info['hold'] * $ship_loaded);
639
      $fuel_left -= $ship_info['consumption'] * $ship_loaded;
640
641
      $fleet_capacity += $ship_info['capacity'] * $ship_loaded;
642
    }
643
  }
644
645
  return array('fleet' => $fleet_array, 'ship_data' => $ship_data, 'capacity' => $fleet_capacity, 'consumption' => $fuel_total - $fuel_left);
646
}
647