AMXX-BG.INFO server_query.inc Raw include

server_query.inc

Original include source with line numbers.

Back Download .inc
1 #if defined _server_query_included
2 #endinput
3 #endif
4
5 #define _server_query_included
6
7 #if AMXX_VERSION_NUM >= 175
8 #pragma reqlib server_query
9 #if !defined AMXMODX_NOAUTOLOAD
10 #pragma loadlib server_query
11 #endif
12 #else
13 #pragma library server_query
14 #endif
15
16 #include < amxmodx >
17
18 #define SQ_RULE_NAME_SIZE 256
19 #define SQ_RULE_VALUE_SIZE 256
20
21 /*
22 * Queries a server for information
23 *
24 * @param ip - IP of the server without port
25 * @param port - The port number of the server
26 * @param type - The type of query to perform (matches SQ_* constants)
27 * @param function - The callback function to be executed when the query is finished
28 * @param error - The error code given when there was a problem with the query (matches SQError_* constants)
29 * @param timeout - The time in seconds to wait for a response before setting as failed
30 * @param data - Extra data array to pass to the callback function
31 * @param data_size - Size of the extra data array being passed
32 *
33 * @note Only 1 query can be performed on the same ip:port combination at a time.
34 * Trying to use a different query type on the same ip:port while another is already taking place will throw an error.
35 *
36 * @return Returns unique SQuery ID (integer) on success, 0 on failure (and passes error code to param)
37 *
38 *
39 * Structure for callback function:
40 *
41 * sq_query("127.0.0.1", 27015, SQ_Server, "SQueryResults", errcode)
42 *
43 * public SQueryResults(squery_id, type, Trie:buffer, Float:query_time, bool:failed, data[], data_size)
44 *
45 * @param squery_id - The unique SQuery ID (integer) return value from sq_query()
46 * @param type - The type of query performed (matches SQ_* constants)
47 * @param buffer - The buffer containing the server info
48 * @param query_time - The time in seconds it took for the query to finish
49 * @param failed - false if results were found, true otherwise
50 * @param data - The data sent to the sq_query() native
51 * @param data_size - The size of the data sent to the sq_query() native
52 *
53 * @note The buffer is a Trie with key->value pairs for data
54 * Do not destroy this (or any Arrays or Tries it contains) in the callback!
55 *
56 * @return Return value is ignored
57 *
58 */
59 enum _:ServerQueryType
60 {
61 SQ_Server,
62 SQ_Players,
63 SQ_Challenge,
64 SQ_Ping,
65 SQ_Rules,
66 };
67 native sq_query(const ip[],const port,const type,const function[],&error,const timeout=60,const data[]="",const data_size=0);
68
69 /*
70 * Gets a description of the errcode when sq_query() fails
71 *
72 * @param errcode - The error code from the sq_query() function (matches SQError_* constants)
73 * @param error - The output string to contain the description
74 * @param len - The max length of the result string
75 *
76 * @return The length of the result on success, 0 on failure
77 *
78 */
79 enum _:ServerQueryErrors
80 {
81 SQError_NoError,
82 SQError_InvalidParams,
83 SQError_MaxConnections,
84 SQError_InvalidQueryType,
85 SQError_InvalidIP,
86 SQError_CouldNotConnect,
87 SQError_InvalidFunction,
88 SQError_AlreadyConnected
89 };
90 stock sq_error(const errcode,error[],const len)
91 {
92 switch( errcode )
93 {
94 /*case SQError_NoError:
95 {
96 return copy( error, len, "No error" );
97 }*/
98 case SQError_InvalidParams:
99 {
100 return copy( error, len, "Invalid function parameter list." );
101 }
102 case SQError_MaxConnections:
103 {
104 return copy( error, len, "Too many server queries are already taking place." );
105 }
106 case SQError_InvalidQueryType:
107 {
108 return copy( error, len, "Invalid server query type." );
109 }
110 case SQError_InvalidIP:
111 {
112 return copy( error, len, "Invalid IP given." );
113 }
114 case SQError_CouldNotConnect:
115 {
116 return copy( error, len, "Could not connect to given IP." );
117 }
118 case SQError_InvalidFunction:
119 {
120 return copy( error, len, "Invalid function handle." );
121 }
122 case SQError_AlreadyConnected:
123 {
124 return copy( error, len, "Connection exists for given IP." );
125 }
126 }
127
128 return 0;
129 }
130
131 /*
132 * Gets a description of the server type based on it's servertype info from the buffer
133 *
134 * @param servertype - The servertype retrieved from the server info buffer (matches SERVERTYPE_* constants)
135 * @param result - The output string to contain the description
136 * @param len - The max length of the result string
137 *
138 * @return The length of the result on success, 0 on failure
139 *
140 */
141 #define SERVERTYPE_LISTEN 'l' // listen
142 #define SERVERTYPE_DEDICATED 'd' // dedicated
143 #define SERVERTYPE_HLTV 'p' // HLTV
144 stock sq_servertype(const servertype,result[],const len)
145 {
146 switch( servertype )
147 {
148 case SERVERTYPE_LISTEN:
149 {
150 return copy( result, len, "Listen" );
151 }
152 case SERVERTYPE_DEDICATED:
153 {
154 return copy( result, len, "Dedicated" );
155 }
156 case SERVERTYPE_HLTV:
157 {
158 return copy( result, len, "HLTV" );
159 }
160 }
161
162 return 0;
163 }
164
165 /*
166 * Converts the time played in the server into a descriptive string
167 *
168 * @param time_played - The time played
169 * @param output - The output string
170 * @param output_len - The max length of the output string
171 * @param steam_format (optional) - If true, it will be in the Steam format of "View Game Info" (eg. 1h 59m 13s, or 12m 4s). If false, it will be in HH:MM:SS format (default: false)
172 *
173 * @return The length of the output string
174 *
175 */
176 stock sq_timeplayed(const Float:time_played,output[],const output_len,bool:steam_format=false)
177 {
178 new iSeconds = floatround(time_played, floatround_floor);
179 new iMinutes = iSeconds / 60;
180 new iHours = iMinutes / 60;
181
182 iSeconds %= 60;
183 iMinutes %= 60;
184
185 new iLen;
186
187 if( steam_format )
188 {
189 if( iHours )
190 {
191 iLen = formatex( output, output_len, "%dh ", iHours );
192 }
193
194 if( iMinutes || iLen )
195 {
196 iLen += formatex( output[ iLen ], output_len - iLen, "%dm ", iMinutes );
197 }
198
199 if( iSeconds || iLen )
200 {
201 iLen += formatex( output[ iLen ], output_len - iLen, "%ds", iSeconds );
202 }
203 }
204 else
205 {
206 iLen = formatex( output, output_len, "%d:%02d:%02d", iHours, iMinutes, iSeconds );
207 }
208
209 return iLen;
210 }
211
212 /*
213 * Converts The Ship's response for game mode into a string
214 *
215 * @param game_mode - The game mode of the server
216 * @param output - The output string
217 * @param output_len - The max length of the output string
218 *
219 * @return The length of the output string on success, 0 on failure
220 *
221 */
222 enum _:SHIP_GAMEMODES
223 {
224 SHIP_GAMEMODE_HUNT,
225 SHIP_GAMEMODE_ELIM,
226 SHIP_GAMEMODE_DUEL,
227 SHIP_GAMEMODE_DM,
228 SHIP_GAMEMODE_TEAM_VIP,
229 SHIP_GAMEMODE_TEAM_ELIM
230 };
231 stock sq_theship_gamemode(const game_mode,output[],const output_len)
232 {
233 // 0x00 for Hunt, 0x01 for Elimination, 0x02 for Duel, 0x03 for Deathmatch, 0x04 for Team VIP, 0x05 for Team Elimination
234
235 static const szGameModes[ SHIP_GAMEMODES ][ ] =
236 {
237 "Hunt",
238 "Elimination",
239 "Duel",
240 "Deathmatch",
241 "Team VIP",
242 "Team Elimination"
243 };
244
245 return ( 0 <= game_mode < SHIP_GAMEMODES ) ? copy( output, output_len, szGameModes[ game_mode ] ) : 0;
246 }
247
248 /*
249 * Reads a long from a buffer at a given start position
250 *
251 * @param buffer - The buffer to read from
252 * @param buffer_len - The length of the buffer
253 * @param start - The start position of the buffer
254 * @param result - The integer that is read is passed into that variable by reference
255 *
256 * @return Returns the end position in the buffer where the integer stops
257 *
258 */
259 stock sq_readlong(const {Array,_}:buffer,const buffer_len,start,&result)
260 {
261 return sq_readint( buffer, buffer_len, start, 4, result, true );
262 }
263
264 /*
265 * Reads a short from a buffer at a given start position
266 *
267 * @param buffer - The buffer to read from
268 * @param buffer_len - The length of the buffer
269 * @param start - The start position of the buffer
270 * @param result - The integer that is read is passed into that variable by reference
271 *
272 * @return Returns the end position in the buffer where the integer stops
273 *
274 */
275 stock sq_readshort(const {Array,_}:buffer,const buffer_len,start,&result)
276 {
277 return sq_readint( buffer, buffer_len, start, 2, result, false );
278 }
279
280 /*
281 * Reads a byte from a buffer at a given start position
282 *
283 * @param buffer - The buffer to read from
284 * @param buffer_len - The length of the buffer
285 * @param start - The start position of the buffer
286 * @param result - The integer that is read is passed into that variable by reference
287 *
288 * @return Returns the end position in the buffer where the integer stops
289 *
290 */
291 stock sq_readbyte(const {Array,_}:buffer,const buffer_len,start,&result)
292 {
293 return sq_readint( buffer, buffer_len, start, 1, result, false );
294 }
295
296 /*
297 * Reads a float from a buffer at a given start position
298 *
299 * @param buffer - The buffer to read from
300 * @param buffer_len - The length of the buffer
301 * @param start - The start position of the buffer
302 * @param result - The float that is read is passed into that variable by reference
303 *
304 * @return Returns the end position in the buffer where the float stops
305 *
306 */
307 stock sq_readfloat(const {Array,_}:buffer,const buffer_len,start,&Float:result)
308 {
309 return sq_readint( buffer, buffer_len, start, 4, _:result, false );
310 }
311
312 /*
313 * Reads an integer from a buffer at a given start position for a specific number of bytes
314 *
315 * @param buffer - The buffer to read from
316 * @param buffer_len - The length of the buffer
317 * @param start - The start position of the buffer
318 * @param bytes - The number of bytes to read
319 * @param result - The float that is read is passed into that variable by reference
320 * @param check_neg (optional) - If true, it checks if the integer is negative, otherwise it doesn't check (default: true)
321 *
322 * @return Returns the end position in the buffer where the integer stops
323 *
324 */
325 stock sq_readint(const {Array,_}:buffer,const buffer_len,start,bytes,&result,bool:check_neg=true)
326 {
327 result = 0;
328
329 new iPos = start;
330
331 if( ( iPos + bytes - 1 ) < buffer_len )
332 {
333 new bool:bNegative = ( check_neg && ArrayGetCell( Array:buffer, iPos + bytes - 1 ) < 0 );
334 new iTemp;
335
336 for( new i = 0; i < bytes; i++ )
337 {
338 result = sq_fixedunsigned8( ArrayGetCell( Array:buffer, iPos++ ) );
339
340 if( bNegative )
341 {
342 result = 0xFF - result;
343 }
344
345 iTemp += ( result << ( 8 * i ) );
346 }
347
348 if( bNegative )
349 {
350 iTemp = ( iTemp + 1 ) * -1;
351 }
352
353 result = iTemp;
354 }
355 else
356 {
357 iPos += bytes;
358 }
359
360 return iPos;
361 }
362
363 /*
364 * Reads a string from a buffer at given start position
365 *
366 * @param buffer - The buffer to read from
367 * @param buffer_len - The length of the buffer
368 * @param start - The start position of the buffer
369 * @param output - The output string
370 * @param output_len - The max length of the output string
371 *
372 * @return Returns the end position of where the string stops
373 *
374 */
375 stock sq_readstring(const {Array,_}:buffer,const buffer_len,start,output[],const output_len)
376 {
377 new iPos = start - 1;
378
379 new cChar, iLen;
380 while( ++iPos < buffer_len && ( cChar = ArrayGetCell( Array:buffer, iPos ) ) != 0 )
381 {
382 if( iLen < output_len )
383 {
384 output[ iLen++ ] = cChar;
385 }
386 }
387
388 output[ iLen ] = 0;
389
390 return ( iPos + 1 );
391 }
392
393 /*
394 * Fixes a value to an unsigned 8-bit integer
395 *
396 * @param value - The value to be fixed
397 *
398 * @return Returns the fixed unsigned 8-bit integer
399 *
400 */
401 stock sq_fixedunsigned8(value)
402 {
403 value = clamp( value, -0xFF, 0xFF );
404
405 if( value < 0 )
406 {
407 value = 0xFF + value + 1;
408 }
409
410 return value;
411 }
412 /* AMXX-Studio Notes - DO NOT MODIFY BELOW HERE
413 *{\\ rtf1\\ ansi\\ deff0{\\ fonttbl{\\ f0\\ fnil Tahoma;}}\n\\ viewkind4\\ uc1\\ pard\\ lang1033\\ f0\\ fs16 \n\\ par }
414 */
415