Completed
Push — v3 ( 30beb6...048774 )
by
unknown
17s queued 15s
created

Doom3::processResponse()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 15
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.0416

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
c 1
b 0
f 0
dl 0
loc 15
ccs 5
cts 6
cp 0.8333
rs 10
cc 3
nc 2
nop 0
crap 3.0416
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\Protocol;
22
use GameQ\Buffer;
23
use GameQ\Result;
24
use GameQ\Exception\Protocol as Exception;
25
26
/**
27
 * Doom3 Protocol Class
28
 *
29
 * Handles processing DOOM 3 servers
30
 *
31
 * @package GameQ\Protocols
32
 * @author Wilson Jesus <>
33
 */
34
class Doom3 extends Protocol
35
{
36
    /**
37
     * Array of packets we want to look up.
38
     * Each key should correspond to a defined method in this or a parent class
39
     *
40
     * @type array
41
     */
42
    protected $packets = [
43
        self::PACKET_ALL => "\xFF\xFFgetInfo\x00PiNGPoNG\x00",
44
    ];
45
46
    /**
47
     * Use the response flag to figure out what method to run
48
     *
49
     * @type array
50
     */
51
    protected $responses = [
52
        "\xFF\xFFinfoResponse" => 'processStatus',
53
    ];
54
55
    /**
56
     * The query protocol used to make the call
57
     *
58
     * @type string
59
     */
60
    protected $protocol = 'doom3';
61
62
    /**
63
     * String name of this protocol class
64
     *
65
     * @type string
66
     */
67
    protected $name = 'doom3';
68
69
    /**
70
     * Longer string name of this protocol class
71
     *
72
     * @type string
73
     */
74
    protected $name_long = "Doom 3";
75
76
    /**
77
     * The client join link
78
     *
79
     * @type string
80
     */
81
    protected $join_link = null;
82
83
    /**
84
     * Normalize settings for this protocol
85
     *
86
     * @type array
87
     */
88
    protected $normalize = [
89
        // General
90
        'general' => [
91
            // target       => source
92
            'hostname'   => 'si_name',
93
            'gametype'   => 'gamename',
94
            'mapname'    => 'si_map',
95
            'maxplayers' => 'si_maxPlayers',
96
            'numplayers' => 'clients',
97
            'password'   => 'si_usepass',
98
        ],
99
        // Individual
100
        'player'  => [
101
            'name'  => 'name',
102
            'ping'  => 'ping',
103
        ],
104
    ];
105
106
    /**
107
     * Handle response from the server
108
     *
109
     * @return mixed
110
     * @throws Exception
111
     */
112 24
    public function processResponse()
113
    {
114
        // Make a buffer
115 24
        $buffer = new Buffer(implode('', $this->packets_response));
116
117
        // Grab the header
118 24
        $header = $buffer->readString();
119
120
        // Header
121
        // Figure out which packet response this is
122 24
        if (empty($header) || !array_key_exists($header, $this->responses)) {
123
            throw new Exception(__METHOD__ . " response type '" . bin2hex($header) . "' is not valid");
124
        }
125
126 24
        return call_user_func_array([$this, $this->responses[$header]], [$buffer]);
127
    }
128
129
    /**
130
     * Process the status response
131
     *
132
     * @param Buffer $buffer
133
     *
134
     * @return array
135
     */
136 24
    protected function processStatus(Buffer $buffer)
137
    {
138
        // We need to split the data and offload
139 24
        $results = $this->processServerInfo($buffer);
140
141 24
        $results = array_merge_recursive(
142 4
            $results,
143 24
            $this->processPlayers($buffer)
144
        );
145
146 24
        unset($buffer);
147
148
        // Return results
149 24
        return $results;
150
    }
151
152
    /**
153
     * Handle processing the server information
154
     *
155
     * @param Buffer $buffer
156
     *
157
     * @return array
158
     */
159 24
    protected function processServerInfo(Buffer $buffer)
160
    {
161
        // Set the result to a new result instance
162 24
        $result = new Result();
163
164 24
        $result->add('version', $buffer->readInt8() . '.' . $buffer->readInt8());
165
166
        // Key / value pairs, delimited by an empty pair
167 24
        while ($buffer->getLength()) {
168 24
            $key = trim($buffer->readString());
169 24
            $val = utf8_encode(trim($buffer->readString()));
170
171
            // Something is empty so we are done
172 24
            if (empty($key) && empty($val)) {
173 24
                break;
174
            }
175
176 24
            $result->add($key, $val);
177
        }
178
179 24
        unset($buffer);
180
181 24
        return $result->fetch();
182
    }
183
184
    /**
185
     * Handle processing of player data
186
     *
187
     * @param Buffer $buffer
188
     *
189
     * @return array
190
     */
191 12
    protected function processPlayers(Buffer $buffer)
192
    {
193
        // Some games do not have a number of current players
194 12
        $playerCount = 0;
195
196
        // Set the result to a new result instance
197 12
        $result = new Result();
198
199
        // Parse players
200
        // Loop thru the buffer until we run out of data
201 12
        while (($id = $buffer->readInt8()) != 32) {
202
            // Add player info results
203
            $result->addPlayer('id', $id);
204
            $result->addPlayer('ping', $buffer->readInt16());
205
            $result->addPlayer('rate', $buffer->readInt32());
206
            // Add player name, encoded
207
            $result->addPlayer('name', utf8_encode(trim($buffer->readString())));
208
209
            // Increment
210
            $playerCount++;
211
        }
212
213
        // Add the number of players to the result
214 12
        $result->add('clients', $playerCount);
215
216
        // Clear
217 12
        unset($buffer, $playerCount);
218
219 12
        return $result->fetch();
220
    }
221
}
222