Completed
Pull Request — master (#329)
by De Cramer
03:46
created

Dedimania::__construct()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 35
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 33
nc 1
nop 15
dl 0
loc 35
rs 8.8571
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: php_r
5
 * Date: 27.2.2018
6
 * Time: 10.50
7
 */
8
9
namespace eXpansionExperimantal\Bundle\Dedimania\Plugins;
10
11
use eXpansionExperimantal\Bundle\Dedimania\Classes\IXR_Base64;
12
use eXpansionExperimantal\Bundle\Dedimania\Classes\Request;
13
use eXpansionExperimantal\Bundle\Dedimania\Services\DedimaniaService;
14
use eXpansionExperimantal\Bundle\Dedimania\Structures\DedimaniaPlayer;
15
use eXpansionExperimantal\Bundle\Dedimania\Structures\DedimaniaRecord;
16
use eXpansion\Framework\Config\Model\ConfigInterface;
17
use eXpansion\Framework\Core\DataProviders\Listener\ListenerInterfaceExpTimer;
18
use eXpansion\Framework\Core\Helpers\ChatNotification;
19
use eXpansion\Framework\Core\Helpers\FileSystem;
20
use eXpansion\Framework\Core\Helpers\Time;
21
use eXpansion\Framework\Core\Helpers\TMString;
22
use eXpansion\Framework\Core\Plugins\StatusAwarePluginInterface;
23
use eXpansion\Framework\Core\Services\Application\AbstractApplication;
24
use eXpansion\Framework\Core\Services\Console;
25
use eXpansion\Framework\Core\Services\DedicatedConnection\Factory;
26
use eXpansion\Framework\Core\Storage\Data\Player as DedicatedPlayer;
27
use eXpansion\Framework\Core\Storage\GameDataStorage;
28
use eXpansion\Framework\Core\Storage\MapStorage;
29
use eXpansion\Framework\Core\Storage\PlayerStorage;
30
use eXpansion\Framework\GameManiaplanet\DataProviders\Listener\ListenerInterfaceMpLegacyPlayer;
31
use eXpansion\Framework\GameManiaplanet\DataProviders\Listener\ListenerInterfaceMpScriptMap;
32
use eXpansion\Framework\GameManiaplanet\DataProviders\Listener\ListenerInterfaceMpScriptMatch;
33
use eXpansion\Framework\GameManiaplanet\ScriptMethods\GetScores;
34
use eXpansion\Framework\GameTrackmania\DataProviders\Listener\ListenerInterfaceRaceData;
35
use eXpansion\Framework\Notifications\Services\Notifications;
36
use Maniaplanet\DedicatedServer\Connection;
37
use Maniaplanet\DedicatedServer\Structures\Map;
38
use Maniaplanet\DedicatedServer\Structures\Player;
39
use Maniaplanet\DedicatedServer\Xmlrpc\Request as XmlRpcRequest;
40
41
42
class Dedimania implements StatusAwarePluginInterface, ListenerInterfaceExpTimer, ListenerInterfaceMpScriptMap, ListenerInterfaceMpScriptMatch, ListenerInterfaceRaceData, ListenerInterfaceMpLegacyPlayer
43
{
44
    const dedimaniaUrl = "http://dedimania.net:8081/Dedimania";
45
46
    /**
47
     * @var DedimaniaService
48
     */
49
    private $dedimaniaService;
50
    /**
51
     * @var ConfigInterface
52
     */
53
    private $enabled;
54
    /**
55
     * @var ConfigInterface
56
     */
57
    private $apikey;
58
    /**
59
     * @var ConfigInterface
60
     */
61
    private $serverLogin;
62
63
    private $read = [];
64
    private $write = [];
65
    private $except = [];
66
67
    /** @var \Webaccess */
68
    protected $webaccess;
69
    /**
70
     * @var Console
71
     */
72
    private $console;
73
    /** @var int */
74
    private $tryTimer = -1;
75
76
    /** @var int */
77
    private $lastUpdate;
78
    /** @var string|null */
79
    private $sessionId = null;
80
    private $titles;
81
    /**
82
     * @var Connection
83
     */
84
    private $connection;
0 ignored issues
show
Unused Code introduced by
The property $connection is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
85
    /**
86
     * @var GameDataStorage
87
     */
88
    private $gameDataStorage;
89
    /**
90
     * @var MapStorage
91
     */
92
    private $mapStorage;
93
    /**
94
     * @var PlayerStorage
95
     */
96
    private $playerStorage;
97
    /**
98
     * @var Notifications
99
     */
100
    private $notifications;
101
    /**
102
     * @var Time
103
     */
104
    private $time;
105
    /**
106
     * @var GetScores
107
     */
108
    private $getScores;
109
    /**
110
     * @var FileSystem
111
     */
112
    private $fileSystem;
113
114
    /** @var ChatNotification */
115
    private $chatNotification;
116
117
    /** @var Factory */
118
    private $factory;
119
120
121
    /**
122
     * Dedimania constructor.
123
     * @param                  $titles
124
     * @param ConfigInterface  $enabled
125
     * @param ConfigInterface  $apikey
126
     * @param ConfigInterface  $serverLogin
127
     * @param DedimaniaService $dedimaniaService
128
     * @param Console          $console
129
     * @param Factory          $connectionFactory
130
     * @param GameDataStorage  $gameDataStorage
131
     * @param MapStorage       $mapStorage
132
     * @param PlayerStorage    $playerStorage
133
     * @param Notifications    $notifications
134
     * @param Time             $time
135
     * @param GetScores        $getScores
136
     * @param FileSystem       $fileSystem
137
     * @param ChatNotification $chatNotification
138
     */
139
    public function __construct(
140
        $titles,
141
        ConfigInterface $enabled,
142
        ConfigInterface $apikey,
143
        ConfigInterface $serverLogin,
144
        DedimaniaService $dedimaniaService,
145
        Console $console,
146
        Factory $connectionFactory,
147
        GameDataStorage $gameDataStorage,
148
        MapStorage $mapStorage,
149
        PlayerStorage $playerStorage,
150
        Notifications $notifications,
151
        Time $time,
152
        GetScores $getScores,
153
        FileSystem $fileSystem,
154
        ChatNotification $chatNotification
155
    ) {
156
        require_once(dirname(__DIR__).DIRECTORY_SEPARATOR."Classes".DIRECTORY_SEPARATOR."Webaccess.php");
157
        $this->webaccess = new \Webaccess($console);
158
        $this->console = $console;
159
        $this->dedimaniaService = $dedimaniaService;
160
        $this->enabled = $enabled;
161
        $this->apikey = $apikey;
162
        $this->serverLogin = $serverLogin;
163
        $this->titles = $titles;
164
        $this->factory = $connectionFactory;
165
        $this->gameDataStorage = $gameDataStorage;
166
        $this->mapStorage = $mapStorage;
167
        $this->playerStorage = $playerStorage;
168
        $this->notifications = $notifications;
169
        $this->time = $time;
170
        $this->getScores = $getScores;
171
        $this->fileSystem = $fileSystem;
172
        $this->chatNotification = $chatNotification;
173
    }
174
175
    /**
176
     * Set the status of the plugin
177
     *
178
     * @param boolean $status
179
     *
180
     * @return void
181
     * @throws \Exception
182
     */
183
    public function setStatus($status)
184
    {
185
        if ($status && $this->enabled->get()) {
186
            try {
187
                $this->lastUpdate = time();
188
                $this->openSession($this->serverLogin->get(), $this->apikey->get());
189
            } catch (\Exception $e) {
190
                echo $e->getMessage();
191
            }
192
        }
193
    }
194
195
196
    /** @api */
197
    public function onPreLoop()
198
    {
199
        // do nothing
200
    }
201
202
    /** @api */
203
    public function onPostLoop()
204
    {
205
        try {
206
            if ($this->tryTimer == -1) {
207
                $this->webaccess->select($this->read, $this->write, $this->except, 0, 0);
208
            } else {
209
                if (time() >= $this->tryTimer) {
210
                    $this->console->writeln("Webaccess: Main Loop active again!");
211
                    $this->tryTimer = -1;
212
                }
213
            }
214
        } catch (\Exception $e) {
215
            $this->console->writeln(
216
                'Webaccess: OnTick Update $f00failed$555, trying to retry in 2 seconds...');
217
            $this->tryTimer = time() + 2;
218
        }
219
    }
220
221
    /** @api */
222
    public function onEverySecond()
223
    {
224
        try {
225
            if ($this->sessionId !== null && (time() - $this->lastUpdate) > 3 * 60) {
226
                $this->lastUpdate = time();
227
                $this->console->writeln("Dedimania: sent connection keep-alive!");
228
                $this->updateServerPlayers();
229
            }
230
        } catch (\Exception $e) {
231
            $this->console->writeln("Dedimania: periodic keep-alive failed: ".$e->getMessage());
232
        }
233
    }
234
235
236
    /**
237
     * Send a request to Dedimania
238
     *
239
     * @param Request  $request
240
     * @param callable $callback
241
     */
242
    final public function sendRequest(Request $request, $callback)
243
    {
244
        $this->webaccess->request(
245
            self::dedimaniaUrl,
246
            [[$this, "process"], $callback],
247
            $request->getXml(),
248
            true,
249
            600,
250
            3,
251
            5,
252
            'eXpansion server controller',
253
            'application/x-www-form-urlencoded; charset=UTF-8'
254
        );
255
    }
256
257
    final public function process($response, $callback)
258
    {
259
260
        try {
261
262
            if (is_array($response) && array_key_exists('Message', $response)) {
263
264
                $message = [];
265
                try {
266
                    if (isset($response['Message'])) {
267
                        $message = XmlRpcRequest::decode($response['Message']);
268
                    } else {
269
                        $this->console->writeln("Dedimania: Error received non-xmlrpc string. See dump below:");
270
                        $this->console->writeln(Console::error.$response);
271
                    }
272
                } catch (\Exception $ex) {
273
                    $this->console->writeln("Dedimania: Error received non-xmlrpc string. See dump below:");
274
                    $this->console->writeln(Console::error.$response['Message']);
275
276
                    return;
277
                }
278
                $errors = end($message[1]);
279
                $err = false;
280
281
282
                if (count($errors) > 0 && array_key_exists('methods', $errors[0])) {
283
                    $err = false;
284
                    foreach ($errors[0]['methods'] as $error) {
285
                        if (!empty($error['errors'])) {
286
                            $this->console->writeln('Dedimania error on method: $fff'.$error['methodName']);
287
                            $this->console->writeln('$f00'.$error['errors']);
288
                            $err = true;
289
                        }
290
                    }
291
                }
292
                if ($err) {
293
                    return;
294
                }
295
296
                $array = $message[1];
297
                unset($array[count($array) - 1]); // remove trailing errors and info
298
299
                if (array_key_exists("faultString", $array[0])) {
300
                    $this->console->writeln('Dedimania fault:$f00 '.$array[0]['faultString']);
301
302
                    return;
303
                }
304
305
                if (!empty($array[0][0]['Error'])) {
306
                    $this->console->writeln('Dedimania error:$f00 '.$array[0][0]['Error']);
307
308
                    return;
309
                }
310
311
                if (sizeof($array) == 1) {
312
                    call_user_func_array($callback, [$array[0][0]]);
313
                } elseif (sizeof($array) > 1) {
314
                    $out = [];
315
                    foreach ($array as $key => $value) {
316
                        $out[] = $value[0];
317
                    }
318
                    call_user_func_array($callback, [$out]);
319
                }
320
321
                return;
322
            } else {
323
                $this->console->writeln('Dedimania Error: $f00Can\'t find Message from Dedimania reply');
324
            }
325
        } catch (\Exception $e) {
326
            $this->console->writeln('Dedimania Error: $f00Connection to dedimania server failed.'.$e->getMessage()." trace:".$e->getTraceAsString());
327
        }
328
    }
329
330
    //#region public dedimania methods
331
332
    /**
333
     * @param string $serverlogin
334
     * @param string $apikey
335
     * @throws \Exception
336
     *
337
     */
338
    public function openSession($serverlogin, $apikey)
339
    {
340
        $this->sessionId = null;
341
        $server = new Player();
342
        $server->login = $this->gameDataStorage->getSystemInfo()->serverLogin;
343
344
        $info = $this->factory->getConnection()->getDetailedPlayerInfo($server);
345
346
        $packMask = $this->getPackMask($this->gameDataStorage->getVersion()->titleId);
347
        if (!$packMask) {
348
            throw new \Exception("Packmask not found for titleId");
349
        }
350
        $params = [
351
            "Game" => "TM2",
352
            "Login" => $serverlogin,
353
            "Code" => $apikey,
354
            "Path" => $info->path,
355
            "Packmask" => $packMask,
356
            "ServerVersion" => $this->gameDataStorage->getVersion()->version,
357
            "ServerBuild" => $this->gameDataStorage->getVersion()->build,
358
            "Tool" => "eXpansion",
359
            "Version" => AbstractApplication::EXPANSION_VERSION,
360
            "ServerIp" => $this->gameDataStorage->getSystemInfo()->publishedIp,
361
        ];
362
363
        $request = new Request('dedimania.OpenSession', [$params]);
364
365
        $this->sendRequest($request, function ($response) {
366
            $this->sessionId = $response['SessionId'];
367
            $this->getRecords();
368
            $this->connectAllPlayers();
369
        });
370
    }
371
372
    public function getRecords()
373
    {
374
        if ($this->sessionId == null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $this->sessionId of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
375
            return;
376
        }
377
378
        $map = $this->mapStorage->getCurrentMap();
379
380
        $this->dedimaniaService->setDisabled(true);
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a string|false.

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...
381
        $this->dedimaniaService->setDedimaniaRecords([]);
382
383
        if ($map->authorTime < 6200) {
384
            $status = "Times under 6.2s are refused!";
385
            $this->console->writeln("Dedimania: Disabling records for this map. ".$status);
386
387
            return;
388
        }
389
390
        if ($map->nbCheckpoints < 1) {
391
            $status = "Checkpoints needs to be more than 1!";
392
            $this->console->writeln("Dedimania: Disabling records for this map. ".$status);
393
394
            return;
395
        }
396
397
        $params = [
398
            $this->sessionId,
399
            $this->getMapInfo(),
400
            $this->getGameMode(),
401
            $this->getServerInfo(),
402
            $this->getPlayers(),
403
        ];
404
405
        $request = new Request('dedimania.GetChallengeRecords', $params);
406
407
        $this->sendRequest($request, function ($response) {
408
409
            $this->dedimaniaService->setServerMaxRank($response['ServerMaxRank']);
410
            /** @var DedimaniaRecord[] $recs */
411
            $recs = DedimaniaRecord::fromArrayOfArray($response['Records']);
412
413
            if (isset($response['Records']['Login'])) {
414
                $recs = [];
415
                $recs[] = $response['Records'];
416
            }
417
418
            $this->dedimaniaService->setDedimaniaRecords($recs);
419
420
            // @todo remove when dedimania records has better frontend
421
            if (!empty($recs) && count($recs) > 0) {
422
423
                foreach ($this->playerStorage->getOnline() as $login => $player) {
424
                    $rec = $this->dedimaniaService->getRecord($login);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $rec is correct as $this->dedimaniaService->getRecord($login) (which targets eXpansionExperimantal\Bu...niaService::getRecord()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
425
                    if ($rec) {
426
                        $time = $this->time->timeToText($rec->best, true);
427
                        $this->chatNotification->sendMessage(
428
                            "|record|{record} Your current {variable}".$rec->rank.". {record}dedimania record {variable}|time| ".$time,
429
                            $login);
430
                    }
431
                }
432
            }
433
        });
434
435
    }
436
437
    public function updateServerPlayers()
438
    {
439
        if ($this->sessionId == null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $this->sessionId of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
440
            return;
441
        }
442
443
        $params = [
444
            $this->sessionId,
445
            $this->getServerInfo(),
446
            $this->getVotesInfo(),
447
            $this->getPlayers(),
448
        ];
449
        $request = new Request('dedimania.UpdateServerPlayers', $params);
450
451
        $this->sendRequest($request, function ($response) {
0 ignored issues
show
Unused Code introduced by
The parameter $response 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...
452
            // do nothing
453
        });
454
455
    }
456
457
    /**
458
     * @param DedicatedPlayer $player
459
     */
460
    public function connectPlayer(DedicatedPlayer $player)
461
    {
462
        $params = [
463
            $this->sessionId,
464
            $player->getLogin(),
465
            $player->getNickName(),
466
            $player->getPath(),
467
            $player->isSpectator(),
468
        ];
469
470
        $request = new Request('dedimania.PlayerConnect', $params);
471
        $this->sendRequest($request, function ($response) use ($player) {
472
            $dediplayer = DedimaniaPlayer::fromArray($response);
473
474
            if ($dediplayer->banned) {
475
                $this->chatNotification->sendMessage("|error|{error} Player {variable}".$player->getLogin()."{error} is banned from dedimania.");
476
477
                return;
478
            }
479
480
            $this->dedimaniaService->connectPlayer($dediplayer);
481
482
483
        });
484
    }
485
486
    /**
487
     * @param DedicatedPlayer $player
488
     */
489
    public function disconnectPlayer(DedicatedPlayer $player)
490
    {
491
        $params = [
492
            $this->sessionId,
493
            $player->getLogin(),
494
            $player->getNickName(),
495
            $player->getPath(),
496
            $player->isSpectator(),
497
        ];
498
499
        $request = new Request('dedimania.PlayerConnect', $params);
500
        $this->sendRequest($request, function ($response) use ($player) {
0 ignored issues
show
Unused Code introduced by
The parameter $response 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...
501
            $this->dedimaniaService->disconnectPlayer($player->getLogin());
502
        });
503
    }
504
505
    public function connectAllPlayers()
506
    {
507
        $players = $this->playerStorage->getOnline();
508
509
        /** @var Request $request */
510
        $request = null;
511
        foreach ($players as $x => $player) {
512
            $params = [
513
                $this->sessionId,
514
                $player->getLogin(),
515
                $player->getNickName(),
516
                $player->getPath(),
517
                $player->isSpectator(),
518
            ];
519
            if ($request === null) {
520
                $request = new Request('dedimania.PlayerConnect', $params);
521
            } else {
522
                $request->add('dedimania.PlayerConnect', $params);
523
            }
524
        }
525
526
        // no players to connect
527
        if ($request === null) {
528
            return;
529
        }
530
531
        $this->sendRequest($request, function ($response) {
532
533
            if (array_key_exists("Login", $response)) {
534
                $response = [0 => $response];
535
            }
536
            $this->dedimaniaService->setPlayers(DedimaniaPlayer::fromArrayOfArray($response));
537
        });
538
    }
539
540
    /*
541
     */
542
543
    public function setRecords()
544
    {
545
        if ($this->dedimaniaService->isDisabled()) {
546
547
            return;
548
        }
549
550
        $that = $this;
551
        $this->getScores->get(function ($scores) use ($that) {
552
            if (count($scores['players']) > 0 && isset($scores['players'][0]['login'])) {
553
554
                $player = new Player();
555
                $player->login = $scores['players'][0]['login'];
556
                try {
557
                    $replay = new IXR_Base64($this->factory->getConnection()->getValidationReplay($player));
558
                    $that->dedimaniaService->setVReplay($replay);
0 ignored issues
show
Documentation introduced by
$replay is of type object<eXpansionExperima...nia\Classes\IXR_Base64>, but the function expects a string.

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...
559
                    $VReplayChecks = $scores['players'][0]['bestracecheckpoints'];
560
561
                    $times = [];
562
                    foreach ($scores['players'] as $player) {
563
                        if (count($player['bestracecheckpoints']) > 0) {
564
                            $times[] = [
565
                                "Login" => $player['login'],
566
                                "Best" => $player['bestracetime'],
567
                                "Checks" => implode(",", $player['bestracecheckpoints']),
568
                            ];
569
                        }
570
                    }
571
572
                    $params = [
573
                        $this->sessionId,
574
                        $this->getMapInfo(),
575
                        $this->getGameMode(),
576
                        $times,
577
                        $this->getReplays($scores['players'][0]['login'], $VReplayChecks),
578
                    ];
579
580
                    $request = new Request("dedimania.SetChallengeTimes", $params);
581
582
                    $that->sendRequest($request, function ($response) {
0 ignored issues
show
Unused Code introduced by
The parameter $response 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...
583
                        $this->console->writeln('Dedimania: $0f0records saved.');
584
                    });
585
                } catch (\Exception $e) {
586
                    $this->console->writeln('Dedimania: Can\'t send times, $f00'.$e->getMessage());
587
                }
588
            }
589
590
        });
591
592
    }
593
594
//endregion
595
//#region protected helper functions
596
597
    /**
598
     * @param string $top1Login
599
     * @param array  $bestCheckpoints
600
     * @return array
601
     */
602
    protected function getReplays($top1Login, $bestCheckpoints)
603
    {
604
        list($login, $GReplay) = $this->dedimaniaService->getGReplay();
605
606
        if ($GReplay != "") {
607
            if ($top1Login != $login) {
608
                $this->console->getSfStyleOutput()->warning('Fetched Ghost Replay for Dedimania differs from top 1 holders login.');
609
                $this->console->writeln("Trying to fetch the right new one.");
610
                $this->setGReplay($top1Login);
611
                $replay = $this->dedimaniaService->getGReplay();
612
                $GReplay = $replay[1];
613
            }
614
        }
615
616
        return [
617
            "VReplay" => $this->dedimaniaService->getVReplay(),
618
            "VReplayChecks" => implode(",", $bestCheckpoints),
619
            "Top1GReplay" => $GReplay,
620
        ];
621
    }
622
623
    /**
624
     * Sets new Ghost replay for the map
625
     * @param $login
626
     */
627
    protected function setGReplay($login)
628
    {
629
        $tempReplay = new IXR_Base64("");
630
        $this->dedimaniaService->setGReplay("", $tempReplay);
631
632
        $player = new Player();
633
        $player->login = $login;
634
        try {
635
            $this->factory->getConnection()->saveBestGhostsReplay($player, "exp2_temp_replay");
636
            $replay = new IXR_Base64(
637
                $this->fileSystem->getUserData()->readAndDelete(
638
                    "Replays".DIRECTORY_SEPARATOR."exp2_temp_replay.Replay.Gbx")
639
            );
640
            $this->dedimaniaService->setGReplay($login, $replay);
641
        } catch (\Exception $e) {
642
            $this->console->writeln('Dedimania: $f00Error while fetching GhostsReplay');
643
        }
644
645
    }
646
647
    protected function getVotesInfo()
648
    {
649
        $map = $this->mapStorage->getCurrentMap();
650
651
        return [
652
            "UId" => $map->uId,
653
            "GameMode" => $this->getGameMode(),
654
        ];
655
    }
656
657
    protected function getMapInfo()
658
    {
659
        $map = $this->factory->getConnection()->getCurrentMapInfo();
660
661
        return [
662
            "UId" => $map->uId,
663
            "Name" => $map->name,
664
            "Environment" => $map->environnement,
665
            "Author" => $map->author,
666
            "NbCheckpoints" => $map->nbCheckpoints,
667
            "NbLaps" => $map->nbLaps,
668
        ];
669
    }
670
671
672
    protected function getPlayers()
673
    {
674
        $players = [];
675
        foreach ($this->playerStorage->getPlayers() as $player) {
676
            $players [] = [
677
                "Login" => $player->getLogin(),
678
                "IsSpec" => $player->isSpectator(),
679
            ];
680
        }
681
682
        return $players;
683
    }
684
685
    protected function getServerInfo()
686
    {
687
        return [
688
            "SrvName" => $this->gameDataStorage->getServerOptions()->name,
689
            "Comment" => $this->gameDataStorage->getServerOptions()->comment ?: "",
690
            "Private" => $this->gameDataStorage->getServerOptions()->password ? true : false,
691
            "NumPlayers" => count($this->playerStorage->getPlayers()),
692
            "MaxPlayers" => intval($this->gameDataStorage->getServerOptions()->currentMaxPlayers),
693
            "NumSpecs" => count($this->playerStorage->getSpectators()),
694
            "MaxSpecs" => intval($this->gameDataStorage->getServerOptions()->currentMaxSpectators),
695
        ];
696
    }
697
698
    protected function getGameMode()
699
    {
700
        switch (strtolower($this->gameDataStorage->getGameInfos()->scriptName)) {
701
702
            case "timeattack.script.txt":
703
            case "laps.script.txt":
704
                return "TA";
705
            case "rounds.script.txt":
706
            case "team.script.txt":
707
            case "cup.script.txt":
708
                return "Rounds";
709
            default:
710
                return "";
711
        }
712
    }
713
714
    protected function getPackMask($titleId)
715
    {
716
        foreach ($this->titles as $title => $data) {
717
            if (in_array($titleId, $data)) {
718
                return ucfirst($title);
719
            }
720
        }
721
722
        return "";
723
    }
724
725
//#endregion
726
//#region Dedicated server callbacks
727
728
    /**
729
     * Callback sent when the "StartMap" section start.
730
     *
731
     * @param int     $count Each time this section is played, this number is incremented by one
732
     * @param int     $time Server time when the callback was sent
733
     * @param boolean $restarted true if the map was restarted, false otherwise
734
     * @param Map     $map Map started with.
735
     *
736
     * @return void
737
     */
738
    public function onStartMapStart($count, $time, $restarted, Map $map)
739
    {
740
        if (!$restarted) {
741
            $this->lastUpdate = time();
742
            $this->getRecords();
743
        }
744
    }
745
746
    /**
747
     * Callback sent when the "EndMap" section start.
748
     *
749
     * @param int     $count Each time this section is played, this number is incremented by one
750
     * @param int     $time Server time when the callback was sent
751
     * @param boolean $restarted true if the map was restarted, false otherwise
752
     * @param Map     $map Map started with.
753
     *
754
     * @return void
755
     */
756
    public function onEndMapStart($count, $time, $restarted, Map $map)
757
    {
758
        if (!$restarted) {
759
            $this->setRecords();
760
        }
761
    }
762
763
    /**
764
     * @param string $login Login of the player that crossed the CP point
765
     * @param int    $time Server time when the event occured,
766
     * @param int    $raceTime Total race time in milliseconds
767
     * @param int    $stuntsScore Stunts score
768
     * @param int    $cpInRace Number of checkpoints crossed since the beginning of the race
769
     * @param int[]  $curCps Checkpoints times since the beginning of the race
770
     * @param string $blockId Id of the checkpoint block
771
     * @param string $speed Speed of the player in km/h
772
     * @param string $distance Distance traveled by the player
773
     */
774
    public function onPlayerEndRace(
775
        $login,
776
        $time,
777
        $raceTime,
778
        $stuntsScore,
779
        $cpInRace,
780
        $curCps,
781
        $blockId,
782
        $speed,
783
        $distance
784
    ) {
785
786
        $record = $this->dedimaniaService->processRecord($login, $raceTime, $curCps);
787
        if ($record instanceof DedimaniaRecord) {
788
            $rank = $record->rank;
789
            if ($rank > 0) {
790
                if ($rank === 1) {
791
                    $this->setGReplay($login);
792
                }
793
                $player = $this->playerStorage->getPlayerInfo($login);
794
                $this->chatNotification->sendMessage("|record| {variable}$rank. {record}Dedimania Record {variable}|time| ".$this->time->timeToText($raceTime,
795
                        true)." {record}driven by {variable}".TMString::trimStyles($player->getNickname())); // @todo remove this when the local records handler works nicely also for dedimania
796
            }
797
        }
798
    }
799
800
    /**
801
     * Callback sent when the "StartMap" section end.
802
     *
803
     * @param int     $count Each time this section is played, this number is incremented by one
804
     * @param int     $time Server time when the callback was sent
805
     * @param boolean $restarted true if the map was restarted, false otherwise
806
     * @param Map     $map Map started with.
807
     *
808
     * @return void
809
     */
810
    public function onStartMapEnd($count, $time, $restarted, Map $map)
811
    {
812
813
    }
814
815
    /**
816
     * Callback sent when the "EndMatch" section start.
817
     *
818
     * @param int $count Each time this section is played, this number is incremented by one
819
     * @param int $time Server time when the callback was sent
820
     *
821
     * @return void
822
     */
823
    public function onEndMatchStart($count, $time)
824
    {
825
        // do nothing
826
    }
827
828
829
    /**
830
     * Callback sent when the "EndMap" section end.
831
     *
832
     * @param int     $count Each time this section is played, this number is incremented by one
833
     * @param int     $time Server time when the callback was sent
834
     * @param boolean $restarted true if the map was restarted, false otherwise
835
     * @param Map     $map Map started with.
836
     *
837
     * @return void
838
     */
839
    public function onEndMapEnd($count, $time, $restarted, Map $map)
840
    {
841
        // do nothing
842
    }
843
844
    /**
845
     * Callback sent when the "StartMatch" section start.
846
     *
847
     * @param int $count Each time this section is played, this number is incremented by one
848
     * @param int $time Server time when the callback was sent
849
     *
850
     * @return void
851
     */
852
    public function onStartMatchStart($count, $time)
853
    {
854
        // do nothing
855
    }
856
857
    /**
858
     * Callback sent when the "StartMatch" section end.
859
     *
860
     * @param int $count Each time this section is played, this number is incremented by one
861
     * @param int $time Server time when the callback was sent
862
     *
863
     * @return void
864
     */
865
    public function onStartMatchEnd($count, $time)
866
    {
867
        // do nothing
868
    }
869
870
871
    /**
872
     * Callback sent when the "EndMatch" section end.
873
     *
874
     * @param int $count Each time this section is played, this number is incremented by one
875
     * @param int $time Server time when the callback was sent
876
     *
877
     * @return void
878
     */
879
    public function onEndMatchEnd($count, $time)
880
    {
881
        // do nothing
882
    }
883
884
    /**
885
     * Callback sent when the "StartTurn" section start.
886
     *
887
     * @param int $count Each time this section is played, this number is incremented by one
888
     * @param int $time Server time when the callback was sent
889
     *
890
     * @return void
891
     */
892
    public function onStartTurnStart($count, $time)
893
    {
894
        //
895
    }
896
897
    /**
898
     * Callback sent when the "StartTurn" section end.
899
     *
900
     * @param int $count Each time this section is played, this number is incremented by one
901
     * @param int $time Server time when the callback was sent
902
     *
903
     * @return void
904
     */
905
    public function onStartTurnEnd($count, $time)
906
    {
907
        //
908
    }
909
910
    /**
911
     * Callback sent when the "EndMatch" section start.
912
     *
913
     * @param int $count Each time this section is played, this number is incremented by one
914
     * @param int $time Server time when the callback was sent
915
     *
916
     * @return void
917
     */
918
    public function onEndTurnStart($count, $time)
919
    {
920
        //
921
    }
922
923
    /**
924
     * Callback sent when the "EndMatch" section end.
925
     *
926
     * @param int $count Each time this section is played, this number is incremented by one
927
     * @param int $time Server time when the callback was sent
928
     *
929
     * @return void
930
     */
931
    public function onEndTurnEnd($count, $time)
932
    {
933
        //
934
    }
935
936
    /**
937
     * Callback sent when the "StartRound" section start.
938
     *
939
     * @param int $count Each time this section is played, this number is incremented by one
940
     * @param int $time Server time when the callback was sent
941
     *
942
     * @return void
943
     */
944
    public function onStartRoundStart($count, $time)
945
    {
946
        //
947
    }
948
949
    /**
950
     * Callback sent when the "StartRound" section end.
951
     *
952
     * @param int $count Each time this section is played, this number is incremented by one
953
     * @param int $time Server time when the callback was sent
954
     *
955
     * @return void
956
     */
957
    public function onStartRoundEnd($count, $time)
958
    {
959
        //
960
    }
961
962
    /**
963
     * Callback sent when the "EndMatch" section start.
964
     *
965
     * @param int $count Each time this section is played, this number is incremented by one
966
     * @param int $time Server time when the callback was sent
967
     *
968
     * @return void
969
     */
970
    public function onEndRoundStart($count, $time)
971
    {
972
        //
973
    }
974
975
    /**
976
     * Callback sent when the "EndMatch" section end.
977
     *
978
     * @param int $count Each time this section is played, this number is incremented by one
979
     * @param int $time Server time when the callback was sent
980
     *
981
     * @return void
982
     */
983
    public function onEndRoundEnd($count, $time)
984
    {
985
        //
986
    }
987
988
989
    /**
990
     * @param DedicatedPlayer $player
991
     * @return void
992
     */
993
    public function onPlayerConnect(DedicatedPlayer $player)
994
    {
995
        $this->connectPlayer($player);
996
    }
997
998
    /**
999
     * @param DedicatedPlayer $player
1000
     * @param string          $disconnectionReason
1001
     * @return void
1002
     */
1003
    public function onPlayerDisconnect(DedicatedPlayer $player, $disconnectionReason)
1004
    {
1005
        $this->disconnectPlayer($player);
1006
    }
1007
1008
    /**
1009
     * @param DedicatedPlayer $oldPlayer
1010
     * @param DedicatedPlayer $player
1011
     * @return void
1012
     */
1013
    public function onPlayerInfoChanged(
1014
        DedicatedPlayer $oldPlayer,
1015
        DedicatedPlayer $player
1016
    ) {
1017
        //
1018
    }
1019
1020
    /**
1021
     * @param DedicatedPlayer $oldPlayer
1022
     * @param DedicatedPlayer $player
1023
     * @return void
1024
     */
1025
    public function onPlayerAlliesChanged(
1026
        DedicatedPlayer $oldPlayer,
1027
        DedicatedPlayer $player
1028
    ) {
1029
        //
1030
    }
1031
}