MinecraftServer   A
last analyzed

Complexity

Total Complexity 34

Size/Duplication

Total Lines 349
Duplicated Lines 4.58 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
wmc 34
c 0
b 0
f 0
lcom 1
cbo 7
dl 16
loc 349
rs 9.2

19 Methods

Rating   Name   Duplication   Size   Complexity  
A setQueryPort() 0 4 1
A getQueryPort() 0 4 1
A setRconPort() 0 4 1
A getRconPort() 0 4 1
A setMinHeap() 0 4 1
A getMinHeap() 0 4 1
A setMaxHeap() 0 4 1
A getMaxHeap() 0 4 1
B installServer() 0 24 3
B getInstallationProgress() 0 24 4
A uploadShellScripts() 0 21 2
A regenerateScripts() 0 4 1
A changeState() 0 6 1
B uploadDefaultServerConfigurationFile() 0 27 2
B modifyServerPropertiesFile() 0 51 6
B execPluginScript() 0 23 4
A removeFromServer() 16 16 1
A removeInstallationFiles() 0 6 1
A loadValidatorMetadata() 0 19 1

How to fix   Duplicated Code   

Duplicated Code

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

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/**
4
 * This file is part of Dedipanel project
5
 *
6
 * (c) 2010-2015 Dedipanel <http://www.dedicated-panel.net>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace DP\GameServer\MinecraftServerBundle\Entity;
13
14
use Doctrine\ORM\Mapping as ORM;
15
use DP\GameServer\GameServerBundle\Entity\GameServer;
16
use Symfony\Component\Validator\Constraints as Assert;
17
use DP\Core\MachineBundle\PHPSeclibWrapper\PHPSeclibWrapper;
18
use DP\Core\GameBundle\Entity\Plugin;
19
use DP\Core\CoreBundle\Exception\MissingPacketException;
20
use Symfony\Component\Validator\Mapping\ClassMetadata;
21
22
/**
23
 * DP\GameServer\MinecraftServerBundle\Entity\MinecraftServer
24
 *
25
 * @ORM\Table(name="minecraft_server")
26
 * @ORM\Entity(repositoryClass="DP\GameServer\GameServerBundle\Entity\GameServerRepository")
27
 * 
28
 * @todo: refacto phpseclib
29
 * @todo: refacto domain logic
30
 */
