Passed
Push — v3 ( 962004...bdfc5f )
by Austin
06:52
created

Mumble::processResponse()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 34
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 12
c 1
b 0
f 0
dl 0
loc 34
ccs 13
cts 13
cp 1
rs 9.8666
cc 4
nc 4
nop 0
crap 4
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\Result;
23
use GameQ\Exception\Protocol as Exception;
24
25
/**
26
 * Mumble Protocol class
27
 *
28
 * References:
29
 * https://github.com/edmundask/MurmurQuery - Thanks to skylord123
30
 *
31
 * @author Austin Bischoff <[email protected]>
32
 */
33
class Mumble extends Protocol
34
{
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 => "\x6A\x73\x6F\x6E", // JSON packet
44
    ];
45
46
    /**
47
     * The transport mode for this protocol is TCP
48
     *
49
     * @type string
50
     */
51
    protected $transport = self::TRANSPORT_TCP;
52
53
    /**
54
     * The query protocol used to make the call
55
     *
56
     * @type string
57
     */
58
    protected $protocol = 'mumble';
59
60
    /**
61
     * String name of this protocol class
62
     *
63
     * @type string
64
     */
65
    protected $name = 'mumble';
66
67
    /**
68
     * Longer string name of this protocol class
69
     *
70
     * @type string
71
     */
72
    protected $name_long = "Mumble Server";
73
74
    /**
75
     * The client join link
76
     *
77
     * @type string
78
     */
79
    protected $join_link = "mumble://%s:%d/";
80
81
    /**
82
     * 27800 = 64738 - 36938
83
     *
84
     * @type int
85
     */
86
    protected $port_diff = -36938;
87
88
    /**
89
     * Normalize settings for this protocol
90
     *
91
     * @type array
92
     */
93
    protected $normalize = [
94
        // General
95
        'general' => [
96
            'dedicated'  => 'dedicated',
97
            'gametype'   => 'gametype',
98
            'hostname'   => 'name',
99
            'numplayers' => 'numplayers',
100
            'maxplayers' => 'x_gtmurmur_max_users',
101
        ],
102
        // Player
103
        'player'  => [
104
            'name' => 'name',
105
            'ping' => 'tcpPing',
106
            'team' => 'channel',
107
            'time' => 'onlinesecs',
108
        ],
109
        // Team
110
        'team'    => [
111
            'name' => 'name',
112
        ],
113
    ];
114
115
    /**
116
     * Process the response
117
     *
118
     * @return array
119
     * @throws \GameQ\Exception\Protocol
120
     */
121 3
    public function processResponse()
122
    {
123
124
        // Try to json_decode, make it into an array
125 3
        if (($data = json_decode(implode('', $this->packets_response), true)) === null) {
126 1
            throw new Exception(__METHOD__ . " Unable to decode JSON data.");
127
        }
128
129
        // Set the result to a new result instance
130 2
        $result = new Result();
131
132
        // Always dedicated
133 2
        $result->add('dedicated', 1);
134
135
        // Let's iterate over the response items, there are a lot
136 2
        foreach ($data as $key => $value) {
137
            // Ignore root for now, that is where all of the channel/player info is housed
138 2
            if (in_array($key, ['root'])) {
139 2
                continue;
140
            }
141
142
            // Add them as is
143 2
            $result->add($key, $value);
144
        }
145
146
        // Offload the channel and user parsing
147 2
        $this->processChannelsAndUsers($data['root'], $result);
148
149 2
        unset($data);
150
151
        // Manually set the number of players
152 2
        $result->add('numplayers', count($result->get('players')));
153
154 2
        return $result->fetch();
155
    }
156
157
    /*
158
     * Internal methods
159
     */
160
161
    /**
162
     * Handles processing the the channels and user info
163
     *
164
     * @param array         $data
165
     * @param \GameQ\Result $result
166
     */
167 2
    protected function processChannelsAndUsers(array $data, Result &$result)
168
    {
169
170
        // Let's add all of the channel information
171 2
        foreach ($data as $key => $value) {
172
            // We will handle these later
173 2
            if (in_array($key, ['channels', 'users'])) {
174
                // skip
175 2
                continue;
176
            }
177
178
            // Add the channel property as a team
179 2
            $result->addTeam($key, $value);
180
        }
181
182
        // Itereate over the users in this channel
183 2
        foreach ($data['users'] as $user) {
184 2
            foreach ($user as $key => $value) {
185 2
                $result->addPlayer($key, $value);
186
            }
187
        }
188
189
        // Offload more channels to parse
190 2
        foreach ($data['channels'] as $channel) {
191 2
            $this->processChannelsAndUsers($channel, $result);
192
        }
193 2
    }
194
}
195