Passed
Pull Request — v3 (#729)
by
unknown
05:18 queued 02:43
created

Doom3   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 179
Duplicated Lines 0 %

Test Coverage

Coverage 82.05%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 10
eloc 51
c 1
b 0
f 0
dl 0
loc 179
ccs 32
cts 39
cp 0.8205
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A processStatus() 0 14 1
A processResponse() 0 15 3
A processServerInfo() 0 23 4
A processPlayers() 0 29 2
1
<?php
2
/**
3
 * This file is part of GameQ.
4
 *
5
 * GameQ is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU Lesser General Public License as published by
7
 * the Free Software Foundation; either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * GameQ is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public License
16
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18
19
namespace GameQ\Protocols;
20
21
use GameQ\Buffer;
22
use GameQ\Exception\Protocol as Exception;
23
use GameQ\Helpers\Str;
24
use GameQ\Protocol;
25
use GameQ\Result;
26
27
/**
28
 * Doom3 Protocol Class
29
 *
30
 * Handles processing DOOM 3 servers
31
 *
32
 * @package GameQ\Protocols
33
 * @author Wilson Jesus <>
34
 */
35
class Doom3 extends Protocol
36
{
37
    /**
38
     * Array of packets we want to look up.
39
     * Each key should correspond to a defined method in this or a parent class
40
     *
41
     * @var array
42
     */
43
    protected $packets = [
44
        self::PACKET_ALL => "\xFF\xFFgetInfo\x00PiNGPoNG\x00",
45
    ];
46
47
    /**
48
     * Use the response flag to figure out what method to run
49
     *
50
     * @var array
51
     */
52
    protected $responses = [
53
        "\xFF\xFFinfoResponse" => 'processStatus',
54
    ];
55
56
    /**
57
     * The query protocol used to make the call
58
     *
59
     * @var string
60
     */
61
    protected $protocol = 'doom3';
62
63
    /**
64
     * String name of this protocol class
65
     *
66
     * @var string
67
     */
68
    protected $name = 'doom3';
69
70
    /**
71
     * Longer string name of this protocol class
72
     *
73
     * @var string
74
     */
75
    protected $name_long = "Doom 3";
76
77
    /**
78
     * Normalize settings for this protocol
79
     *
80
     * @var array
81
     */
82
    protected $normalize = [
83
        // General
84
        'general' => [
85
            // target       => source
86
            'hostname'   => 'si_name',
87
            'gametype'   => 'gamename',
88
            'mapname'    => 'si_map',
89
            'maxplayers' => 'si_maxPlayers',
90
            'numplayers' => 'clients',
91
            'password'   => 'si_usepass',
92
        ],
93
        // Individual
94
        'player'  => [
95
            'name'  => 'name',
96
            'ping'  => 'ping',
97
        ],
98
    ];
99
100
    /**
101
     * Handle response from the server
102
     *
103
     * @return mixed
104
     * @throws Exception
105
     */
106 24
    public function processResponse()
107
    {
108
        // Make a buffer
109 24
        $buffer = new Buffer(implode('', $this->packets_response));
110
111
        // Grab the header
112 24
        $header = $buffer->readString();
113
114
        // Header
115
        // Figure out which packet response this is
116 24
        if (empty($header) || !array_key_exists($header, $this->responses)) {
117
            throw new Exception(__METHOD__ . " response type '" . bin2hex($header) . "' is not valid");
118
        }
119
120 24
        return call_user_func_array([$this, $this->responses[$header]], [$buffer]);
121
    }
122
123
    /**
124
     * Process the status response
125
     *
126
     * @param Buffer $buffer
127
     *
128
     * @return array
129
     */
130 24
    protected function processStatus(Buffer $buffer)
131
    {
132
        // We need to split the data and offload
133 24
        $results = $this->processServerInfo($buffer);
134
135 24
        $results = array_merge_recursive(
136 24
            $results,
137 24
            $this->processPlayers($buffer)
138 16
        );
139
140 24
        unset($buffer);
141
142
        // Return results
143 24
        return $results;
144
    }
145
146
    /**
147
     * Handle processing the server information
148
     *
149
     * @param Buffer $buffer
150
     *
151
     * @return array
152
     */
153 24
    protected function processServerInfo(Buffer $buffer)
154
    {
155
        // Set the result to a new result instance
156 24
        $result = new Result();
157
158 24
        $result->add('version', $buffer->readInt8() . '.' . $buffer->readInt8());
159
160
        // Key / value pairs, delimited by an empty pair
161 24
        while ($buffer->getLength()) {
162 24
            $key = trim($buffer->readString());
163 24
            $val = Str::isoToUtf8(trim($buffer->readString()));
164
165
            // Something is empty so we are done
166 24
            if (empty($key) && empty($val)) {
167 24
                break;
168
            }
169
170 24
            $result->add($key, $val);
171 4
        }
172
173 24
        unset($buffer);
174
175 24
        return $result->fetch();
176
    }
177
178
    /**
179
     * Handle processing of player data
180
     *
181
     * @param Buffer $buffer
182
     *
183
     * @return array
184
     */
185 12
    protected function processPlayers(Buffer $buffer)
186
    {
187
        // Some games do not have a number of current players
188 12
        $playerCount = 0;
189
190
        // Set the result to a new result instance
191 12
        $result = new Result();
192
193
        // Parse players
194
        // Loop thru the buffer until we run out of data
195 12
        while (($id = $buffer->readInt8()) != 32) {
196
            // Add player info results
197
            $result->addPlayer('id', $id);
198
            $result->addPlayer('ping', $buffer->readInt16());
199
            $result->addPlayer('rate', $buffer->readInt32());
200
            // Add player name, encoded
201
            $result->addPlayer('name', Str::isoToUtf8(trim($buffer->readString())));
202
203
            // Increment
204
            $playerCount++;
205
        }
206
207
        // Add the number of players to the result
208 12
        $result->add('clients', $playerCount);
209
210
        // Clear
211 12
        unset($buffer, $playerCount);
212
213 12
        return $result->fetch();
214
    }
215
}
216