31
class MinecraftServer extends GameServer
32
{
33
34
    /**
35
     * @var integer $queryPort
36
     *
37
     * @ORM\Column(name="queryPort", type="integer", nullable=true)
38
     */
39
    protected $queryPort;
40
41
    /**
42
     * @var integer $rconPort
43
     *
44
     * @ORM\Column(name="rconPort", type="integer")
45
     */
46
    protected $rconPort;
47
48
    /**
49
     * @var integer $minHeap
50
     *
51
     * @ORM\Column(name="minHeap", type="integer")
52
     */
53
    protected $minHeap;
54
55
    /**
56
     * @var integer $maxHeap
57
     *
58
     * @ORM\Column(name="maxHeap", type="integer")
59
     */
60
    protected $maxHeap;
61
62
    /*
63
     * Set minecraft query port
64
     *
65
     * @param integer $queryPort
66
     */
67
    public function setQueryPort($queryPort)
68
    {
69
        $this->queryPort = $queryPort;
70
    }
71
72
    /*
73
     * Get minecraft query port
74
     *
75
     * @return integer Query port
76
     */
77
    public function getQueryPort()
78
    {
79
        return $this->queryPort;
80
    }
81
82
    /*
83
     * Set rcon port
84
     *
85
     * @param integer $rconPort
86
     */
87
    public function setRconPort($rconPort)
88
    {
89
        $this->rconPort = $rconPort;
90
    }
91
92
    /*
93
     * Get rcon port
94
     *
95
     * @return integer RCON Port
96
     */
97
    public function getRconPort()
98
    {
99
        return $this->rconPort;
100
    }
101
102
    /**
103
     * Set min heap
104
     *
105
     * @param integer $minHeap
106
     */
107
    public function setMinHeap($minHeap)
108
    {
109
        $this->minHeap = $minHeap;
110
    }
111
112
    /**
113
     * Get min heap
114
     *
115
     * @return integer Min heap
116
     */
117
    public function getMinHeap()
118
    {
119
        return $this->minHeap;
120
    }
121
122
    /**
123
     * Set max heap
124
     *
125
     * @param integer $maxHeap
126
     */
127
    public function setMaxHeap($maxHeap)
128
    {
129
        $this->maxHeap = $maxHeap;
130
    }
131
132
    /**
133
     * Get max heap
134
     *
135
     * @return integer Max heap
136
     */
137
    public function getMaxHeap()
138
    {
139
        return $this->maxHeap;
140
    }
141
142
    /**
143
     * Download server
144
     */
145
    public function installServer(\Twig_Environment $twig)
146
    {
147
        $conn = $this->getMachine()->getConnection();
148
149
        if (!$conn->isJavaInstalled()) {
150
            throw new MissingPacketException('oracle-java8-installer');
151
        }
152
153
        $installDir = $this->getAbsoluteDir();
154
        $logPath = $installDir . 'install.log';
155
156
        $conn->mkdir($installDir);
157
158
        $dlUrl = 'https://s3.amazonaws.com/MinecraftDownload/launcher/minecraft_server.jar';
159
        if ($this->game->getLaunchName() == 'bukkit') {
160
            $dlUrl = 'http://dl.bukkit.org/latest-rb/craftbukkit.jar';
161
        }
162
163
        $conn->exec('cd ' . $installDir . ' && wget -N -o ' . $logPath . ' ' . $dlUrl . ' &');
164
165
        $this->installationStatus = 0;
166
167
        return true;
168
    }
169
170
    public function getInstallationProgress()
171
    {
172
        $installDir = $this->getAbsoluteDir();
173
        $logPath = $installDir . 'install.log';
174
        $binPath = $installDir . $this->getGame()->getBin();
175
        $conn    = $this->getMachine()->getConnection();
176
        
177
        $status = $conn->exec("if [ -d $installDir ]; then if [ -e $logPath ]; then echo 1; elif [ -e $binPath ]; then echo 2; else echo 0; fi; else echo 0; fi;");
178
179
        if ($status == 2) {
180
            return 100;
181
        }
182
183
        // On récupère les 20 dernières lignes du fichier afin de déterminer le pourcentage
184
        $installLog = $conn->exec('tail -n 20 ' . $logPath);
185
        $percent    = $this->getPercentFromInstallLog($installLog);
186
187
        // Suppression du fichier de log si le dl est terminé
188
        if (!empty($percent) && $percent == 100) {
189
            $conn->exec('rm ' . $logPath);
190
        }
191
192
        return $percent;
193
    }
194
195
    public function uploadShellScripts(\Twig_Environment $twig)
196
    {
197
        $conn = $this->getMachine()->getConnection();
198
        $game = $this->getGame();
199
200
        $scriptPath = $this->getAbsoluteDir() . 'minecraft.sh';
201
202
        $minecraftScript = $twig->render('DPMinecraftServerBundle:sh:minecraft.sh.twig', array(
203
            'screenName' => $this->getScreenName(), 'bin' => $game->getBin(),
204
            'options' => 'nogui', 'minHeap' => $this->getMinHeap(), 'maxHeap' => $this->getMaxHeap(),
205
            'parallelThreads' => 1, 'binDir' => $this->getAbsoluteBinDir(), 'core' => implode(',', $this->getCore()),
206
        ));
207
208
        if (!$conn->upload($scriptPath, $minecraftScript, 0750)) {
209
            return false;
210
        }
211
212
        $this->installationStatus = 101;
213
214
        return true;
215
    }
216
    
217
    public function regenerateScripts(\Twig_Environment $twig)
218
    {
219
        return $this->uploadShellScripts($twig);
220
    }
221
222
    /**
223
     * {@inheritdoc}
224
     */
225
    public function changeState($state)
226
    {
227
        $scriptPath = $this->getAbsoluteDir() . 'minecraft.sh';
228
229
        return $this->getMachine()->getConnection()->exec($scriptPath . ' ' . $state);
230
    }
231
232
    public function uploadDefaultServerConfigurationFile()
233
    {
234
        $template = $this->getGame()->getConfigTemplate();
235
236
        if (!empty($template)) {
237
            $conn = $this->getMachine()->getConnection();
238
            $cfgPath = $this->getAbsoluteDir() . 'server.properties';
239
240
            // Supression du fichier s'il existe déjà
241
            $conn->exec('if [ -e ' . $cfgPath . ']; then rm ' . $cfgPath . '; fi');
242
243
            $env = new \Twig_Environment(new \Twig_Loader_String());
0 ignored issues
show
Deprecated Code introduced by
The class Twig_Loader_String has been deprecated with message: since 1.18.1 (to be removed in 2.0)

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
244
            $cfgFile = $env->render($template, array(
245
                'serverPort'    => $this->getPort(),
246
                'queryPort'     => $this->getQueryPort(),
247
                'rconPort'      => $this->getRconPort(),
248
                'rconPassword'  => $this->getRconPassword(),
249
                'maxPlayers'    => $this->getMaxplayers(),
250
                'motd'          => $this->getFullName(),
251
                'ip'            => $this->getMachine()->getPublicIp(),
252
            ));
253
254
            return $conn->upload($cfgPath, $cfgFile, 0750);
255
        }
256
257
        return false;
258
    }
259
260
    public function modifyServerPropertiesFile()
261
    {
262
        // Variables à modifier dans le fichier server.properties
263
        $varToChange = array(
264
            'motd'          => $this->getName(), 
265
            'server-port'   => $this->getPort(),
266
            'enable-query'  => 'true',
267
            'query.port'    => $this->getQueryPort(),
268
            'enable-rcon'   => 'true',
269
            'rcon.port'     => $this->getRconPort(),
270
            'rcon.password' => $this->getRconPassword(),
271
            'server-ip'     => $this->getMachine()->getPublicIp(),
272
            'max-players'   => $this->getMaxplayers(),
273
        );
274
275
        // Récupération du fichier server.properties distant
276
        $conn = $this->getMachine()->getConnection();
277
        $cfgPath = $this->getAbsoluteDir() . 'server.properties';
278
279
        $remoteFile = $conn->download($cfgPath);
280
        $fileLines = explode("\n", $remoteFile);
281
282
        foreach ($fileLines AS &$line) {
283
            if (false === $pos = strpos($line, '=')) continue;
284
285
            // Extraction du nom de la variable
286
            $var = substr($line, 0, $pos);
287
288
            // Si c'est l'une des variables à modifier, on modifie la ligne
289
            // Et on supprime l'entrée dans l'array des variables à modifier
290
            if (array_key_exists($var, $varToChange)) {
291
                $line = $var . '=' . $varToChange[$var];
292
293
                unset($varToChange[$var]);
294
            }
295
        }
296
        // Suppression de la référence
297
        unset($line);
298
299
        // S'il reste des variables dans l'array $varToChange
300
        // On ajoute les lignes au fichier
301
        // (puisqu'elle n'existe pas, les nouvelles valeurs n'ont pas encore été mises)
302
        if (!empty($varToChange)) {
303
            foreach ($varToChange AS $var => $val) {
304
                $fileLines[] .= $var . '=' . $val;
305
            }
306
        }
307
308
        // Upload du nouveau fichier
309
        return $conn->upload($cfgPath, implode("\n", $fileLines));
310
    }
311
312
    public function execPluginScript(\Twig_Environment $twig, Plugin $plugin, $action)
313
    {
314
        if ($action != 'install' && $action != 'uninstall') {
315
            throw new BadMethodCallException('Only actions available for MinecraftServers plugin script are : install and uninstall.');
316
        }
317
        
318
        $conn = $this->getMachine()->getConnection();
319
        
320
        $dir = $this->getAbsoluteDir();
321
        $scriptPath = $dir . 'plugin.sh';
322
        $pluginScript = $twig->render('DPMinecraftServerBundle:sh:plugin.sh.twig', array('gameDir' => $dir . 'plugins'));
323
            
324
        $conn->upload($scriptPath, $pluginScript);
325
        
326
        $screenName = $this->getPluginInstallScreenName();
327
        $screenCmd  = 'screen -dmS ' . $screenName . ' ' . $scriptPath . ' ' . $action;
328
        
329
        if ($action == 'install') {
330
            $screenCmd .= ' "' . $plugin->getDownloadUrl () . '"';
331
        }
332
        
333
        $conn->exec($screenCmd);
334
    }
335
336 View Code Duplication
    public function removeFromServer()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
337
    {
338
        $screenName = $this->getScreenName();
339
        $serverDir = $this->getAbsoluteDir();
340
        $scriptPath = $serverDir . 'minecraft.sh';
341
        
342
        $conn = $this->getMachine()->getConnection();
343
344
        // On commence par vérifier que le serveur n'est pas lancé (sinon on l'arrête)
345
        $pgrep   = '`ps aux | grep SCREEN | grep "' . $screenName . ' " | grep -v grep | wc -l`';
346
        $stopCmd = 'if [ ' . $pgrep . ' != "0" ]; then ' . $scriptPath . ' stop; fi;';
347
        $conn->exec($stopCmd);
348
349
        // Puis on supprime complètement le dossier du serveur
350
        return $conn->remove($serverDir);
351
    }
352
353
    public function removeInstallationFiles()
354
    {
355
        $logPath = $this->getAbsoluteDir() . 'install.log';
356
357
        return $this->getMachine()->getConnection()->remove($logPath);
358
    }
359
360
    public static function loadValidatorMetadata(ClassMetadata $metadata)
361
    {
362
        $metadata->addPropertyConstraint('queryPort', new Assert\NotBlank(array('message' => 'minecraft.assert.query_port.empty')));
363
        $metadata->addPropertyConstraint('queryPort', new Assert\Range(array(
364
            'min' => 1024,
365
            'minMessage' => 'minecraft.assert.query_port.min',
366
            'max' => 65536,
367
            'maxMessage' => 'minecraft.assert.query_port.max'
368
        )));
369
        $metadata->addPropertyConstraint('rconPort', new Assert\NotBlank(array('message' => 'minecraft.assert.rcon_port.empty')));
370
        $metadata->addPropertyConstraint('rconPort', new Assert\Range(array(
371
            'min' => 1024,
372
            'minMessage' => 'minecraft.assert.rcon_port.min',
373
            'max' => 65536,
374
            'maxMessage' => 'minecraft.assert.rcon_port.max'
375
        )));
376
        $metadata->addPropertyConstraint('minHeap', new Assert\NotBlank(array('message' => 'minecraft.assert.min_heap')));
377
        $metadata->addPropertyConstraint('maxHeap', new Assert\NotBlank(array('message' => 'minecraft.assert.max_heap')));
378
    }
379
}
380