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

Dedimania::process()   C

Complexity

Conditions 16
Paths 131

Size

Total Lines 72
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
eloc 45
nc 131
nop 2
dl 0
loc 72
rs 5.0621
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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
 * 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
}