Remove reference, moved to separate repo

This commit is contained in:
mmorrison 2019-02-04 00:17:44 -06:00
parent 361aea2417
commit 0ac80cc139
50 changed files with 3 additions and 7074 deletions

View file

@ -353,8 +353,9 @@ Games List
* World in Conflict
> Want support for one of these games? Please open an issue to show your interest!
> __Know how to code?__ Protocols for most of the games above are documented
> in the /reference folder, ready for you to develop into GameDig!
> __Know how to code?__ Protocol details for many of the games above are documented
> at https://github.com/sonicsnes/legacy-query-library-archive
> , ready for you to develop into GameDig!
> Don't see your game listed here?
>

View file

@ -1,5 +0,0 @@
The files in this folder are INDIVIDUALLY LICENSED.
The applicable license is located in the header of each individual file.
These files are not covered by the node-GameDig project license.
The source of node-GameDig does not use or execute the content of
any file of this folder, and maintains a separate, unrelated license.

View file

@ -1,2 +0,0 @@
gamedig note:
connect over TCP, and the data just starts coming, no packet needs sent?

View file

@ -1,276 +0,0 @@
LICENSE: The Artistic License 2.0
/*
* qstat.h
* by Steve Jankowski
* steve@qstat.org
* http://www.qstat.org
*
* Copyright 1996,1997,1998,1999,2000,2001,2002 by Steve Jankowski
*/
{
/* BFRIS */
BFRIS_SERVER, /* id */
"BFS", /* type_prefix */
"bfs", /* type_string */
"-bfs", /* type_option */
"BFRIS", /* game_name */
0, /* master */
BFRIS_DEFAULT_PORT, /* default_port */
0, /* port_offset */
TF_TCP_CONNECT, /* flags */
"Rules", /* game_rule */
"BFRIS", /* template_var */
NULL, /* status_packet */
0, /* status_len */
NULL, /* player_packet */
0, /* player_len */
NULL, /* rule_packet */
0, /* rule_len */
NULL, /* master_packet */
0, /* master_len */
NULL, /* master_protocol */
NULL, /* master_query */
display_bfris_player_info, /* display_player_func */
display_server_rules, /* display_rule_func */
raw_display_bfris_player_info,/* display_raw_player_func */
raw_display_server_rules, /* display_raw_rule_func */
xml_display_bfris_player_info, /* display_xml_player_func */
xml_display_server_rules, /* display_xml_rule_func */
send_bfris_request_packet, /* status_query_func */
NULL, /* rule_query_func */
NULL, /* player_query_func */
deal_with_bfris_packet, /* packet_func */
},
/* postions of map name, player name (in player substring), zero-based */
#define BFRIS_MAP_POS 18
#define BFRIS_PNAME_POS 11
query_status_t deal_with_bfris_packet(struct qserver *server, char *rawpkt, int pktlen)
{
int i, player_data_pos, nplayers;
SavedData *sdata;
unsigned char *saved_data;
int saved_data_size;
debug( 2, "deal_with_bfris_packet %p, %d", server, pktlen );
server->ping_total += time_delta(&packet_recv_time, &server->packet_time1);
/* add to the data previously saved */
sdata = &server->saved_data;
if (!sdata->data)
{
sdata->data = (char*)malloc(pktlen);
}
else
{
sdata->data = (char*)realloc(sdata->data, sdata->datalen + pktlen);
}
memcpy(sdata->data + sdata->datalen, rawpkt, pktlen);
sdata->datalen += pktlen;
saved_data = (unsigned char*)sdata->data;
saved_data_size = sdata->datalen;
/* after we get the server portion of the data, server->game != NULL */
if (!server->game)
{
/* server data goes up to map name */
if (sdata->datalen <= BFRIS_MAP_POS)
{
return INPROGRESS;
}
/* see if map name is complete */
player_data_pos = 0;
for (i = BFRIS_MAP_POS; i < saved_data_size; i++)
{
if (saved_data[i] == '\0')
{
player_data_pos = i + 1;
/* data must extend beyond map name */
if (saved_data_size <= player_data_pos)
{
return INPROGRESS;
}
break;
}
}
/* did we find beginning of player data? */
if (!player_data_pos)
{
return INPROGRESS;
}
/* now we can go ahead and fill in server data */
server->map_name = strdup((char*)saved_data + BFRIS_MAP_POS);
server->max_players = saved_data[12];
server->protocol_version = saved_data[11];
/* save game type */
switch (saved_data[13] &15)
{
case 0:
server->game = "FFA";
break;
case 5:
server->game = "Rover";
break;
case 6:
server->game = "Occupation";
break;
case 7:
server->game = "SPAAL";
break;
case 8:
server->game = "CTF";
break;
default:
server->game = "unknown";
break;
}
server->flags |= FLAG_DO_NOT_FREE_GAME;
add_rule(server, server->type->game_rule, server->game, NO_FLAGS);
if (get_server_rules)
{
char buf[24];
/* server revision */
sprintf(buf, "%d", (unsigned int)saved_data[11]);
add_rule(server, "Revision", buf, NO_FLAGS);
/* latency */
sprintf(buf, "%d", (unsigned int)saved_data[10]);
add_rule(server, "Latency", buf, NO_FLAGS);
/* player allocation */
add_rule(server, "Allocation", saved_data[13] &16 ? "Automatic" : "Manual", NO_FLAGS);
}
}
/* If we got this far, we know the data saved goes at least to the start of
the player information, and that the server data is taken care of.
*/
/* start of player data */
player_data_pos = BFRIS_MAP_POS + strlen((char*)saved_data + BFRIS_MAP_POS) + 1;
/* ensure all player data have arrived */
nplayers = 0;
while (saved_data[player_data_pos] != '\0')
{
player_data_pos += BFRIS_PNAME_POS;
/* does player data extend to player name? */
if (saved_data_size <= player_data_pos + 1)
{
return INPROGRESS;
}
/* does player data extend to end of player name? */
for (i = 0; player_data_pos + i < saved_data_size; i++)
{
if (saved_data_size == player_data_pos + i + 1)
{
return INPROGRESS;
}
if (saved_data[player_data_pos + i] == '\0')
{
player_data_pos += i + 1;
nplayers++;
break;
}
}
}
/* all player data are complete */
server->num_players = nplayers;
if (get_player_info)
{
/* start of player data */
player_data_pos = BFRIS_MAP_POS + strlen((char*)saved_data + BFRIS_MAP_POS) + 1;
for (i = 0; i < nplayers; i++)
{
struct player *player;
player = add_player(server, saved_data[player_data_pos]);
player->ship = saved_data[player_data_pos + 1];
player->ping = saved_data[player_data_pos + 2];
player->frags = saved_data[player_data_pos + 3];
player->team = saved_data[player_data_pos + 4];
switch (player->team)
{
case 0:
player->team_name = "silver";
break;
case 1:
player->team_name = "red";
break;
case 2:
player->team_name = "blue";
break;
case 3:
player->team_name = "green";
break;
case 4:
player->team_name = "purple";
break;
case 5:
player->team_name = "yellow";
break;
case 6:
player->team_name = "cyan";
break;
default:
player->team_name = "unknown";
break;
}
player->flags |= PLAYER_FLAG_DO_NOT_FREE_TEAM;
player->room = saved_data[player_data_pos + 5];
/* score is little-endian integer */
player->score = saved_data[player_data_pos + 7] +
(saved_data[player_data_pos + 8] << 8) +
(saved_data[player_data_pos + 9] << 16) +
(saved_data[player_data_pos + 10] << 24);
/* for archs with > 4-byte int */
if (player->score &0x80000000)
{
player->score = - (~(player->score)) - 1;
}
player_data_pos += BFRIS_PNAME_POS;
player->name = strdup((char*)saved_data + player_data_pos);
player_data_pos += strlen(player->name) + 1;
}
}
server->server_name = BFRIS_SERVER_NAME;
return DONE_FORCE;
}

View file

@ -1,2 +0,0 @@
I was under the impression all the crysis games used gamespy?
If anyone notices a problem, this is reference for some old cryengine protocol.

View file

@ -1,100 +0,0 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* $Id: cry.php,v 1.2 2008/04/22 18:52:27 tombuskens Exp $
*/
[cry]
rules = "\x7f\xff\xff\xffrules"
status = "\x7f\xff\xff\xffstatus"
players = "\x7f\xff\xff\xffplayers"
[farcry2]
status = "\x06\x01\x00\x00\x2b\xbf\x53\x51\xdc\x80\x19\xb8\xb0\x57\xa3\x75"
require_once GAMEQ_BASE . 'Protocol.php';
/**
* CryEngine protocol
*
* @author Tom Buskens <t.buskens@deviation.nl>
* @version $Revision: 1.2 $
*/
class GameQ_Protocol_cry extends GameQ_Protocol
{
public function rules()
{
// Header
$this->header();
// Rules
while ($this->p->getLength()) {
$this->r->add($this->p->readString(), $this->p->readString());
}
}
public function status()
{
// Header
$this->header();
// Unknown
$this->p->read(15);
$this->r->add('hostname', $this->p->readString());
$this->r->add('mod', $this->p->readString());
$this->r->add('gametype', $this->p->readString());
$this->r->add('map', $this->p->readString());
$this->r->add('num_players', $this->p->readInt8());
$this->r->add('max_players', $this->p->readInt8());
$this->r->add('password', $this->p->readInt8());
$this->p->read(2);
$this->r->add('punkbuster', $this->p->readInt8());
}
public function players()
{
$this->header();
$this->p->skip(2);
while ($this->p->getLength()) {
$this->r->addPlayer('name', $this->p->readString());
$this->r->addPlayer('team', $this->p->readString());
$this->p->skip(1);
$this->r->addPlayer('score', $this->p->readInt8());
$this->p->skip(3);
$this->r->addPlayer('ping', $this->p->readInt8());
$this->p->skip(7);
}
}
private function header()
{
if ($this->p->read(4) !== "\x7f\xff\xff\xff") {
throw new GameQ_ParsingException($this->p);
}
$this->p->skip(2);
}
}
?>

View file

@ -1,326 +0,0 @@
LICENSE: The Artistic License 2.0
/*
* qstat.h
* by Steve Jankowski
* steve@qstat.org
* http://www.qstat.org
*
* Copyright 1996,1997,1998,1999,2000,2001,2002 by Steve Jankowski
*/
{
/* CRYSIS PROTOCOL */
CRYSIS_PROTOCOL_SERVER, /* id */
"CRYSIS", /* type_prefix */
"crysis", /* type_string */
"-crysis", /* type_option */
"Crysis", /* game_name */
0, /* master */
0, /* default_port */
0, /* port_offset */
TF_TCP_CONNECT|TF_QUERY_ARG_REQUIRED|TF_QUERY_ARG, /* flags */
"gamerules", /* game_rule */
"CRYSISPROTOCOL", /* template_var */
NULL, /* status_packet */
0, /* status_len */
NULL, /* player_packet */
0, /* player_len */
NULL, /* rule_packet */
0, /* rule_len */
NULL, /* master_packet */
0, /* master_len */
NULL, /* master_protocol */
NULL, /* master_query */
NULL, /* display_player_func */
display_server_rules, /* display_rule_func */
NULL, /* display_raw_player_func */
raw_display_server_rules, /* display_raw_rule_func */
xml_display_player_info, /* display_xml_player_func */
xml_display_server_rules, /* display_xml_rule_func */
send_crysis_request_packet, /* status_query_func */
NULL, /* rule_query_func */
NULL, /* player_query_func */
deal_with_crysis_packet, /* packet_func */
},
/*
* qstat 2.8
* by Steve Jankowski
*
* Crysis query protocol
* Copyright 2012 Steven Hartland
*
* Licensed under the Artistic License, see LICENSE.txt for license terms
*
*/
#include <sys/types.h>
#ifndef _WIN32
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#else
#include <winsock.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include "debug.h"
#include "utils.h"
#include "qstat.h"
#include "md5.h"
#include "packet_manip.h"
char *decode_crysis_val( char *val )
{
// Very basic html conversion
val = str_replace( val, "&quot;", "\"" );
return str_replace( val, "&amp;", "&" );
}
query_status_t send_crysis_request_packet( struct qserver *server )
{
char cmd[256], buf[1024], *password, *md5;
debug( 2, "challenge: %ld", server->challenge );
switch ( server->challenge )
{
case 0:
// Not seen a challenge yet, request it
server->challenge++;
sprintf( cmd, "challenge" );
break;
case 1:
server->challenge++;
password = get_param_value( server, "password", "" );
sprintf( cmd, "%s:%s", server->challenge_string, password );
md5 = md5_hex( cmd, strlen( cmd ) );
sprintf( cmd, "authenticate %s", md5 );
free( md5 );
break;
case 2:
// NOTE: we currently don't support player info
server->challenge++;
server->flags |= TF_STATUS_QUERY;
server->n_servers = 3;
sprintf( cmd, "status" );
break;
case 3:
return DONE_FORCE;
}
server->saved_data.pkt_max = -1;
sprintf(buf, "POST /RPC2 HTTP/1.1\015\012Keep-Alive: 300\015\012User-Agent: qstat %s\015\012Content-Length: %d\015\012Content-Type: text/xml\015\012\015\012<?xml version=\"1.0\" encoding=\"UTF-8\"?><methodCall><methodName>%s</methodName><params /></methodCall>", VERSION, (int)(98 + strlen(cmd)), cmd);
return send_packet( server, buf, strlen( buf ) );
}
query_status_t valid_crysis_response( struct qserver *server, char *rawpkt, int pktlen )
{
char *s;
int len;
int cnt = packet_count( server );
if ( 0 == cnt && 0 != strncmp( "HTTP/1.1 200 OK", rawpkt, 15 ) )
{
// not valid response
return REQ_ERROR;
}
s = strnstr(rawpkt, "Content-Length: ", pktlen );
if ( NULL == s )
{
// not valid response
return INPROGRESS;
}
s += 16;
if ( 1 != sscanf( s, "%d", &len ) )
{
return INPROGRESS;
}
s = strnstr(rawpkt, "\015\012\015\012", pktlen );
if ( NULL == s )
{
return INPROGRESS;
}
s += 4;
if ( pktlen != ( s - rawpkt + len ) )
{
return INPROGRESS;
}
return DONE_FORCE;
}
char* crysis_response( struct qserver *server, char *rawpkt, int pktlen )
{
char *s, *e;
int len = pktlen;
s = strnstr(rawpkt, "<methodResponse><params><param><value><string>", len );
if ( NULL == s )
{
// not valid response
return NULL;
}
s += 46;
len += rawpkt - s;
e = strnstr(s, "</string></value>", len );
if ( NULL == e )
{
// not valid response
return NULL;
}
*e = '\0';
return strdup( s );
}
query_status_t deal_with_crysis_packet( struct qserver *server, char *rawpkt, int pktlen )
{
char *s, *val, *line;
query_status_t state = INPROGRESS;
debug( 2, "processing..." );
if ( ! server->combined )
{
state = valid_crysis_response( server, rawpkt, pktlen );
server->retry1 = n_retries;
if ( 0 == server->n_requests )
{
server->ping_total = time_delta( &packet_recv_time, &server->packet_time1 );
server->n_requests++;
}
switch ( state )
{
case INPROGRESS:
{
// response fragment recieved
int pkt_id;
int pkt_max;
// We're expecting more to come
debug( 5, "fragment recieved..." );
pkt_id = packet_count( server );
pkt_max = pkt_id++;
if ( ! add_packet( server, 0, pkt_id, pkt_max, pktlen, rawpkt, 1 ) )
{
// fatal error e.g. out of memory
return MEM_ERROR;
}
// combine_packets will call us recursively
return combine_packets( server );
}
case DONE_FORCE:
break; // single packet response fall through
default:
return state;
}
}
if ( DONE_FORCE != state )
{
state = valid_crysis_response( server, rawpkt, pktlen );
switch ( state )
{
case DONE_FORCE:
break; // actually process
default:
return state;
}
}
debug( 3, "packet: challenge = %ld", server->challenge );
switch ( server->challenge )
{
case 1:
s = crysis_response( server, rawpkt, pktlen );
if ( NULL != s )
{
server->challenge_string = s;
return send_crysis_request_packet( server );
}
return REQ_ERROR;
case 2:
s = crysis_response( server, rawpkt, pktlen );
if ( NULL == s )
{
return REQ_ERROR;
}
if ( 0 != strncmp( s, "authorized", 10 ) )
{
free( s );
return REQ_ERROR;
}
free( s );
return send_crysis_request_packet( server );
case 3:
s = crysis_response( server, rawpkt, pktlen );
if ( NULL == s )
{
return REQ_ERROR;
}
}
// Correct ping
// Not quite right but gives a good estimate
server->ping_total = ( server->ping_total * server->n_requests ) / 2;
debug( 3, "processing response..." );
s = decode_crysis_val( s );
line = strtok( s, "\012" );
// NOTE: id=XXX and msg=XXX will be processed by the mod following the one they where the response of
while ( NULL != line )
{
debug( 4, "LINE: %s\n", line );
val = strstr( line, ":" );
if ( NULL != val )
{
*val = '\0';
val+=2;
debug( 4, "var: %s, val: %s", line, val );
if ( 0 == strcmp( "name", line ) )
{
server->server_name = strdup( val );
}
else if ( 0 == strcmp( "level", line ) )
{
server->map_name = strdup( val );
}
else if ( 0 == strcmp( "players", line ) )
{
if ( 2 == sscanf( val, "%d/%d", &server->num_players, &server->max_players) )
{
}
}
else if (
0 == strcmp( "version", line ) ||
0 == strcmp( "gamerules", line ) ||
0 == strcmp( "time remaining", line )
)
{
add_rule( server, line, val, NO_FLAGS );
}
}
line = strtok( NULL, "\012" );
}
gettimeofday( &server->packet_time1, NULL );
return DONE_FORCE;
}

View file

@ -1,56 +0,0 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* $Id: cs2d.php,v 1.1 2008/04/14 18:04:50 tombuskens Exp $
*/
[cs2d]
status = "\xfa\x00"
require_once GAMEQ_BASE . 'Protocol.php';
/**
* Counterstrike 2d Protocol
*
* @author Tom Buskens <t.buskens@deviation.nl>
* @version $Revision: 1.1 $
*/
class GameQ_Protocol_cs2d extends GameQ_Protocol
{
public function status()
{
$this->p->skip(2);
$this->r->add('hostname', $this->readString());
$this->r->add('password', $this->p->readInt8());
$this->r->add('mapname', $this->readString());
$this->r->add('num_players', $this->p->readInt8());
$this->r->add('max_players', $this->p->readInt8());
$this->r->add('fog_of_war', $this->p->readInt8());
$this->r->add('war_mode', $this->p->readInt8());
$this->r->add('version', $this->readString());
}
private function readString()
{
$str = $this->p->readString("\x0D");
$this->p->skip(1);
return $str;
}
}
?>

View file

@ -1,70 +0,0 @@
/*----------------------------------------------------------------------------------------------------------\
| |
| [ LIVE GAME SERVER LIST ] [ © RICHARD PERRY FROM GREYCUBE.COM ] |
| |
| Released under the terms and conditions of the GNU General Public License Version 3 (http://gnu.org) |
| |
\-----------------------------------------------------------------------------------------------------------*/
function lgsl_query_29(&$server, &$lgsl_need, &$lgsl_fp)
{
//---------------------------------------------------------+
// REFERENCE: http://www.cs2d.com/servers.php
if ($lgsl_need['s'] || $lgsl_need['e'])
{
$lgsl_need['s'] = FALSE;
$lgsl_need['e'] = FALSE;
fwrite($lgsl_fp, "\x01\x00\x03\x10\x21\xFB\x01\x75\x00");
$buffer = fread($lgsl_fp, 4096);
if (!$buffer) { return FALSE; }
$buffer = substr($buffer, 4); // REMOVE HEADER
$server['e']['bit_flags'] = ord(lgsl_cut_byte($buffer, 1)) - 48;
$server['s']['name'] = lgsl_cut_pascal($buffer);
$server['s']['map'] = lgsl_cut_pascal($buffer);
$server['s']['players'] = ord(lgsl_cut_byte($buffer, 1));
$server['s']['playersmax'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['gamemode'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['bots'] = ord(lgsl_cut_byte($buffer, 1));
$server['s']['password'] = ($server['e']['bit_flags'] & 1) ? "1" : "0";
$server['e']['registered_only'] = ($server['e']['bit_flags'] & 2) ? "1" : "0";
$server['e']['fog_of_war'] = ($server['e']['bit_flags'] & 4) ? "1" : "0";
$server['e']['friendlyfire'] = ($server['e']['bit_flags'] & 8) ? "1" : "0";
}
if ($lgsl_need['p'])
{
$lgsl_need['p'] = FALSE;
fwrite($lgsl_fp, "\x01\x00\xFB\x05");
$buffer = fread($lgsl_fp, 4096);
if (!$buffer) { return FALSE; }
$buffer = substr($buffer, 4); // REMOVE HEADER
$player_total = ord(lgsl_cut_byte($buffer, 1));
for ($i=0; $i<$player_total; $i++)
{
$server['p'][$i]['pid'] = ord(lgsl_cut_byte($buffer, 1));
$server['p'][$i]['name'] = lgsl_cut_pascal($buffer);
$server['p'][$i]['team'] = ord(lgsl_cut_byte($buffer, 1));
$server['p'][$i]['score'] = lgsl_unpack(lgsl_cut_byte($buffer, 4), "l");
$server['p'][$i]['deaths'] = lgsl_unpack(lgsl_cut_byte($buffer, 4), "l");
}
}
//---------------------------------------------------------+
return TRUE;
}

View file

@ -1,58 +0,0 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* $Id: cube.php,v 1.1 2007/07/04 09:08:36 tombuskens Exp $
*/
[cube]
status = "\x00"
require_once GAMEQ_BASE . 'Protocol.php';
/**
* Cube Engine protocol
*
* @author Tom Buskens <t.buskens@deviation.nl>
* @version $Revision: 1.1 $
*/
class GameQ_Protocol_cube extends GameQ_Protocol
{
/*
* status packet
*/
public function status()
{
// Header
if (!$this->p->read() == "\x00") {
throw new GameQ_ParsingException($this->p);
}
$this->p->skip(2);
// Vars
$this->r->add('protocol', $this->p->readInt8());
$this->r->add('mode', $this->p->readInt8());
$this->r->add('num_players', $this->p->readInt8());
$this->r->add('time_remaining', $this->p->readInt8());
$this->r->add('map', $this->p->readString());
$this->r->add('servername', $this->p->readString());
$this->r->add('max_players', $this->p->readInt8());
}
}
?>

View file

@ -1,79 +0,0 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* $Id: sauerbraten.php,v 1.2 2008/06/25 13:50:47 tombuskens Exp $
*/
[sauerbraten]
status = "\xFF"
require_once GAMEQ_BASE . 'Protocol.php';
/**
* Sauerbraten / Cube 2 Engine protocol
*
* @author Tom Buskens <t.buskens@deviation.nl>
* @version $Revision: 1.2 $
*/
class GameQ_Protocol_sauerbraten extends GameQ_Protocol
{
private function getint()
{
$i = $this->p->readInt8();
if ($i == 0x80)
{
$i = $this->p->readInt8();
$i |= $this->p->readInt8() << 8;
}
else if ($i == 0x81)
{
$i = $this->p->readInt8();
$i |= $this->p->readInt8() << 8;
$i |= $this->p->readInt8() << 16;
$i |= $this->p->readInt8() << 24;
}
return $i;
}
/*
* status packet
*/
public function status()
{
// Header
if (!$this->p->read() == "\x00") {
throw new GameQ_ParsingException($this->p);
}
// Vars
$this->r->add('num_players', $this->getint());
$this->r->add('num_attributes', $this->getint());
$this->r->add('protocol', $this->getint());
$this->r->add('servermode', $this->getint());
$this->r->add('time_remaining', $this->getint());
$this->r->add('max_players', $this->getint());
$this->r->add('locked', $this->getint());
$this->r->add('map', $this->p->readString());
$this->r->add('servername', $this->p->readString());
}
}
?>

View file

@ -1,168 +0,0 @@
/*----------------------------------------------------------------------------------------------------------\
| |
| [ LIVE GAME SERVER LIST ] [ © RICHARD PERRY FROM GREYCUBE.COM ] |
| |
| Released under the terms and conditions of the GNU General Public License Version 3 (http://gnu.org) |
| |
\-----------------------------------------------------------------------------------------------------------*/
function lgsl_query_24(&$server, &$lgsl_need, &$lgsl_fp)
{
//---------------------------------------------------------+
// REFERENCE: http://cubelister.sourceforge.net
fwrite($lgsl_fp, "\x21\x21");
$buffer = fread($lgsl_fp, 4096);
if (!$buffer) { return FALSE; }
$buffer = substr($buffer, 2); // REMOVE HEADER
//---------------------------------------------------------+
if ($buffer[0] == "\x1b") // CUBE 1
{
// RESPONSE IS XOR ENCODED FOR SOME STRANGE REASON
for ($i=0; $i<strlen($buffer); $i++) { $buffer[$i] = chr(ord($buffer[$i]) ^ 0x61); }
$server['s']['game'] = "Cube";
$server['e']['netcode'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['gamemode'] = ord(lgsl_cut_byte($buffer, 1));
$server['s']['players'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['timeleft'] = lgsl_time(ord(lgsl_cut_byte($buffer, 1)) * 60);
$server['s']['map'] = lgsl_cut_string($buffer);
$server['s']['name'] = lgsl_cut_string($buffer);
$server['s']['playersmax'] = "0"; // NOT PROVIDED
// DOES NOT RETURN PLAYER INFORMATION
return TRUE;
}
elseif ($buffer[0] == "\x80") // ASSAULT CUBE
{
$server['s']['game'] = "AssaultCube";
$server['e']['netcode'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['version'] = lgsl_unpack(lgsl_cut_byte($buffer, 2), "S");
$server['e']['gamemode'] = ord(lgsl_cut_byte($buffer, 1));
$server['s']['players'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['timeleft'] = lgsl_time(ord(lgsl_cut_byte($buffer, 1)) * 60);
$server['s']['map'] = lgsl_cut_string($buffer);
$server['s']['name'] = lgsl_cut_string($buffer);
$server['s']['playersmax'] = ord(lgsl_cut_byte($buffer, 1));
}
elseif ($buffer[1] == "\x05") // CUBE 2 - SAUERBRATEN
{
$server['s']['game'] = "Sauerbraten";
$server['s']['players'] = ord(lgsl_cut_byte($buffer, 1));
$info_returned = ord(lgsl_cut_byte($buffer, 1)); // CODED FOR 5
$server['e']['netcode'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['version'] = lgsl_unpack(lgsl_cut_byte($buffer, 2), "S");
$server['e']['gamemode'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['timeleft'] = lgsl_time(ord(lgsl_cut_byte($buffer, 1)) * 60);
$server['s']['playersmax'] = ord(lgsl_cut_byte($buffer, 1));
$server['s']['password'] = ord(lgsl_cut_byte($buffer, 1)); // BIT FIELD
$server['s']['password'] = $server['s']['password'] & 4 ? "1" : "0";
$server['s']['map'] = lgsl_cut_string($buffer);
$server['s']['name'] = lgsl_cut_string($buffer);
}
elseif ($buffer[1] == "\x06") // BLOODFRONTIER
{
$server['s']['game'] = "Blood Frontier";
$server['s']['players'] = ord(lgsl_cut_byte($buffer, 1));
$info_returned = ord(lgsl_cut_byte($buffer, 1)); // CODED FOR 6
$server['e']['netcode'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['version'] = lgsl_unpack(lgsl_cut_byte($buffer, 2), "S");
$server['e']['gamemode'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['mutators'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['timeleft'] = lgsl_time(ord(lgsl_cut_byte($buffer, 1)) * 60);
$server['s']['playersmax'] = ord(lgsl_cut_byte($buffer, 1));
$server['s']['password'] = ord(lgsl_cut_byte($buffer, 1)); // BIT FIELD
$server['s']['password'] = $server['s']['password'] & 4 ? "1" : "0";
$server['s']['map'] = lgsl_cut_string($buffer);
$server['s']['name'] = lgsl_cut_string($buffer);
}
else // UNKNOWN
{
return FALSE;
}
//---------------------------------------------------------+
// CRAZY PROTOCOL - REQUESTS MUST BE MADE FOR EACH PLAYER
// BOTS ARE RETURNED BUT NOT INCLUDED IN THE PLAYER TOTAL
// AND THERE CAN BE ID GAPS BETWEEN THE PLAYERS RETURNED
if ($lgsl_need['p'] && $server['s']['players'])
{
$player_key = 0;
for ($player_id=0; $player_id<32; $player_id++)
{
fwrite($lgsl_fp, "\x00\x01".chr($player_id));
// READ PACKET
$buffer = fread($lgsl_fp, 4096);
if (!$buffer) { break; }
// CHECK IF PLAYER ID IS ACTIVE
if ($buffer[5] != "\x00")
{
if ($player_key < $server['s']['players']) { continue; }
break;
}
// IF PREVIEW PACKET GET THE FULL PACKET THAT FOLLOWS
if (strlen($buffer) < 15)
{
$buffer = fread($lgsl_fp, 4096);
if (!$buffer) { break; }
}
// REMOVE HEADER
$buffer = substr($buffer, 7);
// WE CAN NOW GET THE PLAYER DETAILS
if ($server['s']['game'] == "Blood Frontier")
{
$server['p'][$player_key]['pid'] = lgsl_unpack(lgsl_cut_byte($buffer, 1), "C");
$server['p'][$player_key]['ping'] = lgsl_unpack(lgsl_cut_byte($buffer, 1), "C");
$server['p'][$player_key]['ping'] = $server['p'][$player_key]['ping'] == 128 ? lgsl_unpack(lgsl_cut_byte($buffer, 2), "S") : $server['p'][$player_key]['ping'];
$server['p'][$player_key]['name'] = lgsl_cut_string($buffer);
$server['p'][$player_key]['team'] = lgsl_cut_string($buffer);
$server['p'][$player_key]['score'] = lgsl_unpack(lgsl_cut_byte($buffer, 1), "c");
$server['p'][$player_key]['damage'] = lgsl_unpack(lgsl_cut_byte($buffer, 1), "C");
$server['p'][$player_key]['deaths'] = lgsl_unpack(lgsl_cut_byte($buffer, 1), "C");
$server['p'][$player_key]['teamkills'] = lgsl_unpack(lgsl_cut_byte($buffer, 1), "C");
$server['p'][$player_key]['accuracy'] = lgsl_unpack(lgsl_cut_byte($buffer, 1), "C")."%";
$server['p'][$player_key]['health'] = lgsl_unpack(lgsl_cut_byte($buffer, 1), "c");
$server['p'][$player_key]['spree'] = lgsl_unpack(lgsl_cut_byte($buffer, 1), "C");
$server['p'][$player_key]['weapon'] = lgsl_unpack(lgsl_cut_byte($buffer, 1), "C");
}
else
{
$server['p'][$player_key]['pid'] = lgsl_unpack(lgsl_cut_byte($buffer, 1), "C");
$server['p'][$player_key]['name'] = lgsl_cut_string($buffer);
$server['p'][$player_key]['team'] = lgsl_cut_string($buffer);
$server['p'][$player_key]['score'] = lgsl_unpack(lgsl_cut_byte($buffer, 1), "c");
$server['p'][$player_key]['deaths'] = lgsl_unpack(lgsl_cut_byte($buffer, 1), "C");
$server['p'][$player_key]['teamkills'] = lgsl_unpack(lgsl_cut_byte($buffer, 1), "C");
$server['p'][$player_key]['accuracy'] = lgsl_unpack(lgsl_cut_byte($buffer, 1), "C")."%";
$server['p'][$player_key]['health'] = lgsl_unpack(lgsl_cut_byte($buffer, 1), "c");
$server['p'][$player_key]['armour'] = lgsl_unpack(lgsl_cut_byte($buffer, 1), "C");
$server['p'][$player_key]['weapon'] = lgsl_unpack(lgsl_cut_byte($buffer, 1), "C");
}
$player_key++;
}
}
//---------------------------------------------------------+
return TRUE;
}

View file

@ -1,284 +0,0 @@
LICENSE: The Artistic License 2.0
/*
* qstat.h
* by Steve Jankowski
* steve@qstat.org
* http://www.qstat.org
*
* Copyright 1996,1997,1998,1999,2000,2001,2002 by Steve Jankowski
*/
char cube2_serverstatus[3] = {'\x80', '\x10', '\x27'};
{
/* Cube 2/Sauerbraten/Blood Frontier */
CUBE2_SERVER, /* id */
"CUBE2", /* type_prefix */
"cube2", /* type_string */
"-cubes", /* type_option */
"Sauerbraten", /* game_name */
0, /* master */
CUBE2_DEFAULT_PORT, /* default_port */
1, /* port_offset */
0, /* flags */
"", /* game_rule */
"CUBE2", /* template_var */
cube2_serverstatus, /* status_packet */
sizeof(cube2_serverstatus), /* status_len */
NULL, /* player_packet */
0, /* player_len */
NULL, /* rule_packet */
0, /* rule_len */
NULL, /* master_packet */
0, /* master_len */
NULL, /* master_protocol */
NULL, /* master_query */
NULL, /* display_player_func */
display_server_rules, /* display_rule_func */
NULL, /* display_raw_player_func */
raw_display_server_rules, /* display_raw_rule_func */
NULL, /* display_xml_player_func */
xml_display_server_rules, /* display_xml_rule_func */
send_cube2_request_packet, /* status_query_func */
NULL, /* rule_query_func */
NULL, /* player_query_func */
deal_with_cube2_packet, /* packet_func */
},
/*
* qstat 2.12
* by Steve Jankowski
*
* Cube 2 / Sauerbraten protocol
* Copyright 2011 NoisyB
*
* Licensed under the Artistic License, see LICENSE.txt for license terms
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "debug.h"
#include "qstat.h"
#include "packet_manip.h"
struct offset
{
unsigned char *d;
int pos;
int len;
};
//#define SB_MASTER_SERVER "http://sauerbraten.org/masterserver/retrieve.do?item=list"
#define SB_PROTOCOL 258
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX_ATTR 255
#define MAX_STRING 1024
static int
getint (struct offset * d)
{
int val = 0;
if ( d->pos >= d->len )
{
return 0;
}
val = d->d[d->pos++] & 0xff; // 8 bit value
// except...
if ( val == 0x80 && d->pos < d->len - 2 ) // 16 bit value
{
val = (d->d[d->pos++] & 0xff);
val |= (d->d[d->pos++] & 0xff) << 8;
}
else if ( val == 0x81 && d->pos < d->len - 4 ) // 32 bit value
{
val = (d->d[d->pos++] & 0xff);
val |= (d->d[d->pos++] & 0xff) << 8;
val |= (d->d[d->pos++] & 0xff) << 16;
val |= (d->d[d->pos++] & 0xff) << 24;
}
return val;
}
static char * getstr( char *dest, int dest_len, struct offset *d )
{
int len = 0;
if (d->pos >= d->len)
{
return NULL;
}
len = MIN( dest_len, d->len - d->pos );
strncpy( dest, (const char *) d->d + d->pos, len )[len - 1] = 0;
d->pos += strlen (dest) + 1;
return dest;
}
static char* sb_getversion_s (int n)
{
static char *version_s[] =
{
"Justice",
"CTF",
"Assassin",
"Summer",
"Spring",
"Gui",
"Water",
"Normalmap",
"Sp",
"Occlusion",
"Shader",
"Physics",
"Mp",
"",
"Agc",
"Quakecon",
"Independence"
};
n = SB_PROTOCOL - n;
if (n >= 0 && (size_t) n < sizeof(version_s) / sizeof(version_s[0]))
{
return version_s[n];
}
return "unknown";
}
static char* sb_getmode_s(int n)
{
static char *mode_s[] =
{
"slowmo SP",
"slowmo DMSP",
"demo",
"SP",
"DMSP",
"ffa/default",
"coopedit",
"ffa/duel",
"teamplay",
"instagib",
"instagib team",
"efficiency",
"efficiency team",
"insta arena",
"insta clan arena",
"tactics arena",
"tactics clan arena",
"capture",
"insta capture",
"regen capture",
"assassin",
"insta assassin",
"ctf",
"insta ctf"
};
n += 6;
if (n >= 0 && (size_t) n < sizeof(mode_s) / sizeof(mode_s[0]))
{
return mode_s[n];
}
return "unknown";
}
query_status_t send_cube2_request_packet( struct qserver *server )
{
return send_packet( server, server->type->status_packet, server->type->status_len );
}
query_status_t deal_with_cube2_packet( struct qserver *server, char *rawpkt, int pktlen )
{
// skip unimplemented ack, crc, etc
int i;
int numattr;
int attr[MAX_ATTR];
char buf[MAX_STRING];
enum {
MM_OPEN = 0,
MM_VETO,
MM_LOCKED,
MM_PRIVATE
};
struct offset d;
d.d = (unsigned char *) rawpkt;
d.pos = 0;
d.len = pktlen;
server->ping_total += time_delta( &packet_recv_time, &server->packet_time1 );
getint( &d ); // we have the ping already
server->num_players = getint( &d );
numattr = getint( &d );
for ( i = 0; i < numattr && i < MAX_ATTR; i++ )
{
attr[i] = getint (&d);
}
server->protocol_version = attr[0];
sprintf( buf, "%d %s", attr[0], sb_getversion_s (attr[0]) );
add_rule( server, "version", buf, NO_FLAGS );
sprintf( buf, "%d %s", attr[1], sb_getmode_s (attr[1]) );
add_rule( server, "mode", buf, NO_FLAGS );
sprintf( buf, "%d", attr[2] );
add_rule( server, "seconds_left", buf, NO_FLAGS );
server->max_players = attr[3];
switch ( attr[5] )
{
case MM_OPEN:
sprintf( buf, "%d open", attr[5] );
break;
case MM_VETO:
sprintf( buf, "%d veto", attr[5] );
break;
case MM_LOCKED:
sprintf( buf, "%d locked", attr[5] );
break;
case MM_PRIVATE:
sprintf( buf, "%d private", attr[5] );
break;
default:
sprintf( buf, "%d unknown", attr[5] );
}
add_rule( server, "mm", buf, NO_FLAGS);
for ( i = 0; i < numattr && i < MAX_ATTR; i++ )
{
char buf2[MAX_STRING];
sprintf( buf, "attr%d", i );
sprintf( buf2, "%d", attr[i] );
add_rule( server, buf, buf2, NO_FLAGS );
}
getstr( buf, MAX_STRING, &d );
server->map_name = strdup(buf);
getstr( buf, MAX_STRING, &d );
server->server_name = strdup(buf);
return DONE_FORCE;
}

View file

@ -1,2 +0,0 @@
This is the doc for some descent 3 protocol that ISNT the gamespy
protocol. Not really sure what it's for.

View file

@ -1,223 +0,0 @@
LICENSE: The Artistic License 2.0
/*
* qstat.h
* by Steve Jankowski
* steve@qstat.org
* http://www.qstat.org
*
* Copyright 1996,1997,1998,1999,2000,2001,2002 by Steve Jankowski
*/
/* for some reason Descent3 uses a different request for pxo/non-pxo games. blah. */
unsigned char descent3_pxoinfoquery[] = {
0x01, /* "internal descent3 routing" */
0x29, /* request server info? (pxo listed servers) */
0x0b, 0x00, /* packet length (- routing byte) */
0x1b, 0x2f, 0xf4, 0x41, 0x09, 0x00, 0x00, 0x00 /* unknown */
};
unsigned char descent3_tcpipinfoquery[] = {
0x01, /* "internal descent3 routing" */
0x1e, /* request server info? (tcpip only servers) */
0x0b, 0x00, /* packet length (- routing byte) */
0x1b, 0x2f, 0xf4, 0x41, 0x09, 0x00, 0x00, 0x00 /* unknown */
};
/* http://ml.warpcore.org/d3dl/200101/msg00001.html
* http://ml.warpcore.org/d3dl/200101/msg00004.html */
unsigned char descent3_playerquery[] = {
0x01, /* "internal descent3 routing" */
0x72, /* MP_REQUEST_PLAYERLIST */
0x03, 0x00 /* packet length (- routing byte) */
};
{
/* DESCENT3 PROTOCOL */
DESCENT3_SERVER, /* id */
"D3S", /* type_prefix */
"d3s", /* type_string */
"-d3s", /* type_option */
"Descent3", /* game_name */
0, /* master */
DESCENT3_DEFAULT_PORT, /* default_port */
0, /* port_offset */
0, /* flags */
"gametype", /* game_rule */
"DESCENT3", /* template_var */
(char*) &descent3_tcpipinfoquery, /* status_packet */
sizeof( descent3_tcpipinfoquery), /* status_len */
(char*) &descent3_playerquery, /* player_packet */
sizeof( descent3_playerquery), /* player_len */
NULL, /* rule_packet */
0, /* rule_len */
NULL, /* master_packet */
0, /* master_len */
NULL, /* master_protocol */
NULL, /* master_query */
display_descent3_player_info, /* display_player_func */
display_server_rules, /* display_rule_func */
raw_display_descent3_player_info, /* display_raw_player_func */
raw_display_server_rules, /* display_raw_rule_func */
xml_display_descent3_player_info, /* display_xml_player_func */
xml_display_server_rules, /* display_xml_rule_func */
send_gps_request_packet, /* status_query_func */
NULL, /* rule_query_func */
NULL, /* player_query_func */
deal_with_descent3_packet, /* packet_func */
},
{
/* DESCENT3 PROTOCOL */
DESCENT3_PXO_SERVER, /* id */
"D3P", /* type_prefix */
"d3p", /* type_string */
"-d3p", /* type_option */
"Descent3 PXO protocol", /* game_name */
0, /* master */
DESCENT3_DEFAULT_PORT, /* default_port */
0, /* port_offset */
0, /* flags */
"gametype", /* game_rule */
"DESCENT3", /* template_var */
(char*) &descent3_pxoinfoquery, /* status_packet */
sizeof( descent3_pxoinfoquery), /* status_len */
(char*) &descent3_playerquery, /* player_packet */
sizeof( descent3_playerquery), /* player_len */
NULL, /* rule_packet */
0, /* rule_len */
NULL, /* master_packet */
0, /* master_len */
NULL, /* master_protocol */
NULL, /* master_query */
display_descent3_player_info, /* display_player_func */
display_server_rules, /* display_rule_func */
raw_display_descent3_player_info, /* display_raw_player_func */
raw_display_server_rules, /* display_raw_rule_func */
xml_display_descent3_player_info, /* display_xml_player_func */
xml_display_server_rules, /* display_xml_rule_func */
send_gps_request_packet, /* status_query_func */
NULL, /* rule_query_func */
NULL, /* player_query_func */
deal_with_descent3_packet, /* packet_func */
},
query_status_t deal_with_descent3_packet(struct qserver *server, char *rawpkt, int pktlen)
{
char *pkt;
char buf[24];
debug( 2, "deal_with_descent3_packet %p, %d", server, pktlen );
if (server->server_name == NULL)
{
server->ping_total += time_delta(&packet_recv_time, &server->packet_time1);
}
if (pktlen < 4)
{
fprintf(stderr, "short descent3 packet\n");
print_packet(server, rawpkt, pktlen);
return PKT_ERROR;
}
/* 'info' response */
if (rawpkt[1] == 0x1f)
{
if (server->server_name != NULL)
{
return PKT_ERROR;
}
pkt = &rawpkt[0x15];
server->server_name = strdup(pkt);
pkt += strlen(pkt) + 2;
server->map_name = strdup(pkt); /* mission name (blah.mn3) */
pkt += strlen(pkt) + 2;
add_rule(server, "level_name", pkt, NO_FLAGS);
pkt += strlen(pkt) + 2;
add_rule(server, "gametype", pkt, NO_FLAGS);
pkt += strlen(pkt) + 1;
sprintf(buf, "%hu", swap_short_from_little(pkt));
add_rule(server, "level_num", buf, NO_FLAGS);
pkt += 2;
server->num_players = swap_short_from_little(pkt);
pkt += 2;
server->max_players = swap_short_from_little(pkt);
pkt += 2;
/* unknown/undecoded fields.. stuff like permissible, banned items/ships, etc */
add_uchar_rule(server, "u0", pkt[0]);
add_uchar_rule(server, "u1", pkt[1]);
add_uchar_rule(server, "u2", pkt[2]);
add_uchar_rule(server, "u3", pkt[3]);
add_uchar_rule(server, "u4", pkt[4]);
add_uchar_rule(server, "u5", pkt[5]);
add_uchar_rule(server, "u6", pkt[6]);
add_uchar_rule(server, "u7", pkt[7]);
add_uchar_rule(server, "u8", pkt[8]);
add_uchar_rule(server, "randpowerup", (unsigned char)!(pkt[4] &1)); /*
randomize powerup spawn */
add_uchar_rule(server, "acccollisions", (unsigned char)((pkt[5] &4) > 0));
/* accurate collision detection */
add_uchar_rule(server, "brightships", (unsigned char)((pkt[5] &16) > 0));
/* bright player ships */
add_uchar_rule(server, "mouselook", (unsigned char)((pkt[6] &1) > 0)); /*
mouselook enabled */
sprintf(buf, "%s%s", (pkt[4] &16) ? "PP" : "CS", (pkt[6] &1) ? "-ML" : "");
add_rule(server, "servertype", buf, NO_FLAGS);
sprintf(buf, "%hhu", pkt[9]);
add_rule(server, "difficulty", buf, NO_FLAGS);
/* unknown/undecoded fields after known flags removed */
add_uchar_rule(server, "x4", (unsigned char)(pkt[4] &~(1+16)));
add_uchar_rule(server, "x5", (unsigned char)(pkt[5] &~(4+16)));
add_uchar_rule(server, "x6", (unsigned char)(pkt[6] &~1));
if (get_player_info && server->num_players)
{
server->next_player_info = 0;
send_player_request_packet(server);
return INPROGRESS;
}
}
/* MP_PLAYERLIST_DATA */
else if (rawpkt[1] == 0x73)
{
struct player *player;
struct player **last_player = &server->players;
if (server->players != NULL)
{
return PKT_ERROR;
}
pkt = &rawpkt[0x4];
while (*pkt)
{
player = (struct player*)calloc(1, sizeof(struct player));
player->name = strdup(pkt);
pkt += strlen(pkt) + 1;
*last_player = player;
last_player = &player->next;
}
server->next_player_info = NO_PLAYER_INFO;
}
else
{
fprintf(stderr, "unknown d3 packet\n");
print_packet(server, rawpkt, pktlen);
}
return DONE_FORCE;
}

View file

@ -1,2 +0,0 @@
I was under the impression farcry uses ASE.
If anyone ever has issues, this is the doc for some old farcry query protocol.

View file

@ -1,261 +0,0 @@
LICENSE: The Artistic License 2.0
/*
* qstat.h
* by Steve Jankowski
* steve@qstat.org
* http://www.qstat.org
*
* Copyright 1996,1997,1998,1999,2000,2001,2002 by Steve Jankowski
*/
unsigned char farcry_serverquery[] = {
0x08,0x80
};
{
/* FARCRY PROTOCOL */
FARCRY_SERVER, /* id */
"FCS", /* type_prefix */
"fcs", /* type_string */
"-fcs", /* type_option */
"FarCry", /* game_name */
0, /* master */
FARCRY_DEFAULT_PORT, /* default_port */
0, /* port_offset */
TF_QUERY_ARG, /* flags */
"gametype", /* game_rule */
"FARCRY", /* template_var */
(char*)farcry_serverquery, /* status_packet */
sizeof( savage_serverquery ) - 1, /* status_len */
NULL, /* player_packet */
0, /* player_len */
NULL, /* rule_packet */
0, /* rule_len */
NULL, /* master_packet */
0, /* master_len */
NULL, /* master_protocol */
NULL, /* master_query */
display_farcry_player_info, /* display_player_func */
display_server_rules, /* display_rule_func */
raw_display_farcry_player_info, /* display_raw_player_func */
raw_display_server_rules, /* display_raw_rule_func */
xml_display_farcry_player_info, /* display_xml_player_func */
xml_display_server_rules, /* display_xml_rule_func */
send_farcry_request_packet, /* status_query_func */
NULL, /* rule_query_func */
NULL, /* player_query_func */
deal_with_farcry_packet, /* packet_func */
},
query_status_t send_farcry_request_packet(struct qserver *server)
{
int len;
char *pkt;
if (get_player_info)
{
pkt = server->type->player_packet;
len = server->type->player_len;
}
else
{
pkt = server->type->status_packet;
len = server->type->status_len;
}
return send_packet(server, pkt, len);
}
query_status_t deal_with_farcry_packet(struct qserver *server, char *rawpkt, int pktlen)
{
char *s, *key, *value, *end;
debug( 2, "deal_with_farcry_packet %p, %d", server, pktlen );
server->n_servers++;
if (NULL == server->server_name)
{
server->ping_total += time_delta(&packet_recv_time, &server->packet_time1);
}
else
{
gettimeofday(&server->packet_time1, NULL);
}
rawpkt[pktlen] = '\0';
end = s = rawpkt;
end += pktlen;
while (*s)
{
// Find the seperator
while (s <= end && *s != '\xFF')
{
s++;
}
if (s >= end)
{
// Hit the end no more
break;
}
// key start
key = ++s;
while (s < end && *s != '\xFE')
{
s++;
}
if (*s != '\xFE')
{
// malformed
break;
}
*s++ = '\0';
// key end
// value start
value = s;
while (s < end && *s != '\xFF')
{
s++;
}
if (*s == '\xFF')
{
*s = '\0';
}
//fprintf( stderr, "'%s' = '%s'\n", key, value );
// Decode current key par
if (0 == strcmp("cmax", key))
{
// Max players
server->max_players = atoi(value);
}
else if (0 == strcmp("cnum", key))
{
// Current players
server->num_players = atoi(value);
}
else if (0 == strcmp("bal", key))
{
// Balance
add_rule(server, "Balance", value, NO_FLAGS);
}
else if (0 == strcmp("world", key))
{
// Current map
server->map_name = strdup(value);
}
else if (0 == strcmp("gametype", key))
{
// Game type
server->game = find_savage_game(value);
add_rule(server, server->type->game_rule, server->game, NO_FLAGS);
}
else if (0 == strcmp("pure", key))
{
// Pure
add_rule(server, "Pure", value, NO_FLAGS);
}
else if (0 == strcmp("time", key))
{
// Current game time
add_rule(server, "Time", value, NO_FLAGS);
}
else if (0 == strcmp("notes", key))
{
// Notes
add_rule(server, "Notes", value, NO_FLAGS);
}
else if (0 == strcmp("needcmdr", key))
{
// Need Commander
add_rule(server, "Need Commander", value, NO_FLAGS);
}
else if (0 == strcmp("name", key))
{
// Server name
server->server_name = strdup(value);
}
else if (0 == strcmp("fw", key))
{
// Firewalled
add_rule(server, "Firewalled", value, NO_FLAGS);
}
else if (0 == strcmp("players", key))
{
// Players names
int player_number = 0;
int team_number = 1;
char *team_name, *player_name, *n;
n = team_name = value;
// team name
n++;
while (*n && *n != '\x0a')
{
n++;
}
if (*n != '\x0a')
{
// Broken data
break;
}
*n = '\0';
player_name = ++n;
while (*n)
{
while (*n && *n != '\x0a')
{
n++;
}
if (*n != '\x0a')
{
// Broken data
break;
}
*n = '\0';
n++;
if (0 == strncmp("Team ", player_name, 5))
{
team_name = player_name;
team_number++;
}
else
{
if (0 != strlen(player_name))
{
struct player *player = add_player(server, player_number);
if (NULL != player)
{
player->name = strdup(player_name);
player->team = team_number;
player->team_name = strdup(team_name);
} player_number++;
}
}
player_name = n;
}
}
*s = '\xFF';
}
return DONE_FORCE;
}

View file

@ -1,57 +0,0 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* $Id: freelancer.php,v 1.2 2008/02/22 13:33:40 tombuskens Exp $
*/
[freelancer]
status = "\x00\x02\xf1\x26\x01\x26\xf0\x90\xa6\xf0\x26\x57\x4e\xac\xa0\xec\xf8\x68\xe4\x8d\x21"
require_once GAMEQ_BASE . 'Protocol.php';
/**
* Freelancer protocol
* UNTESTED
*
* @author Tom Buskens <t.buskens@deviation.nl>
* @version $Revision: 1.2 $
*/
class GameQ_Protocol_freelancer extends GameQ_Protocol
{
/*
* status packet
*/
public function status()
{
// Server name length @ 3
$this->p->skip(3);
$name_length = $this->p->readInt8() - 90;
// Max players @ 20
$this->p->skip(17);
$this->r->add('max_players', $this->p->readInt8() - 1);
// Num players @ 24
$this->p->skip(3);
$this->r->add('num_players', $this->p->readInt8() - 1);
// Servername @ 91
$this->p->skip(66);
$this->r->add('servername', $this->p->read($name_length));
}
}
?>

View file

@ -1,58 +0,0 @@
/*----------------------------------------------------------------------------------------------------------\
| |
| [ LIVE GAME SERVER LIST ] [ © RICHARD PERRY FROM GREYCUBE.COM ] |
| |
| Released under the terms and conditions of the GNU General Public License Version 3 (http://gnu.org) |
| |
\-----------------------------------------------------------------------------------------------------------*/
//------------------------------------------------------------------------------------------------------------+
//------------------------------------------------------------------------------------------------------------+
function lgsl_query_14(&$server, &$lgsl_need, &$lgsl_fp)
{
//---------------------------------------------------------+
// REFERENCE: http://flstat.cryosphere.co.uk/global-list.php
fwrite($lgsl_fp, "\x00\x02\xf1\x26\x01\x26\xf0\x90\xa6\xf0\x26\x57\x4e\xac\xa0\xec\xf8\x68\xe4\x8d\x21");
$buffer = fread($lgsl_fp, 4096);
if (!$buffer) { return FALSE; }
//---------------------------------------------------------+
$buffer = substr($buffer, 4); // HEADER ( 00 03 F1 26 )
$buffer = substr($buffer, 4); // NOT USED ( 87 + NAME LENGTH )
$buffer = substr($buffer, 4); // NOT USED ( NAME END TO BUFFER END LENGTH )
$buffer = substr($buffer, 4); // UNKNOWN ( 80 )
$server['s']['map'] = "freelancer";
$server['s']['password'] = lgsl_unpack(lgsl_cut_byte($buffer, 4), "l") - 1 ? 1 : 0;
$server['s']['playersmax'] = lgsl_unpack(lgsl_cut_byte($buffer, 4), "l") - 1;
$server['s']['players'] = lgsl_unpack(lgsl_cut_byte($buffer, 4), "l") - 1;
$buffer = substr($buffer, 4); // UNKNOWN ( 88 )
$name_length = lgsl_unpack(lgsl_cut_byte($buffer, 4), "l");
$buffer = substr($buffer, 56); // UNKNOWN
$server['s']['name'] = lgsl_cut_byte($buffer, $name_length);
lgsl_cut_string($buffer, 0, ":");
lgsl_cut_string($buffer, 0, ":");
lgsl_cut_string($buffer, 0, ":");
lgsl_cut_string($buffer, 0, ":");
lgsl_cut_string($buffer, 0, ":");
// WHATS LEFT IS THE MOTD
$server['e']['motd'] = substr($buffer, 0, -1);
// REMOVE UTF-8 ENCODING NULLS
$server['s']['name'] = str_replace("\x00", "", $server['s']['name']);
$server['e']['motd'] = str_replace("\x00", "", $server['e']['motd']);
// DOES NOT RETURN PLAYER INFORMATION
//---------------------------------------------------------+
return TRUE;
}

View file

@ -1,64 +0,0 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* $Id: ghostrecon.php,v 1.1 2007/07/02 10:14:32 tombuskens Exp $
*/
[ghostrecon]
status = "\xc0\xde\xf1\x11\x42\x06\x00\xf5\x03\x00\x78\x30\x63"
require_once GAMEQ_BASE . 'Protocol.php';
/**
* Ghost Recon protocol
*
* @author Tom Buskens <t.buskens@deviation.nl>
* @version $Revision: 1.1 $
*/
class GameQ_Protocol_ghostrecon extends GameQ_Protocol
{
/*
* Status
*/
public function status()
{
// Unknown
$this->p->skip(25);
$this->r->add('servername', $this->readGhostString());
$this->r->add('map', $this->readGhostString());
$this->r->add('mission', $this->readGhostString());
$this->r->add('gametype', $this->readGhostString());
}
/**
* Read a Ghost Recon string
*
* @return string The string
*/
private function readGhostString()
{
if ($this->p->getLength() < 4) return '';
$this->p->skip(4);
return $this->p->readString();
}
}
?>

View file

@ -1,133 +0,0 @@
/*----------------------------------------------------------------------------------------------------------\
| |
| [ LIVE GAME SERVER LIST ] [ © RICHARD PERRY FROM GREYCUBE.COM ] |
| |
| Released under the terms and conditions of the GNU General Public License Version 3 (http://gnu.org) |
| |
\-----------------------------------------------------------------------------------------------------------*/
function lgsl_query_19(&$server, &$lgsl_need, &$lgsl_fp)
{
//---------------------------------------------------------+
fwrite($lgsl_fp, "\xC0\xDE\xF1\x11\x42\x06\x00\xF5\x03\x21\x21\x21\x21");
$buffer = fread($lgsl_fp, 4096);
if (!$buffer) { return FALSE; }
//---------------------------------------------------------+
$buffer = substr($buffer, 25); // REMOVE HEADER
$server['s']['name'] = lgsl_get_string(lgsl_cut_pascal($buffer, 4, 3, -3));
$server['s']['map'] = lgsl_get_string(lgsl_cut_pascal($buffer, 4, 3, -3));
$server['e']['nextmap'] = lgsl_get_string(lgsl_cut_pascal($buffer, 4, 3, -3));
$server['e']['gametype'] = lgsl_get_string(lgsl_cut_pascal($buffer, 4, 3, -3));
$buffer = substr($buffer, 1);
$server['s']['password'] = ord(lgsl_cut_byte($buffer, 1));
$server['s']['playersmax'] = ord(lgsl_cut_byte($buffer, 4));
$server['s']['players'] = ord(lgsl_cut_byte($buffer, 4));
//---------------------------------------------------------+
for ($player_key=0; $player_key<$server['s']['players']; $player_key++)
{
$server['p'][$player_key]['name'] = lgsl_get_string(lgsl_cut_pascal($buffer, 4, 3, -3));
}
//---------------------------------------------------------+
$buffer = substr($buffer, 17);
$server['e']['version'] = lgsl_get_string(lgsl_cut_pascal($buffer, 4, 3, -3));
$server['e']['mods'] = lgsl_get_string(lgsl_cut_pascal($buffer, 4, 3, -3));
$server['e']['dedicated'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['time'] = lgsl_time(lgsl_unpack(lgsl_cut_byte($buffer, 4), "f"));
$server['e']['status'] = ord(lgsl_cut_byte($buffer, 4));
$server['e']['gamemode'] = ord(lgsl_cut_byte($buffer, 4));
$server['e']['motd'] = lgsl_get_string(lgsl_cut_pascal($buffer, 4, 3, -3));
$server['e']['respawns'] = ord(lgsl_cut_byte($buffer, 4));
$server['e']['time_limit'] = lgsl_time(lgsl_unpack(lgsl_cut_byte($buffer, 4), "f"));
$server['e']['voting'] = ord(lgsl_cut_byte($buffer, 4));
$buffer = substr($buffer, 2);
//---------------------------------------------------------+
for ($player_key=0; $player_key<$server['s']['players']; $player_key++)
{
$server['p'][$player_key]['team'] = ord(lgsl_cut_byte($buffer, 4));
$unknown = ord(lgsl_cut_byte($buffer, 1));
}
//---------------------------------------------------------+
$buffer = substr($buffer, 7);
$server['e']['platoon_1_color'] = ord(lgsl_cut_byte($buffer, 8));
$server['e']['platoon_2_color'] = ord(lgsl_cut_byte($buffer, 8));
$server['e']['platoon_3_color'] = ord(lgsl_cut_byte($buffer, 8));
$server['e']['platoon_4_color'] = ord(lgsl_cut_byte($buffer, 8));
$server['e']['timer_on'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['timer_time'] = lgsl_time(lgsl_unpack(lgsl_cut_byte($buffer, 4), "f"));
$server['e']['time_debriefing'] = lgsl_time(lgsl_unpack(lgsl_cut_byte($buffer, 4), "f"));
$server['e']['time_respawn_min'] = lgsl_time(lgsl_unpack(lgsl_cut_byte($buffer, 4), "f"));
$server['e']['time_respawn_max'] = lgsl_time(lgsl_unpack(lgsl_cut_byte($buffer, 4), "f"));
$server['e']['time_respawn_safe'] = lgsl_time(lgsl_unpack(lgsl_cut_byte($buffer, 4), "f"));
$server['e']['difficulty'] = ord(lgsl_cut_byte($buffer, 4));
$server['e']['respawn_total'] = ord(lgsl_cut_byte($buffer, 4));
$server['e']['random_insertions'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['spectators'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['arcademode'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['ai_backup'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['random_teams'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['time_starting'] = lgsl_time(lgsl_unpack(lgsl_cut_byte($buffer, 4), "f"));
$server['e']['identify_friends'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['identify_threats'] = ord(lgsl_cut_byte($buffer, 1));
$buffer = substr($buffer, 5);
$server['e']['restrictions'] = lgsl_get_string(lgsl_cut_pascal($buffer, 4, 3, -3));
//---------------------------------------------------------+
switch ($server['e']['status'])
{
case 3: $server['e']['status'] = "Joining"; break;
case 4: $server['e']['status'] = "Joining"; break;
case 5: $server['e']['status'] = "Joining"; break;
}
switch ($server['e']['gamemode'])
{
case 2: $server['e']['gamemode'] = "Co-Op"; break;
case 3: $server['e']['gamemode'] = "Solo"; break;
case 4: $server['e']['gamemode'] = "Team"; break;
}
switch ($server['e']['respawns'])
{
case 0: $server['e']['respawns'] = "None"; break;
case 1: $server['e']['respawns'] = "Individual"; break;
case 2: $server['e']['respawns'] = "Team"; break;
case 3: $server['e']['respawns'] = "Infinite"; break;
}
switch ($server['e']['difficulty'])
{
case 0: $server['e']['difficulty'] = "Recruit"; break;
case 1: $server['e']['difficulty'] = "Veteran"; break;
case 2: $server['e']['difficulty'] = "Elite"; break;
}
//---------------------------------------------------------+
return TRUE;
}

View file

@ -1,694 +0,0 @@
LICENSE: The Artistic License 2.0
/*
* qstat.h
* by Steve Jankowski
* steve@qstat.org
* http://www.qstat.org
*
* Copyright 1996,1997,1998,1999,2000,2001,2002 by Steve Jankowski
*/
unsigned char ghostrecon_serverquery[] = {
0xc0,0xde,0xf1,0x11, /* const ? header */
0x42, /* start flag */
0x03,0x00, /* data len */
0xe9,0x03,0x00 /* server request ?? */
};
unsigned char ghostrecon_playerquery[] = {
0xc0,0xde,0xf1,0x11, /* const ? header */
0x42, /* start flag */
0x06,0x00, /* data len */
0xf5,0x03,0x00,0x78,0x30,0x63 /* player request ?? may be flag 0xf5; len 0x03,0x00; data 0x78, 0x30, 0x63 */
};
{
/* GHOSTRECON PROTOCOL */
GHOSTRECON_SERVER, /* id */
"GRS", /* type_prefix */
"grs", /* type_string */
"-grs", /* type_option */
"Ghost Recon", /* game_name */
0, /* master */
GHOSTRECON_PLAYER_DEFAULT_PORT, /* default_port */
2, /* port_offset */
TF_QUERY_ARG, /* flags */
"gametype", /* game_rule */
"GHOSTRECON", /* template_var */
(char*) &ghostrecon_playerquery, /* status_packet */
sizeof( ghostrecon_playerquery), /* status_len */
NULL, /* player_packet */
0, /* player_len */
NULL, /* rule_packet */
0, /* rule_len */
NULL, /* master_packet */
0, /* master_len */
NULL, /* master_protocol */
NULL, /* master_query */
display_ghostrecon_player_info, /* display_player_func */
display_server_rules, /* display_rule_func */
raw_display_ghostrecon_player_info, /* display_raw_player_func */
raw_display_server_rules, /* display_raw_rule_func */
xml_display_ghostrecon_player_info, /* display_xml_player_func */
xml_display_server_rules, /* display_xml_rule_func */
send_qserver_request_packet, /* status_query_func */
NULL, /* rule_query_func */
NULL, /* player_query_func */
deal_with_ghostrecon_packet, /* packet_func */
},
static const char GrPacketHead[] =
{
'\xc0', '\xde', '\xf1', '\x11'
};
static const char PacketStart = '\x42';
static char Dat2Reply1_2_10[] =
{
'\xf4', '\x03', '\x14', '\x02', '\x0a', '\x41', '\x02', '\x0a', '\x41', '\x00', '\x00', '\x78', '\x30', '\x63'
};
static char Dat2Reply1_3[] =
{
'\xf4', '\x03', '\x14', '\x03', '\x05', '\x41', '\x03', '\x05', '\x41', '\x00', '\x00', '\x78', '\x30', '\x63'
};
static char Dat2Reply1_4[] =
{
'\xf4', '\x03', '\x14', '\x04', '\x00', '\x41', '\x04', '\x00', '\x41', '\x00', '\x00', '\x78', '\x30', '\x63'
};
//static char HDat2[]={'\xea','\x03','\x02','\x00','\x14'};
#define SHORT_GR_LEN 75
#define LONG_GR_LEN 500
#define UNKNOWN_VERSION 0
#define VERSION_1_2_10 1
#define VERSION_1_3 2
#define VERSION_1_4 3
query_status_t deal_with_ghostrecon_packet(struct qserver *server, char *pkt, int pktlen)
{
char str[256], *start, *end, StartFlag, *lpszIgnoreServerPlayer;
char *lpszMission;
unsigned int iIgnoreServerPlayer, iDedicatedServer, iUseStartTimer;
unsigned short GrPayloadLen;
int i;
struct player *player;
int iLen, iTemp;
short sLen;
int iSecsPlayed;
long iSpawnType;
int ServerVersion = UNKNOWN_VERSION;
float flStartTimerSetPoint;
debug( 2, "deal_with_ghostrecon_packet %p, %d", server, pktlen );
start = pkt;
end = &pkt[pktlen];
pkt[pktlen] = '\0';
/*
This function walks a packet that is recieved from a ghost recon server - default from port 2348. It does quite a few
sanity checks along the way as the structure is not documented. The packet is mostly binary in nature with many string
fields being variable in length, ie the length is listed foloowed by that many bytes. There are two structure arrays
that have an array size followed by structure size * number of elements (player name and player data). This routine
walks this packet and increments a pointer "pkt" to extract the info.
*/
if (server->server_name == NULL)
{
server->ping_total += time_delta(&packet_recv_time, &server->packet_time1);
}
/* sanity check against packet */
if (memcmp(pkt, GrPacketHead, sizeof(GrPacketHead)) != 0)
{
server->server_name = strdup("Unknown Packet Header");
return PKT_ERROR;
}
pkt += sizeof(GrPacketHead);
StartFlag = pkt[0];
pkt += 1;
if (StartFlag != 0x42)
{
server->server_name = strdup("Unknown Start Flag");
return PKT_ERROR;
}
/* compare packet length recieved to included size - header info */
sLen = swap_short_from_little(pkt);
pkt += 2;
GrPayloadLen = pktlen - sizeof(GrPacketHead) - 3;
// 3 = size slen + size start flag
if (sLen != GrPayloadLen)
{
server->server_name = strdup("Packet Size Mismatch");
return PKT_ERROR;
}
/*
Will likely need to verify and add to this "if" construct with every patch / add-on.
*/
if (memcmp(pkt, Dat2Reply1_2_10, sizeof(Dat2Reply1_2_10)) == 0)
{
ServerVersion = VERSION_1_2_10;
}
else if (memcmp(pkt, Dat2Reply1_3, sizeof(Dat2Reply1_3)) == 0)
{
ServerVersion = VERSION_1_3;
}
else if (memcmp(pkt, Dat2Reply1_4, sizeof(Dat2Reply1_4)) == 0)
{
ServerVersion = VERSION_1_4;
}
if (ServerVersion == UNKNOWN_VERSION)
{
server->server_name = strdup("Unknown GR Version");
return PKT_ERROR;
}
switch (ServerVersion)
{
case VERSION_1_2_10:
strcpy(str, "1.2.10");
pkt += sizeof(Dat2Reply1_2_10);
break;
case VERSION_1_3:
strcpy(str, "1.3");
pkt += sizeof(Dat2Reply1_3);
break;
case VERSION_1_4:
strcpy(str, "1.4");
pkt += sizeof(Dat2Reply1_4);
break;
}
add_rule(server, "patch", str, NO_FLAGS);
/* have player packet */
// Ghost recon has one of the player slots filled up with the server program itself. By default we will
// drop the first player listed. This causes a bit of a mess here and below but makes for the best display
// a user can specify -grs,ignoreserverplayer=no to override this behaviour.
lpszIgnoreServerPlayer = get_param_value(server, "ignoreserverplayer", "yes");
for (i = 0; i < 4; i++)
{
str[i] = tolower(lpszIgnoreServerPlayer[i]);
}
if (strcmp(str, "yes") == 0)
{
iIgnoreServerPlayer = 1;
}
else
{
iIgnoreServerPlayer = 0;
}
pkt += 4; /* unknown */
// this is the first of many variable strings. get the length,
// increment pointer over length, check for sanity,
// get the string, increment the pointer over string (using length)
iLen = swap_long_from_little(pkt);
pkt += 4;
if ((iLen < 1) || (iLen > SHORT_GR_LEN))
{
server->server_name = strdup("Server Name too Long");
return PKT_ERROR;
}
server->server_name = strndup(pkt, iLen);
pkt += iLen;
iLen = swap_long_from_little(pkt);
pkt += 4;
if ((iLen < 1) || (iLen > SHORT_GR_LEN))
{
add_rule(server, "error", "Map Name too Long", NO_FLAGS);
return PKT_ERROR;
}
server->map_name = strndup(pkt, iLen);
pkt += iLen;
iLen = swap_long_from_little(pkt);
pkt += 4;
if ((iLen < 1) || (iLen > SHORT_GR_LEN))
{
add_rule(server, "error", "Mission Name too Long", NO_FLAGS);
return PKT_ERROR;
}
/* mission does not make sense unless a coop game type. Since
we dont know that now, we will save the mission and set
the rule and free memory below when we know game type */
lpszMission = strndup(pkt, iLen);
pkt += iLen;
iLen = swap_long_from_little(pkt);
pkt += 4;
if ((iLen < 1) || (iLen > SHORT_GR_LEN))
{
add_rule(server, "error", "Mission Type too Long", NO_FLAGS);
return PKT_ERROR;
}
add_nrule(server, "missiontype", pkt, iLen);
pkt += iLen;
if (pkt[1])
{
add_rule(server, "password", "Yes", NO_FLAGS);
}
else
{
add_rule(server, "password", "No", NO_FLAGS);
}
pkt += 2;
server->max_players = swap_long_from_little(pkt);
pkt += 4;
if (server->max_players > 36)
{
add_rule(server, "error", "Max players more then 36", NO_FLAGS);
return PKT_ERROR;
}
server->num_players = swap_long_from_little(pkt);
pkt += 4;
if (server->num_players > server->max_players)
{
add_rule(server, "error", "More then MAX Players", NO_FLAGS);
return PKT_ERROR;
}
if (iIgnoreServerPlayer)
// skip past first player
{
server->num_players--;
server->max_players--;
iLen = swap_long_from_little(pkt);
pkt += 4;
pkt += iLen;
}
for (i = 0; i < server->num_players; i++)
// read each player name
{
iLen = swap_long_from_little(pkt);
pkt += 4;
player = (struct player*)calloc(1, sizeof(struct player));
if ((iLen < 1) || (iLen > SHORT_GR_LEN))
{
add_rule(server, "error", "Player Name too Long", NO_FLAGS);
return PKT_ERROR;
}
player->name = strndup(pkt, iLen);
pkt += iLen; /* player name */
player->team = i; // tag so we can find this record when we have player dat.
player->team_name = "Unassigned";
player->flags |= PLAYER_FLAG_DO_NOT_FREE_TEAM;
player->frags = 0;
player->next = server->players;
server->players = player;
}
pkt += 17;
iLen = swap_long_from_little(pkt);
pkt += 4;
if ((iLen < 1) || (iLen > SHORT_GR_LEN))
{
add_rule(server, "error", "Version too Long", NO_FLAGS);
return PKT_ERROR;
}
strncpy(str, pkt, iLen);
add_rule(server, "version", str, NO_FLAGS);
pkt += iLen; /* version */
iLen = swap_long_from_little(pkt);
pkt += 4;
if ((iLen < 1) || (iLen > LONG_GR_LEN))
{
add_rule(server, "error", "Mods too Long", NO_FLAGS);
return PKT_ERROR;
}
server->game = strndup(pkt, iLen);
for (i = 0; i < (int)strlen(server->game) - 5; i++)
// clean the "/mods/" part from every entry
{
if (memcmp(&server->game[i], "\\mods\\", 6) == 0)
{
server->game[i] = ' ';
strcpy(&server->game[i + 1], &server->game[i + 6]);
}
}
add_rule(server, "game", server->game, NO_FLAGS);
pkt += iLen; /* mods */
iDedicatedServer = pkt[0];
if (iDedicatedServer)
{
add_rule(server, "dedicated", "Yes", NO_FLAGS);
}
else
{
add_rule(server, "dedicated", "No", NO_FLAGS);
}
pkt += 1; /* unknown */
iSecsPlayed = swap_float_from_little(pkt);
add_rule(server, "timeplayed", play_time(iSecsPlayed, 2), NO_FLAGS);
pkt += 4; /* time played */
switch (pkt[0])
{
case 3:
strcpy(str, "Joining");
break;
case 4:
strcpy(str, "Playing");
break;
case 5:
strcpy(str, "Debrief");
break;
default:
strcpy(str, "Undefined");
}
add_rule(server, "status", str, NO_FLAGS);
pkt += 1;
pkt += 3; /* unknown */
switch (pkt[0])
{
case 2:
strcpy(str, "COOP");
break;
case 3:
strcpy(str, "SOLO");
break;
case 4:
strcpy(str, "TEAM");
break;
default:
sprintf(str, "UNKOWN %u", pkt[0]);
break;
}
add_rule(server, "gamemode", str, NO_FLAGS);
if (pkt[0] == 2)
{
add_rule(server, "mission", lpszMission, NO_FLAGS);
}
else
{
add_rule(server, "mission", "No Mission", NO_FLAGS);
}
free(lpszMission);
pkt += 1; /* Game Mode */
pkt += 3; /* unknown */
iLen = swap_long_from_little(pkt);
pkt += 4;
if ((iLen < 1) || (iLen > LONG_GR_LEN))
{
add_rule(server, "error", "MOTD too Long", NO_FLAGS);
return PKT_ERROR;
}
strncpy(str, pkt, sizeof(str));
str[sizeof(str) - 1] = 0;
add_rule(server, "motd", str, NO_FLAGS);
pkt += iLen; /* MOTD */
iSpawnType = swap_long_from_little(pkt);
switch (iSpawnType)
{
case 0:
strcpy(str, "None");
break;
case 1:
strcpy(str, "Individual");
break;
case 2:
strcpy(str, "Team");
break;
case 3:
strcpy(str, "Infinite");
break;
default:
strcpy(str, "Unknown");
}
add_rule(server, "spawntype", str, NO_FLAGS);
pkt += 4; /* spawn type */
iTemp = swap_float_from_little(pkt);
add_rule(server, "gametime", play_time(iTemp, 2), NO_FLAGS);
iTemp = iTemp - iSecsPlayed;
if (iTemp <= 0)
{
iTemp = 0;
}
add_rule(server, "remainingtime", play_time(iTemp, 2), NO_FLAGS);
pkt += 4; /* Game time */
iTemp = swap_long_from_little(pkt);
if (iIgnoreServerPlayer)
{
iTemp--;
}
if (iTemp != server->num_players)
{
add_rule(server, "error", "Number of Players Mismatch", NO_FLAGS);
}
pkt += 4; /* player count 2 */
if (iIgnoreServerPlayer)
{
pkt += 5; // skip first player data
}
for (i = 0; i < server->num_players; i++)
// for each player get binary data
{
player = server->players;
// first we must find the player - lets look for the tag
while (player && (player->team != i))
{
player = player->next;
}
/* get to player - linked list is in reverse order */
if (player)
{
player->team = pkt[2];
switch (player->team)
{
case 1:
player->team_name = "Red";
break;
case 2:
player->team_name = "Blue";
break;
case 3:
player->team_name = "Yellow";
break;
case 4:
player->team_name = "Green";
break;
case 5:
player->team_name = "Unassigned";
break;
default:
player->team_name = "Not Known";
break;
}
player->flags |= PLAYER_FLAG_DO_NOT_FREE_TEAM;
player->deaths = pkt[1];
}
pkt += 5; /* player data*/
}
for (i = 0; i < 5; i++)
{
pkt += 8; /* team data who knows what they have in here */
}
pkt += 1;
iUseStartTimer = pkt[0]; // UseStartTimer
pkt += 1;
iTemp = flStartTimerSetPoint = swap_float_from_little(pkt);
// Start Timer Set Point
pkt += 4;
if (iUseStartTimer)
{
add_rule(server, "usestarttime", "Yes", NO_FLAGS);
add_rule(server, "starttimeset", play_time(iTemp, 2), NO_FLAGS);
}
else
{
add_rule(server, "usestarttime", "No", NO_FLAGS);
add_rule(server, "starttimeset", play_time(0, 2), NO_FLAGS);
}
if ((ServerVersion == VERSION_1_3) || // stuff added in patch 1.3
(ServerVersion == VERSION_1_4))
{
iTemp = swap_float_from_little(pkt); // Debrief Time
add_rule(server, "debrieftime", play_time(iTemp, 2), NO_FLAGS);
pkt += 4;
iTemp = swap_float_from_little(pkt); // Respawn Min
add_rule(server, "respawnmin", play_time(iTemp, 2), NO_FLAGS);
pkt += 4;
iTemp = swap_float_from_little(pkt); // Respawn Max
add_rule(server, "respawnmax", play_time(iTemp, 2), NO_FLAGS);
pkt += 4;
iTemp = swap_float_from_little(pkt); // Respawn Invulnerable
add_rule(server, "respawnsafe", play_time(iTemp, 2), NO_FLAGS);
pkt += 4;
}
else
{
add_rule(server, "debrieftime", "Undefined", NO_FLAGS);
add_rule(server, "respawnmin", "Undefined", NO_FLAGS);
add_rule(server, "respawnmax", "Undefined", NO_FLAGS);
add_rule(server, "respawnsafe", "Undefined", NO_FLAGS);
}
pkt += 4; // 4
iTemp = pkt[0]; // Spawn Count
if ((iSpawnType == 1) || (iSpawnType == 2))
/* Individual or team */
{
sprintf(str, "%u", iTemp);
}
else
/* else not used */
{
sprintf(str, "%u", 0);
}
add_rule(server, "spawncount", str, NO_FLAGS);
pkt += 1; // 5
pkt += 4; // 9
iTemp = pkt[0]; // Allow Observers
if (iTemp)
{
strcpy(str, "Yes");
}
else
/* else not used */
{
strcpy(str, "No");
}
add_rule(server, "allowobservers", str, NO_FLAGS);
pkt += 1; // 10
pkt += 3; // 13
// pkt += 13;
if (iUseStartTimer)
{
iTemp = swap_float_from_little(pkt); // Start Timer Count
add_rule(server, "startwait", play_time(iTemp, 2), NO_FLAGS);
}
else
{
add_rule(server, "startwait", play_time(0, 2), NO_FLAGS);
}
pkt += 4; //17
iTemp = pkt[0]; // IFF
switch (iTemp)
{
case 0:
strcpy(str, "None");
break;
case 1:
strcpy(str, "Reticule");
break;
case 2:
strcpy(str, "Names");
break;
default:
strcpy(str, "Unknown");
break;
}
add_rule(server, "iff", str, NO_FLAGS);
pkt += 1; // 18
iTemp = pkt[0]; // Threat Indicator
if (iTemp)
{
add_rule(server, "ti", "ON ", NO_FLAGS);
}
else
{
add_rule(server, "ti", "OFF", NO_FLAGS);
}
pkt += 1; // 19
pkt += 5; // 24
iLen = swap_long_from_little(pkt);
pkt += 4;
if ((iLen < 1) || (iLen > SHORT_GR_LEN))
{
add_rule(server, "error", "Restrictions too Long", NO_FLAGS);
return PKT_ERROR;
}
add_rule(server, "restrict", pkt, NO_FLAGS);
pkt += iLen; /* restrictions */
pkt += 23;
/*
if ( ghostrecon_debug) print_packet( pkt, GrPayloadLen);
*/
return DONE_FORCE;
}

View file

@ -1,229 +0,0 @@
/*********
QStat - Real-time game server stats
http://sourceforge.net/p/qstat/
License: The Artistic License 2.0
*********/
Ghost Recon - QStat notes
-------------------------
The following Server Stats are pulled from the Ghost Recon Server - NOTE
many other stats continue to work as normal due to the base qstat program.
$SERVERNAME
The name of the GR Server.
$PLAYERS
The number of Players that are playing, oberving or in the Lobby
(note the ignoreserverplayer Argument above)
$MAXPLAYERS
The maximum players that the server will allow playing, oberving
or in the Lobby (note the ignoreserverplayer Argument above)
$MAP
The Name of the MAP that is being used (NOTE not the Mission)
$GAME
The Mods that the server is running. Ex: mp1; is the Desert
Seige Mod
$(RULE:error)
If an error occured there may be some detail here. IF the problm
occurred very early in the interpretation then $SERVERNAME will
hold the details.
$(RULE:mission)
The name of the Mission that the server is running.
$(RULE:gamemode)
What is the Game Mode that the server is in. Known values are
COOP, TEAM and SOLO
$(RULE:missiontype)
What is the Mission Type. Known Values are: Mission, Firefight,
Recon, Hamburger Hill, Last Man Standing, Sharpshooter, Search
And Rescue, Domination, and Seige.
$(RULE:dedicated)
Is this server Dedicated; Yes or No.
$(RULE:status)
What is the Playing Status of the Server, values are Playing,
Joining or Debrief.
$(RULE:gametime)
What is the Time limit for the Game. Values are 00:00, 05:00,
10:00, 15:00 20:00, 25:00, 30:00, 45:00 and 60:00. The 00:00
is for an unlimited game. The format of this uses the -ts,
-tc and -tsw command line options.
$(RULE:timeplayed)
How long has this game been playing. The format of this uses
the -ts, -tc and -tsw command line options.
$(RULE:remainingtime)
How much time is left in this game. The format of this uses
the -ts, -tc and -tsw command line options.
$(RULE:version)
What is the Version number reported by the server. Patch 1.2 =
10.1010A, Patch 1.3 = 11.101A
$(RULE:spawntype)
What type of spawn is in use. Known Values are None, Infinite,
Individual and Team.
$(RULE:spawncount)
How many spawns are allowed. Enhancment possibility to add
$(IF:SPAWN) to filter out when spawntype is none.
$(RULE:restrict)
What Weapon restrictions are in force for the server.
$(RULE:password)
Does the Server have a join password defined Yes or No.
$(RULE:ti)
Is the server using the Threat Indicator.
$(RULE:motd)
What is the Message Of The Day - Note these can be quite big.
$(RULE:patch)
What is the patch level of the GR Server.
$(RULE:usestarttime)
Is the server configured to start a game after "starttimeset"
(Yes) OR does everyone need to click on ready (no).
$(RULE:starttimeset)
What time is configured to automatically start the next round.
$(RULE:debrieftime)
How long does the server wait at the Debrief screen after
a mission.
$(RULE:respawnmin)
How long must a dead player wait before he can repawn.
$(RULE:respawnmax)
What is the longest time that a user has to respawn.
$(RULE:respawnsafe)
How long after respawn is a player invulnerable/cannot damage
others.
$(RULE:allowobservers)
Does the server allow observers? Yes or No
$(RULE:startwait)
How long untill the automatic start timer forces the next game
to start.
$(RULE:iff)
What Identification - Friend or Foe is configured. None,
Reticule or Names
$PLAYERNAME
What is the Players Name.
$TEAMNUM
What Team Number is the Player On. Known Values are 1,2,3,4,5.
1 is Team BLUE, 2 is Team Read, 3 is Team Yellow, 4 is
Team Green, 5 is Unassigned (observer or in lobby)
$TEAMNAME
What is the Name of the Team, see above.
$DEATHS
What is the health of this player. 0 Alive, 1 Dead. Note if the
player has spawns remaining this can change from 1 back to 0.
Enhancement possibility to add $HEALTH or $(RULE:health).
Hopefully RSE/UBI will add the Deaths, Frags, and Ping to the
availible information. If this happens then it would be better
to have a $HEALTH
$(IF:DEATHS) and $(IFNOT:DEATHS)
A Test to see if the player is dead. Usefull in this constuct:
$(IF:DEATHS)Dead$(ENDIF)$(IFNOT:DEATHS)Alive$(ENDIF)
Ghost Recon communicates on two UDP ports and one TCP stream. Normally TCP
is on port 2346 and carries the game dialog. This is the port number
that is mentioned in the game so we use it and apply an offset to get the
port number for status queries. Port 2347 gives some high level server stats
and 2348 gives fairly low level server stats. QStat is designed around
a single port per server so the 2348 port is used. One down side to this
is the lack of many meaningful detail player stats (Deaths, frags, hit
percentage, ping etc.). I imagines that some of these are availible in
the TCP stream but that would be difficult to add to a program like QStat.
The Ghost Recon packets are variable structures with a lot of string
lengths. This requires fairly defensive programming as Red Storm
Entertainment is not forthcoming with any details.
This release adds support for the GhostRecon game. Number one note
is that Red Storm and UBI do not provide the information that many
Quake based users expect. Specifically they do not make Frags, Deaths
Connect Time or Pings availible - at least not as far as I can tell.
That said there are quite a few things that are availible and allow a
server administrator to make the status of his or her server available
to the public via the web.
This change uses all undocumented interfaces to the Ghost Recon server
so will most likely break when you install a patch. It has been tested
against the Desert Seige update and several public servers. It should
work against the 1.2, 1.3, and 1.4 patches and Island Thunder add-on to
Ghost Recon.
The Ghost Recon game type is GRS. For command-line queries, use -grs
There is one query argument to this server, ignoreserverplayer.
This option controls whether the first player is ignored. Ghost Recon
requires that the dedicated server program take up one of the player slots
(always the first slot). The ignoreserverplayer option defaults to 'yes',
so the "server player" will normally not be seen. If you are running
a non-dedicated server, then set ignoreserverplayer to 'no' like this:
-grs,ignoreserverplayer=no
Otherwise you would not be able to display your own stats.
Ghost Recon support provided by Bob Marriott.

View file

@ -1,40 +0,0 @@
/*----------------------------------------------------------------------------------------------------------\
| |
| [ LIVE GAME SERVER LIST ] [ © RICHARD PERRY FROM GREYCUBE.COM ] |
| |
| Released under the terms and conditions of the GNU General Public License Version 3 (http://gnu.org) |
| |
\-----------------------------------------------------------------------------------------------------------*/
function lgsl_query_15(&$server, &$lgsl_need, &$lgsl_fp)
{
//---------------------------------------------------------+
fwrite($lgsl_fp, "GTR2_Direct_IP_Search\x00");
$buffer = fread($lgsl_fp, 4096);
if (!$buffer) { return FALSE; }
//---------------------------------------------------------+
$buffer = str_replace("\xFE", "\xFF", $buffer);
$buffer = explode("\xFF", $buffer);
$server['s']['name'] = $buffer[3];
$server['s']['game'] = $buffer[7];
$server['e']['version'] = $buffer[11];
$server['e']['hostport'] = $buffer[15];
$server['s']['map'] = $buffer[19];
$server['s']['players'] = $buffer[25];
$server['s']['playersmax'] = $buffer[27];
$server['e']['gamemode'] = $buffer[31];
// DOES NOT RETURN PLAYER INFORMATION
//---------------------------------------------------------+
return TRUE;
}

View file

@ -1,716 +0,0 @@
LICENSE: The Artistic License 2.0
/*
* qstat.h
* by Steve Jankowski
* steve@qstat.org
* http://www.qstat.org
*
* Copyright 1996,1997,1998,1999,2000,2001,2002 by Steve Jankowski
*/
#define HAZE_BASIC_INFO 0x01
#define HAZE_GAME_RULES 0x02
#define HAZE_PLAYER_INFO 0x04
#define HAZE_TEAM_INFO 0x08
// Format:
// 1 - 8: Query Request
// 9 - 12: Query Header
// 13: Query ID
// Query ID is made up of the following
// 0x01: Basic Info
// 0x02: Game Rules
// 0x03: Player Information
// 0x04: Team Information
unsigned char haze_status_query[] = {
'f', 'r', 'd', 'q', 'u', 'e', 'r', 'y',
0x10,0x20,0x30,0x40,
0x0A
};
// Format:
// 1 - 8: Query Request
// 9 - 12: Query Header
// 13: Query ID
// Query ID is made up of the following
// 0x01: Basic Info
// 0x02: Game Rules
// 0x03: Player Information
// 0x04: Team Information
unsigned char haze_player_query[] = {
'f', 'r', 'd', 'q', 'u', 'e', 'r', 'y',
0x10,0x20,0x30,0x40,
0x03
};
{
/* HAZE PROTOCOL */
HAZE_SERVER, /* id */
"HAZES", /* type_prefix */
"hazes", /* type_string */
"-hazes", /* type_option */
"Haze Protocol", /* game_name */
0, /* master */
0, /* default_port */
0, /* port_offset */
TF_SINGLE_QUERY, /* flags */
"gametype", /* game_rule */
"HAZE", /* template_var */
(char*) &haze_status_query, /* status_packet */
sizeof( haze_status_query), /* status_len */
(char*) &haze_player_query, /* player_packet */
sizeof( haze_player_query), /* player_len */
NULL, /* rule_packet */
0, /* rule_len */
NULL, /* master_packet */
0, /* master_len */
NULL, /* master_protocol */
NULL, /* master_query */
display_gs2_player_info, /* display_player_func */
display_server_rules, /* display_rule_func */
raw_display_gs2_player_info, /* display_raw_player_func */
raw_display_server_rules, /* display_raw_rule_func */
xml_display_player_info, /* display_xml_player_func */
xml_display_server_rules, /* display_xml_rule_func */
send_haze_request_packet, /* status_query_func */
NULL, /* rule_query_func */
NULL, /* player_query_func */
deal_with_haze_packet, /* packet_func */
},
/*
* qstat 2.8
* by Steve Jankowski
*
* New Haze query protocol
* Copyright 2005 Steven Hartland
*
* Licensed under the Artistic License, see LICENSE.txt for license terms
*
*/
#include <sys/types.h>
#ifndef _WIN32
#include <netinet/in.h>
#include <sys/socket.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include "debug.h"
#include "qstat.h"
#include "packet_manip.h"
// Format:
// 1 - 8: Challenge Request / Response
char haze_challenge[] = {
'f', 'r', 'd', 'c', '_', '_', '_', '_'
};
int process_haze_packet( struct qserver *server );
// Player headers
#define PLAYER_NAME_HEADER 1
#define PLAYER_SCORE_HEADER 2
#define PLAYER_DEATHS_HEADER 3
#define PLAYER_PING_HEADER 4
#define PLAYER_KILLS_HEADER 5
#define PLAYER_TEAM_HEADER 6
#define PLAYER_OTHER_HEADER 7
// Team headers
#define TEAM_NAME_HEADER 1
#define TEAM_OTHER_HEADER 2
// Challenge response algorithum
// Before sending a qr2 query (type 0x00) the client must first send a
// challenge request (type 0x09). The host will respond with the same
// packet type containing a string signed integer.
//
// Once the challenge is received the client should convert the string to a
// network byte order integer and embed it in the keys query.
//
// Example:
//
// challenge request: [0xFE][0xFD][0x09][0x.. 4-byte-instance]
// challenge response: [0x09][0x.. 4-byte-instance]["-1287574694"]
// query: [0xFE][0xFD][0x00][0x.. 4-byte-instance][0xb3412b5a "-1287574694"]
//
query_status_t deal_with_haze_packet( struct qserver *server, char *rawpkt, int pktlen )
{
char *ptr = rawpkt;
unsigned int pkt_id;
unsigned short len;
unsigned char pkt_max, pkt_index;
debug( 2, "packet..." );
if ( pktlen < 8 )
{
// invalid packet
malformed_packet( server, "too short" );
return PKT_ERROR;
}
if ( 0 == strncmp( ptr, "frdcr", 5 ) )
{
// challenge response
ptr += 8;
server->challenge = 1;
// Correct the stats due to two phase protocol
server->retry1++;
server->n_packets--;
if ( server->retry1 == n_retries || server->flags & FLAG_BROADCAST )
{
//server->n_requests--;
}
else
{
server->n_retries--;
}
return send_haze_request_packet( server );
}
if ( pktlen < 12 )
{
// invalid packet
malformed_packet( server, "too short" );
return PKT_ERROR;
}
server->n_servers++;
if ( server->server_name == NULL )
{
server->ping_total += time_delta( &packet_recv_time, &server->packet_time1 );
}
else
{
gettimeofday( &server->packet_time1, NULL);
}
// Query version ID
ptr += 4;
// Could check the header here should
// match the 4 byte id sent
memcpy( &pkt_id, ptr, 4 );
ptr += 4;
// Max plackets
pkt_max = ((unsigned char)*ptr);
ptr++;
// Packet ID
pkt_index = ((unsigned char)*ptr);
ptr++;
// Query Length
//len = (unsigned short)ptr[0] | ((unsigned short)ptr[1] << 8);
//len = swap_short_from_little( ptr );
debug( 1, "%04hx, %04hx", (unsigned short)ptr[0], ((unsigned short)ptr[1] << 8) );
//len = (unsigned short)(unsigned short)ptr[0] | ((unsigned short)ptr[1] << 8);
// TODO: fix this crap
memcpy( &len, ptr+1, 1 );
//memcpy( &len+1, ptr, 1 );
//memcpy( &len, ptr, 2 );
ptr += 2;
debug( 1, "pkt_index = %d, pkt_max = %d, len = %d", pkt_index, pkt_max, len );
if ( 0 != pkt_max )
{
// not a single packet response or callback
debug( 2, "pkt_max %d", pkt_max );
if ( 0 == pkt_index )
{
// to prevent reprocessing when we get the call back
// override the packet flag so it looks like a single
// packet response
rawpkt[8] = '\0';
}
// add the packet recalcing maxes
if ( ! add_packet( server, pkt_id, pkt_index, pkt_max, pktlen, rawpkt, 1 ) )
{
// fatal error e.g. out of memory
return MEM_ERROR;
}
// combine_packets will call us recursively
return combine_packets( server );
}
// if we get here we have what should be a full packet
return process_haze_packet( server );
}
query_status_t deal_with_haze_status( struct qserver *server, char *rawpkt, int pktlen )
{
char *pkt = rawpkt;
int len;
debug( 1, "status packet" );
// Server name
server->server_name = strdup( pkt );
pkt += strlen( pkt ) + 1;
// gametype
add_rule( server, "gametype", pkt, NO_FLAGS );
pkt += strlen( pkt ) + 1;
// map
len = strlen( pkt );
// remove .res from map names
if ( 0 == strncmp( pkt + len - 4, ".res", 4 ) )
{
*(pkt + len - 4) = '\0';
}
server->map_name = strdup( pkt );
pkt += len + 1;
// num players
server->num_players = atoi( pkt );
pkt += strlen( pkt ) + 1;
// max_players
server->max_players = atoi( pkt );
pkt += strlen( pkt ) + 1;
// hostport
change_server_port( server, atoi( pkt ), 0 );
pkt += strlen( pkt ) + 1;
return DONE_FORCE;
}
int process_haze_packet( struct qserver *server )
{
unsigned char state = 0;
unsigned char no_players = 0;
unsigned char total_players = 0;
unsigned char no_teams = 0;
unsigned char total_teams = 0;
int pkt_index = 0;
SavedData *fragment;
debug( 2, "processing packet..." );
while ( NULL != ( fragment = get_packet_fragment( pkt_index++ ) ) )
{
int pktlen = fragment->datalen;
char *ptr = fragment->data;
char *end = ptr + pktlen;
debug( 2, "processing fragment[%d]...", fragment->pkt_index );
// check we have a full header
if ( pktlen < 12 )
{
// invalid packet
malformed_packet( server, "too short" );
return PKT_ERROR;
}
// skip over the header
//server->protocol_version = atoi( val+1 );
ptr += 12;
// 4 * null's signifies the end of a section
// Basic Info
while ( 0 == state && ptr < end )
{
// name value pairs null seperated
char *var, *val;
int var_len, val_len;
if ( ptr+4 <= end && 0x00 == ptr[0] && 0x00 == ptr[1] && 0x00 == ptr[2] && 0x00 == ptr[3] )
{
// end of rules
state++;
ptr += 4;
break;
}
var = ptr;
var_len = strlen( var );
ptr += var_len + 1;
if ( ptr + 1 > end )
{
malformed_packet( server, "no basic value" );
return PKT_ERROR;
}
val = ptr;
val_len = strlen( val );
ptr += val_len + 1;
debug( 2, "var:%s (%d)=%s (%d)\n", var, var_len, val, val_len );
// Lets see what we've got
if ( 0 == strcmp( var, "serverName" ) )
{
server->server_name = strdup( val );
}
else if( 0 == strcmp( var, "map" ) )
{
// remove .res from map names
if ( 0 == strncmp( val + val_len - 4, ".res", 4 ) )
{
*(val + val_len - 4) = '\0';
}
server->map_name = strdup( val );
}
else if( 0 == strcmp( var, "maxPlayers" ) )
{
server->max_players = atoi( val );
}
else if( 0 == strcmp( var, "currentPlayers" ) )
{
server->num_players = no_players = atoi( val );
}
else
{
add_rule( server, var, val, NO_FLAGS );
}
}
// rules
while ( 1 == state && ptr < end )
{
// name value pairs null seperated
char *var, *val;
int var_len, val_len;
if ( ptr+4 <= end && 0x00 == ptr[0] && 0x00 == ptr[1] && 0x00 == ptr[2] && 0x00 == ptr[3] )
{
// end of basic
state++;
ptr += 4;
break;
}
var = ptr;
var_len = strlen( var );
ptr += var_len + 1;
if ( ptr + 1 > end )
{
malformed_packet( server, "no basic value" );
return PKT_ERROR;
}
val = ptr;
val_len = strlen( val );
ptr += val_len + 1;
debug( 2, "var:%s (%d)=%s (%d)\n", var, var_len, val, val_len );
// add the rule
add_rule( server, var, val, NO_FLAGS );
}
// players
while ( 2 == state && ptr < end )
{
// first we have the header
char *header = ptr;
int head_len = strlen( header );
ptr += head_len + 1;
if ( ptr+2 <= end && 0x00 == ptr[0] && 0x00 == ptr[1] )
{
// end of player headers
state++;
ptr += 2;
break;
}
if ( 0 == head_len )
{
// no more info
debug( 3, "All done" );
return DONE_FORCE;
}
debug( 2, "player header '%s'", header );
if ( ptr > end )
{
malformed_packet( server, "no details for header '%s'", header );
return PKT_ERROR;
}
}
while ( 3 == state && ptr < end )
{
char *header = ptr;
int head_len = strlen( header );
int header_type;
// the next byte is the starting number
total_players = *ptr++;
if ( 0 == strcmp( header, "player_" ) || 0 == strcmp( header, "name_" ) )
{
header_type = PLAYER_NAME_HEADER;
}
else if ( 0 == strcmp( header, "score_" ) )
{
header_type = PLAYER_SCORE_HEADER;
}
else if ( 0 == strcmp( header, "deaths_" ) )
{
header_type = PLAYER_DEATHS_HEADER;
}
else if ( 0 == strcmp( header, "ping_" ) )
{
header_type = PLAYER_PING_HEADER;
}
else if ( 0 == strcmp( header, "kills_" ) )
{
header_type = PLAYER_KILLS_HEADER;
}
else if ( 0 == strcmp( header, "team_" ) )
{
header_type = PLAYER_TEAM_HEADER;
}
else
{
header_type = PLAYER_OTHER_HEADER;
}
while( ptr < end )
{
// now each player details
// add the player
struct player *player;
char *val;
int val_len;
// check for end of this headers player info
if ( 0x00 == *ptr )
{
debug( 3, "end of '%s' detail", header );
ptr++;
// Note: can't check ( total_players != no_players ) here as we may have more packets
if ( ptr < end && 0x00 == *ptr )
{
debug( 3, "end of players" );
// end of all player headers / detail
state = 2;
ptr++;
}
break;
}
player = get_player_by_number( server, total_players );
if ( NULL == player )
{
player = add_player( server, total_players );
}
if ( ptr >= end )
{
malformed_packet( server, "short player detail" );
return PKT_ERROR;
}
val = ptr;
val_len = strlen( val );
ptr += val_len + 1;
debug( 2, "Player[%d][%s]=%s\n", total_players, header, val );
// lets see what we got
switch( header_type )
{
case PLAYER_NAME_HEADER:
player->name = strdup( val );
break;
case PLAYER_SCORE_HEADER:
player->score = atoi( val );
break;
case PLAYER_DEATHS_HEADER:
player->deaths = atoi( val );
break;
case PLAYER_PING_HEADER:
player->ping = atoi( val );
break;
case PLAYER_KILLS_HEADER:
player->frags = atoi( val );
break;
case PLAYER_TEAM_HEADER:
player->team = atoi( val );
break;
case PLAYER_OTHER_HEADER:
default:
if ( '_' == header[head_len-1] )
{
header[head_len-1] = '\0';
player_add_info( player, header, val, NO_FLAGS );
header[head_len-1] = '_';
}
else
{
player_add_info( player, header, val, NO_FLAGS );
}
break;
}
total_players++;
if ( total_players > no_players )
{
malformed_packet( server, "to many players %d > %d", total_players, no_players );
return PKT_ERROR;
}
}
}
if ( 3 == state )
{
no_teams = (unsigned char)*ptr;
ptr++;
debug( 2, "No teams:%d\n", no_teams );
state = 3;
}
while ( 4 == state && ptr < end )
{
// first we have the header
char *header = ptr;
int head_len = strlen( header );
int header_type;
ptr += head_len + 1;
if ( 0 == head_len )
{
// no more info
debug( 3, "All done" );
return DONE_FORCE;
}
debug( 2, "team header '%s'", header );
if ( 0 == strcmp( header, "team_t" ) )
{
header_type = TEAM_NAME_HEADER;
}
else
{
header_type = TEAM_OTHER_HEADER;
}
// the next byte is the starting number
total_teams = *ptr++;
while( ptr < end )
{
// now each teams details
char *val;
int val_len;
char rule[512];
if ( ptr >= end )
{
malformed_packet( server, "short team detail" );
return PKT_ERROR;
}
val = ptr;
val_len = strlen( val );
ptr += val_len + 1;
debug( 2, "Team[%d][%s]=%s\n", total_teams, header, val );
// lets see what we got
switch ( header_type )
{
case TEAM_NAME_HEADER:
// BF being stupid again teams 1 based instead of 0
players_set_teamname( server, total_teams + 1, val );
// N.B. yes no break
case TEAM_OTHER_HEADER:
default:
// add as a server rule
sprintf( rule, "%s%d", header, total_teams );
add_rule( server, rule, val, NO_FLAGS );
break;
}
total_teams++;
if ( 0x00 == *ptr )
{
// end of this headers teams
ptr++;
break;
}
}
}
}
return DONE_FORCE;
}
query_status_t send_haze_request_packet( struct qserver *server )
{
char *packet;
char query_buf[128];
size_t len;
unsigned char required = HAZE_BASIC_INFO;
if ( get_server_rules )
{
required |= HAZE_GAME_RULES;
server->flags |= TF_PLAYER_QUERY;
}
if ( get_player_info )
{
required |= HAZE_PLAYER_INFO;
required |= HAZE_TEAM_INFO;
server->flags |= TF_RULES_QUERY;
}
server->flags |= TF_STATUS_QUERY;
if ( server->challenge )
{
// we've recieved a challenge response, send the query + challenge id
len = sprintf(
query_buf,
"frdquery%c%c%c%c%c",
(unsigned char)(server->challenge >> 24),
(unsigned char)(server->challenge >> 16),
(unsigned char)(server->challenge >> 8),
(unsigned char)(server->challenge >> 0),
required
);
packet = query_buf;
}
else
{
// Either basic v3 protocol or challenge request
packet = haze_challenge;
len = sizeof( haze_challenge );
}
return send_packet( server, packet, len );
}

View file

@ -1,52 +0,0 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* $Id: hexen2.php,v 1.1 2007/07/11 09:12:31 tombuskens Exp $
*/
[hexen2]
status = "\x80\x00\x00\x0e\x02HEXENII\x00\x05"
require_once GAMEQ_BASE . 'Protocol.php';
/**
* Hexen 2 protocol
*
* @author Tom Buskens <t.buskens@deviation.nl>
* @version $Revision: 1.1 $
*/
class GameQ_Protocol_hexen2 extends GameQ_Protocol
{
/*
* status packet
*/
public function status()
{
// Header?
$this->p->skip(5);
$this->r->add('address', $this->p->readString());
$this->r->add('servername', $this->p->readString());
$this->r->add('map', $this->p->readString());
$this->r->add('num_players', $this->p->readInt8());
$this->r->add('max_players', $this->p->readInt8());
$this->p->skip(); // unknown
}
}
?>

View file

@ -1,77 +0,0 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* $Id: openttd.php,v 1.1 2009/10/24 18:45:16 evilpie Exp $
*/
[openttd]
status = "\x03\x00\x00"
require_once GAMEQ_BASE . 'Protocol.php';
/**
* OpenTTD Protocol, direct port from udp.cpp source from the game
*
* @author Tom Schuster <evilpie@users.sf.net>
* @version $Revision: 1.1 $
*/
class GameQ_Protocol_openttd extends GameQ_Protocol
{
public function status ()
{
$this->p->readInt16(); # packet size
$this->p->readInt8(); # packet type
$protocol_version = $this->p->readInt8();
$this->r->add('protocol_version', $protocol_version);
switch ($protocol_version)
{
case 4:
$num_grfs = $this->p->readInt8(); #number of grfs
$this->r->add('num_grfs', $num_grfs);
$this->p->skip ($num_grfs * 20); #skip id and md5 hash
case 3:
$this->r->add('game_date', $this->p->readInt32());
$this->r->add('start_date', $this->p->readInt32());
case 2:
$this->r->add('companies_max', $this->p->readInt8());
$this->r->add('companies_on', $this->p->readInt8());
$this->r->add('spectators_max', $this->p->readInt8());
case 1:
$this->r->add('hostname', $this->p->readString());
$this->r->add('version', $this->p->readString());
$this->r->add('language', $this->p->readInt8());
$this->r->add('password', $this->p->readInt8());
$this->r->add('max_clients', $this->p->readInt8());
$this->r->add('clients', $this->p->readInt8());
$this->r->add('spectators', $this->p->readInt8());
if ($protocol_version < 3)
{
$days = ( 365 * 1920 + 1920 / 4 - 1920 / 100 + 1920 / 400 );
$this->r->add('game_date', $this->p->readInt16() + $days);
$this->r->add('start_date', $this->p->readInt16() + $days);
}
$this->r->add('map', $this->p->readString());
$this->r->add('map_width', $this->p->readInt16());
$this->r->add('map_height', $this->p->readInt16());
$this->r->add('map_type', $this->p->readInt8());
$this->r->add('dedicated', $this->p->readInt8());
}
}
}

View file

@ -1,64 +0,0 @@
/*----------------------------------------------------------------------------------------------------------\
| |
| [ LIVE GAME SERVER LIST ] [ © RICHARD PERRY FROM GREYCUBE.COM ] |
| |
| Released under the terms and conditions of the GNU General Public License Version 3 (http://gnu.org) |
| |
\-----------------------------------------------------------------------------------------------------------
function lgsl_query_22(&$server, &$lgsl_need, &$lgsl_fp)
{
//---------------------------------------------------------+
fwrite($lgsl_fp,"\x03\x00\x00");
$buffer = fread($lgsl_fp, 4096);
$buffer = substr($buffer, 3); // REMOVE HEADER
if (!$buffer) { return FALSE; }
$response_type = ord(lgsl_cut_byte($buffer, 1)); // TYPE SHOULD BE 4
//---------------------------------------------------------+
$grf_count = ord(lgsl_cut_byte($buffer, 1));
for ($a=0; $a<$grf_count; $a++)
{
$server['e']['grf_'.$a.'_id'] = strtoupper(dechex(lgsl_unpack(lgsl_cut_byte($buffer, 4), "N")));
for ($b=0; $b<16; $b++)
{
$server['e']['grf_'.$a.'_md5'] .= strtoupper(dechex(ord(lgsl_cut_byte($buffer, 1))));
}
}
//---------------------------------------------------------+
$server['e']['date_current'] = lgsl_unpack(lgsl_cut_byte($buffer, 4), "L");
$server['e']['date_start'] = lgsl_unpack(lgsl_cut_byte($buffer, 4), "L");
$server['e']['companies_max'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['companies'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['spectators_max'] = ord(lgsl_cut_byte($buffer, 1));
$server['s']['name'] = lgsl_cut_string($buffer);
$server['e']['version'] = lgsl_cut_string($buffer);
$server['e']['language'] = ord(lgsl_cut_byte($buffer, 1));
$server['s']['password'] = ord(lgsl_cut_byte($buffer, 1));
$server['s']['playersmax'] = ord(lgsl_cut_byte($buffer, 1));
$server['s']['players'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['spectators'] = ord(lgsl_cut_byte($buffer, 1));
$server['s']['map'] = lgsl_cut_string($buffer);
$server['e']['map_width'] = lgsl_unpack(lgsl_cut_byte($buffer, 2), "S");
$server['e']['map_height'] = lgsl_unpack(lgsl_cut_byte($buffer, 2), "S");
$server['e']['map_set'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['dedicated'] = ord(lgsl_cut_byte($buffer, 1));
// DOES NOT RETURN PLAYER INFORMATION
//---------------------------------------------------------+
return TRUE;
}

View file

@ -1,404 +0,0 @@
LICENSE: The Artistic License 2.0
/*
* qstat.h
* by Steve Jankowski
* steve@qstat.org
* http://www.qstat.org
*
* Copyright 1996,1997,1998,1999,2000,2001,2002 by Steve Jankowski
*/
char ottd_serverinfo[] = {
0x03, 0x00, // packet length
0x00, // packet type
};
char ottd_serverdetails[] = {
0x03, 0x00, // packet length
0x02, // packet type
};
{
/* openTTD */
OTTD_SERVER, /* id */
"OTTDS", /* type_prefix */
"ottds", /* type_string */
"-ottds", /* type_option */
"OpenTTD", /* game_name */
0, /* master */
3979, /* default_port */
0, /* port_offset */
0, /* flags */
"", /* game_rule */
"OPENTTD", /* template_var */
(char*) &ottd_serverinfo, /* status_packet */
sizeof( ottd_serverinfo), /* status_len */
NULL, /* player_packet */
0, /* player_len */
(char*) &ottd_serverdetails,/* rule_packet */
sizeof( ottd_serverdetails), /* rule_len */
NULL, /* master_packet */
0, /* master_len */
NULL, /* master_protocol */
NULL, /* master_query */
display_q2_player_info, /* display_player_func */
display_server_rules, /* display_rule_func */
raw_display_q2_player_info, /* display_raw_player_func */
raw_display_server_rules, /* display_raw_rule_func */
xml_display_player_info,/* display_xml_player_func */
xml_display_server_rules, /* display_xml_rule_func */
send_ottd_request_packet, /* status_query_func */
NULL, /* rule_query_func */
NULL, /* player_query_func */
deal_with_ottd_packet, /* packet_func */
},
/*
* qstat 2.11
*
* opentTTD protocol
* Copyright 2007 Ludwig Nussel
*
* Licensed under the Artistic License, see LICENSE.txt for license terms
*/
#include <sys/types.h>
#ifndef _WIN32
#include <sys/socket.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include "qstat.h"
#include "qserver.h"
#include "debug.h"
enum { MAX_VEHICLE_TYPES = 5, MAX_STATION_TYPES = 5 };
static const char* vehicle_types[] = {
"num_trains",
"num_trucks",
"num_busses",
"num_aircrafts",
"num_ships",
};
static const char* station_types[] = {
"num_stations",
"num_truckbays",
"num_busstations",
"num_airports",
"num_docks",
};
query_status_t deal_with_ottdmaster_packet(struct qserver *server, char *rawpkt, int pktlen)
{
unsigned num;
server->ping_total += time_delta(&packet_recv_time, &server->packet_time1);
server->server_name = MASTER;
if(swap_short_from_little(rawpkt) != pktlen)
{
malformed_packet( server, "invalid packet length" );
return PKT_ERROR;
}
if(rawpkt[2] != 7)
{
malformed_packet( server, "invalid packet type" );
return PKT_ERROR;
}
if(rawpkt[3] != 1)
{
malformed_packet( server, "invalid packet version" );
return PKT_ERROR;
}
num = swap_short_from_little(&rawpkt[4]);
rawpkt += 6;
pktlen -= 6;
if( num && num*6 <= pktlen )
{
unsigned i;
server->master_pkt = (char*)realloc(server->master_pkt, server->master_pkt_len + pktlen );
memset(server->master_pkt + server->master_pkt_len, 0, pktlen );
server->master_pkt_len += pktlen;
for( i = 0; i < num * 6; i += 6 )
{
memcpy(&server->master_pkt[i], &rawpkt[i], 4);
server->master_pkt[i+4] = rawpkt[i+5];
server->master_pkt[i+5] = rawpkt[i+4];
}
server->n_servers += num;
}
else
{
malformed_packet( server, "invalid packet" );
return PKT_ERROR;
}
bind_sockets();
return DONE_AUTO;
}
#define xstr(s) str(s)
#define str(s) #s
#define GET_STRING do { \
str = (char*)ptr; \
ptr = memchr(ptr, '\0', end-ptr); \
if ( !ptr ) \
{ \
malformed_packet( server, "%s:%s invalid packet", __FILE__, xstr(__LINE__) ); \
return PKT_ERROR; \
} \
++ptr; \
} while(0)
#define FAIL_IF(cond, msg) \
if((cond)) { \
malformed_packet( server, "%s:%s %s", __FILE__, xstr(__LINE__), msg ); \
return PKT_ERROR; \
}
#define INVALID_IF(cond) \
FAIL_IF(cond, "invalid packet")
query_status_t deal_with_ottd_packet(struct qserver *server, char *rawpkt, int pktlen)
{
unsigned char *ptr = (unsigned char*)rawpkt;
unsigned char *end = (unsigned char*)(rawpkt + pktlen);
unsigned char type;
char* str;
char buf[32];
unsigned ver;
server->n_servers++;
if ( server->server_name == NULL)
{
server->ping_total += time_delta( &packet_recv_time, &server->packet_time1);
server->n_requests++;
}
else
{
gettimeofday( &server->packet_time1, NULL);
}
FAIL_IF(pktlen < 4 || swap_short_from_little(rawpkt) > pktlen, "invalid packet");
type = ptr[2];
ver = ptr[3];
ptr += 4;
debug(3, "len %hu type %hhu ver %hhu", swap_short_from_little(rawpkt), type, ver);
FAIL_IF(ver != 4 && ver != 5, "only version 4 and 5 servers are supported");
if(type == 1) // info packet
{
unsigned numgrf = *ptr;
FAIL_IF(ptr + numgrf * 20 + 1 > end, "invalid newgrf number");
ptr += numgrf * 20 + 1;
snprintf(buf, sizeof(buf), "%u", swap_long_from_little(ptr));
add_rule(server, "date_days", buf, NO_FLAGS);
ptr += 4;
snprintf(buf, sizeof(buf), "%u", swap_long_from_little(ptr));
add_rule(server, "startdate_days", buf, NO_FLAGS);
ptr += 4;
FAIL_IF(ptr + 3 > end, "invalid packet");
snprintf(buf, sizeof(buf), "%hhu", ptr[0]);
add_rule(server, "maxcompanies", buf, NO_FLAGS);
snprintf(buf, sizeof(buf), "%hhu", ptr[1]);
add_rule(server, "numcompanies", buf, NO_FLAGS);
server->max_spectators = ptr[2];
ptr += 3;
GET_STRING;
server->server_name = strdup(str);
GET_STRING;
add_rule(server, "version", str, NO_FLAGS);
FAIL_IF(ptr + 7 > end, "invalid packet");
{
static const char* langs[] = {
"any",
"English",
"German",
"French"
};
unsigned i = *ptr++;
if(i > 3) i = 0;
add_rule(server, "language", (char*)langs[i], NO_FLAGS);
}
add_rule(server, "password", *ptr++ ? "1" : "0", NO_FLAGS);
server->max_players = *ptr++;
server->num_players = *ptr++;
server->num_spectators = *ptr++;
GET_STRING;
server->map_name = strdup(str);
snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr));
add_rule(server, "map_width", buf, NO_FLAGS);
snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr));
add_rule(server, "map_height", buf, NO_FLAGS);
{
static const char* sets[] = {
"temperate",
"arctic",
"desert",
"toyland"
};
unsigned i = *ptr++;
if(i > 3) i = 0;
add_rule(server, "map_set", (char*)sets[i], NO_FLAGS);
}
add_rule(server, "dedicated", *ptr++ ? "1" : "0", NO_FLAGS);
}
else if(type == 3) // player packet
{
unsigned i, j;
INVALID_IF(ptr + 2 > end);
server->num_players = *ptr++;
for(i = 0; i < server->num_players; ++i)
{
unsigned long long lli;
struct player* player;
unsigned char nr;
nr = *ptr++;
debug(3, "player number %d", nr);
player = add_player(server, i);
FAIL_IF(!player, "can't allocate player");
GET_STRING;
player->name = strdup(str);
debug(3, "name %s", str);
player->frags = 0;
INVALID_IF(ptr + 4 + 3*8 + 2 + 1 + 2*MAX_VEHICLE_TYPES + 2*MAX_STATION_TYPES > end);
snprintf(buf, sizeof(buf), "%u", swap_long_from_little(ptr));
player_add_info(player, "startdate", buf, 0);
ptr += 4;
lli = swap_long_from_little(ptr+4);
lli <<= 32;
lli += swap_long_from_little(ptr);
snprintf(buf, sizeof(buf), "%lld", lli);
player_add_info(player, "value", buf, 0);
ptr += 8;
lli = swap_long_from_little(ptr+4);
lli <<= 32;
lli = swap_long_from_little(ptr);
snprintf(buf, sizeof(buf), "%lld", lli);
player_add_info(player, "money", buf, 0);
ptr += 8;
lli = swap_long_from_little(ptr+4);
lli <<= 32;
lli += swap_long_from_little(ptr);
snprintf(buf, sizeof(buf), "%lld", lli);
player_add_info(player, "income", buf, 0);
ptr += 8;
snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr));
player_add_info(player, "performance", buf, 0);
ptr += 2;
player_add_info(player, "password", *ptr?"1":"0", 0);
++ptr;
for (j = 0; j < MAX_VEHICLE_TYPES; ++j)
{
snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr));
player_add_info(player, (char*)vehicle_types[j], buf, 0);
ptr += 2;
}
for (j = 0; j < MAX_STATION_TYPES; ++j)
{
snprintf(buf, sizeof(buf), "%hu", swap_short_from_little(ptr));
player_add_info(player, (char*)station_types[j], buf, 0);
ptr += 2;
}
if (ver != 5)
{
// connections
while(ptr + 1 < end && *ptr)
{
++ptr;
GET_STRING; // client name
debug(3, "%s played by %s", str, player->name);
GET_STRING; // id
INVALID_IF(ptr + 4 > end);
ptr += 4;
}
++ptr; // record terminated by zero byte
}
}
// spectators
while(ptr + 1 < end && *ptr)
{
++ptr;
GET_STRING; // client name
debug(3, "spectator %s", str);
GET_STRING; // id
INVALID_IF(ptr + 4 > end);
ptr += 4;
}
++ptr; // record terminated by zero byte
server->next_rule = NO_SERVER_RULES; // we're done
server->next_player_info = server->num_players; // we're done
}
else
{
malformed_packet( server, "invalid type" );
return PKT_ERROR;
}
server->retry1 = n_retries; // we're done with this packet, reset retry counter
return DONE_AUTO;
}
query_status_t send_ottdmaster_request_packet(struct qserver *server)
{
return qserver_send_initial(server, server->type->master_packet, server->type->master_len);
}
query_status_t send_ottd_request_packet(struct qserver *server)
{
qserver_send_initial(server, server->type->status_packet, server->type->status_len);
if(get_server_rules || get_player_info)
{
server->next_rule = ""; // trigger calling send_a2s_rule_request_packet
}
return INPROGRESS;
}

View file

@ -1,33 +0,0 @@
/*----------------------------------------------------------------------------------------------------------\
| |
| [ LIVE GAME SERVER LIST ] [ © RICHARD PERRY FROM GREYCUBE.COM ] |
| |
| Released under the terms and conditions of the GNU General Public License Version 3 (http://gnu.org) |
| |
\-----------------------------------------------------------------------------------------------------------*/
function lgsl_query_32(&$server, &$lgsl_need, &$lgsl_fp)
{
//---------------------------------------------------------+
fwrite($lgsl_fp, "\x05\x00\x00\x01\x0A");
$buffer = fread($lgsl_fp, 4096);
if (!$buffer) { return FALSE; }
$buffer = substr($buffer, 5); // REMOVE HEADER
$server['s']['name'] = lgsl_cut_pascal($buffer);
$server['s']['map'] = lgsl_cut_pascal($buffer);
$server['s']['players'] = ord(lgsl_cut_byte($buffer, 1));
$server['s']['playersmax'] = 0; // HELD ON MASTER
// DOES NOT RETURN PLAYER INFORMATION
//---------------------------------------------------------+
return TRUE;
}

View file

@ -1,3 +0,0 @@
Most sources say raven shield uses gamespy1, but these docs are for
some other raven shield protocol. If anyone has an issue, this may
be the actual protocol.

View file

@ -1,446 +0,0 @@
LICENSE: The Artistic License 2.0
/*
* qstat.h
* by Steve Jankowski
* steve@qstat.org
* http://www.qstat.org
*
* Copyright 1996,1997,1998,1999,2000,2001,2002 by Steve Jankowski
*/
char ravenshield_serverquery[] = "REPORT";
{
/* RAVENSHIELD PROTOCOL */
RAVENSHIELD_SERVER, /* id */
"RSS", /* type_prefix */
"rss", /* type_string */
"-rss", /* type_option */
"Ravenshield", /* game_name */
0, /* master */
RAVENSHIELD_DEFAULT_PORT, /* default_port */
1000, /* port_offset */
TF_QUERY_ARG, /* flags */
"gametype", /* game_rule */
"RAVENSHIELD", /* template_var */
(char*)ravenshield_serverquery, /* status_packet */
sizeof( ravenshield_serverquery ) - 1, /* status_len */
NULL, /* player_packet */
0, /* player_len */
NULL, /* rule_packet */
0, /* rule_len */
NULL, /* master_packet */
0, /* master_len */
NULL, /* master_protocol */
NULL, /* master_query */
display_ravenshield_player_info, /* display_player_func */
display_server_rules, /* display_rule_func */
raw_display_ravenshield_player_info, /* display_raw_player_func */
raw_display_server_rules, /* display_raw_rule_func */
xml_display_ravenshield_player_info, /* display_xml_player_func */
xml_display_server_rules, /* display_xml_rule_func */
send_qserver_request_packet, /* status_query_func */
NULL, /* rule_query_func */
NULL, /* player_query_func */
deal_with_ravenshield_packet, /* packet_func */
},
query_status_t deal_with_ravenshield_packet(struct qserver *server, char *rawpkt, int pktlen)
{
char *s, *key, *value;
debug( 2, "deal_with_ravenshield_packet %p, %d", server, pktlen );
server->n_servers++;
if (NULL == server->server_name)
{
server->ping_total += time_delta(&packet_recv_time, &server->packet_time1);
}
else
{
gettimeofday(&server->packet_time1, NULL);
}
rawpkt[pktlen] = '\0';
s = rawpkt;
while (*s)
{
// Find the seperator
while (*s && *s != '\xB6')
{
s++;
}
if (! *s)
{
// Hit the end no more
break;
}
// key start
key = ++s;
while (*s && *s != ' ')
{
s++;
}
if (*s != ' ')
{
// malformed
break;
}
*s++ = '\0';
// key end
// value start
value = s;
while (*s && *s != '\xB6')
{
s++;
}
if (*s == '\xB6')
{
*(s - 1) = '\0';
}
// Decode current key par
if (0 == strcmp("A1", key))
{
// Max players
server->max_players = atoi(value);
}
else if (0 == strcmp("A2", key))
{
// TeamKillerPenalty
add_rule(server, "TeamKillerPenalty", value, NO_FLAGS);
}
else if (0 == strcmp("B1", key))
{
// Current players
server->num_players = atoi(value);
}
else if (0 == strcmp("B2", key))
{
// AllowRadar
add_rule(server, "AllowRadar", value, NO_FLAGS);
}
else if (0 == strcmp("D2", key))
{
// Version info
add_rule(server, "Version", value, NO_FLAGS);
}
else if (0 == strcmp("E1", key))
{
// Current map
server->map_name = strdup(value);
}
else if (0 == strcmp("E2", key))
{
// Unknown
}
else if (0 == strcmp("F1", key))
{
// Game type
server->game = find_ravenshield_game(value);
add_rule(server, server->type->game_rule, server->game, NO_FLAGS);
}
else if (0 == strcmp("F2", key))
{
// Unknown
}
else if (0 == strcmp("G1", key))
{
// Password
add_rule(server, "Password", value, NO_FLAGS);
}
else if (0 == strcmp("G2", key))
{
// Query port
}
else if (0 == strcmp("H1", key))
{
// Unknown
}
else if (0 == strcmp("H2", key))
{
// Number of Terrorists
add_rule(server, "nbTerro", value, NO_FLAGS);
}
else if (0 == strcmp("I1", key))
{
// Server name
server->server_name = strdup(value);
}
else if (0 == strcmp("I2", key))
{
// Unknown
}
else if (0 == strcmp("J1", key))
{
// Game Type Order
// Not pretty ignore for now
//add_rule( server, "Game Type Order", value, NO_FLAGS );
}
else if (0 == strcmp("J2", key))
{
// RotateMap
add_rule(server, "RotateMap", value, NO_FLAGS);
}
else if (0 == strcmp("K1", key))
{
// Map Cycle
// Not pretty ignore for now
//add_rule( server, "Map Cycle", value, NO_FLAGS );
}
else if (0 == strcmp("K2", key))
{
// Force First Person Weapon
add_rule(server, "ForceFPersonWeapon", value, NO_FLAGS);
}
else if (0 == strcmp("L1", key))
{
// Players names
int player_number = 0;
char *n = value;
if (*n == '/')
{
// atleast 1 player
n++;
while (*n && *n != '\xB6')
{
char *player_name = n;
while (*n && *n != '/' && *n != '\xB6')
{
n++;
}
if (*n == '/')
{
*n++ = '\0';
}
else if (*n == '\xB6')
{
*(n - 1) = '\0';
}
if (0 != strlen(player_name))
{
struct player *player = add_player(server, player_number);
if (NULL != player)
{
player->name = strdup(player_name);
}
player_number++;
}
}
}
}
else if (0 == strcmp("L3", key))
{
// PunkBuster state
add_rule(server, "PunkBuster", value, NO_FLAGS);
}
else if (0 == strcmp("M1", key))
{
// Players times
int player_number = 0;
char *n = value;
if (*n == '/')
{
// atleast 1 player
n++;
while (*n && *n != '\xB6')
{
char *time = n;
while (*n && *n != '/' && *n != '\xB6')
{
n++;
}
if (*n == '/')
{
*n++ = '\0';
}
else if (*n == '\xB6')
{
*(n - 1) = '\0';
}
if (0 != strlen(time))
{
int mins, seconds;
if (2 == sscanf(time, "%d:%d", &mins, &seconds))
{
struct player *player = get_player_by_number(server, player_number);
if (NULL != player)
{
player->connect_time = mins * 60+seconds;
}
}
player_number++;
}
}
}
}
else if (0 == strcmp("N1", key))
{
// Players ping
int player_number = 0;
char *n = value;
if (*n == '/')
{
// atleast 1 player
n++;
while (*n && *n != '\xB6')
{
char *ping = n;
while (*n && *n != '/' && *n != '\xB6')
{
n++;
}
if (*n == '/')
{
*n++ = '\0';
}
else if (*n == '\xB6')
{
*(n - 1) = '\0';
}
if (0 != strlen(ping))
{
struct player *player = get_player_by_number(server, player_number);
if (NULL != player)
{
player->ping = atoi(ping);
} player_number++;
}
}
}
}
else if (0 == strcmp("O1", key))
{
// Players fags
int player_number = 0;
char *n = value;
if (*n == '/')
{
// atleast 1 player
n++;
while (*n && *n != '\xB6')
{
char *frags = n;
while (*n && *n != '/' && *n != '\xB6')
{
n++;
}
if (*n == '/')
{
*n++ = '\0';
}
else if (*n == '\xB6')
{
*(n - 1) = '\0';
}
if (0 != strlen(frags))
{
struct player *player = get_player_by_number(server, player_number);
if (NULL != player)
{
player->frags = atoi(frags);
} player_number++;
}
}
}
}
else if (0 == strcmp("P1", key))
{
// Game port
// Not pretty ignore for now
/*
change_server_port( server, atoi( value ), 0 );
*/
}
else if (0 == strcmp("Q1", key))
{
// RoundsPerMatch
add_rule(server, "RoundsPerMatch", value, NO_FLAGS);
}
else if (0 == strcmp("R1", key))
{
// RoundTime
add_rule(server, "RoundTime", value, NO_FLAGS);
}
else if (0 == strcmp("S1", key))
{
// BetweenRoundTime
add_rule(server, "BetweenRoundTime", value, NO_FLAGS);
}
else if (0 == strcmp("T1", key))
{
// BombTime
add_rule(server, "BombTime", value, NO_FLAGS);
}
else if (0 == strcmp("W1", key))
{
// ShowNames
add_rule(server, "ShowNames", value, NO_FLAGS);
}
else if (0 == strcmp("X1", key))
{
// InternetServer
add_rule(server, "InternetServer", value, NO_FLAGS);
}
else if (0 == strcmp("Y1", key))
{
// FriendlyFire
add_rule(server, "FriendlyFire", value, NO_FLAGS);
}
else if (0 == strcmp("Z1", key))
{
// Autobalance
add_rule(server, "Autobalance", value, NO_FLAGS);
}
}
return DONE_FORCE;
}
char *find_ravenshield_game(char *gameno)
{
switch (atoi(gameno))
{
case 8:
return strdup("Team Deathmatch");
break;
case 13:
return strdup("Deathmatch");
break;
case 14:
return strdup("Team Deathmatch");
break;
case 15:
return strdup("Bomb");
break;
case 16:
return strdup("Escort Pilot");
break;
default:
// 1.50 and above actually uses a string so
// return that
return strdup(gameno);
break;
}
}

View file

@ -1,59 +0,0 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* $Id: redfaction.php,v 1.1 2007/06/30 12:43:43 tombuskens Exp $
*/
[redfaction]
status = "\x00\x00\x00\x00"
require_once GAMEQ_BASE . 'Protocol.php';
/**
* Red Faction Protocol
*
* @author Tom Buskens <t.buskens@deviation.nl>
* @version $Revision: 1.1 $
*/
class GameQ_Protocol_redfaction extends GameQ_Protocol
{
/*
* getstatus packet
*/
public function status()
{
// Header, we're being carefull here
if ($this->p->read() !== "\x00") {
throw new GameQ_ParsingException($this->p);
}
// Dunno
while ($this->p->read() !== "\x00") {}
$this->p->read();
// Data
$this->r->add('servername', $this->p->readString());
$this->r->add('gametype', $this->p->readInt8());
$this->r->add('num_players', $this->p->readInt8());
$this->r->add('max_players', $this->p->readInt8());
$this->r->add('map', $this->p->readString());
$this->p->read();
$this->r->add('dedicated', $this->p->readInt8());
}
}

View file

@ -1,62 +0,0 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* $Id: rfactor.php,v 1.2 2009/08/13 20:46:40 evilpie Exp $
*/
[rfactor]
status = "rF_S"
require_once GAMEQ_BASE . 'Protocol.php';
/**
* rFactor Protocol
*
* @author Tom Buskens <t.buskens@deviation.nl>
* @version $Revision: 1.2 $
*/
class GameQ_Protocol_rfactor extends GameQ_Protocol
{
public function status()
{
// Header
$this->p->jumpto(17);
$this->r->add('version', $this->p->readInt16());
$this->p->jumpto(25);
$this->r->add('series', $this->p->readString());
$this->p->jumpto(45);
$this->r->add('servername', $this->p->readString());
$this->p->jumpto(73);
$this->r->add('map', $this->p->readString());
$this->p->jumpto(105);
$this->r->add('motd', $this->p->readString());
$this->p->jumpto(206);
$this->r->add('rate', $this->p->readInt8());
$this->r->add('numplayers', $this->p->readInt8());
$this->r->add('maxplayers', $this->p->readInt8());
$this->r->add('numbots', $this->p->readInt8());
$this->r->add('session', $this->p->readInt8() >> 5);
$this->r->add('damage', $this->p->readInt8());
$this->p->jumpto(217);
$this->r->add('time', $this->p->readInt16());
$this->r->add('laps', $this->p->readInt16() / 16);
}
}
?>

View file

@ -1,94 +0,0 @@
/*----------------------------------------------------------------------------------------------------------\
| |
| [ LIVE GAME SERVER LIST ] [ © RICHARD PERRY FROM GREYCUBE.COM ] |
| |
| Released under the terms and conditions of the GNU General Public License Version 3 (http://gnu.org) |
| |
\-----------------------------------------------------------------------------------------------------------*/
function lgsl_query_16(&$server, &$lgsl_need, &$lgsl_fp)
{
//---------------------------------------------------------+
// REFERENCE:
// http://www.planetpointy.co.uk/software/rfactorsspy.shtml
// http://users.pandora.be/viperius/mUtil/
// USES FIXED DATA POSITIONS WITH RANDOM CHARACTERS FILLING THE GAPS
fwrite($lgsl_fp, "rF_S");
$buffer = fread($lgsl_fp, 4096);
if (!$buffer) { return FALSE; }
//---------------------------------------------------------+
// $server['e']['gamename'] = lgsl_get_string($buffer);
$buffer = substr($buffer, 8);
// $server['e']['fullupdate'] = lgsl_unpack($buffer[0], "C");
$server['e']['region'] = lgsl_unpack($buffer[1] .$buffer[2], "S");
// $server['e']['ip'] = ($buffer[3] .$buffer[4].$buffer[5].$buffer[6]); // UNSIGNED LONG
// $server['e']['size'] = lgsl_unpack($buffer[7] .$buffer[8], "S");
$server['e']['version'] = lgsl_unpack($buffer[9] .$buffer[10], "S");
// $server['e']['version_racecast'] = lgsl_unpack($buffer[11].$buffer[12], "S");
$server['e']['hostport'] = lgsl_unpack($buffer[13].$buffer[14], "S");
// $server['e']['queryport'] = lgsl_unpack($buffer[15].$buffer[16], "S");
$buffer = substr($buffer, 17);
$server['s']['game'] = lgsl_get_string($buffer);
$buffer = substr($buffer, 20);
$server['s']['name'] = lgsl_get_string($buffer);
$buffer = substr($buffer, 28);
$server['s']['map'] = lgsl_get_string($buffer);
$buffer = substr($buffer, 32);
$server['e']['motd'] = lgsl_get_string($buffer);
$buffer = substr($buffer, 96);
$server['e']['packed_aids'] = lgsl_unpack($buffer[0].$buffer[1], "S");
// $server['e']['ping'] = lgsl_unpack($buffer[2].$buffer[3], "S");
$server['e']['packed_flags'] = lgsl_unpack($buffer[4], "C");
$server['e']['rate'] = lgsl_unpack($buffer[5], "C");
$server['s']['players'] = lgsl_unpack($buffer[6], "C");
$server['s']['playersmax'] = lgsl_unpack($buffer[7], "C");
$server['e']['bots'] = lgsl_unpack($buffer[8], "C");
$server['e']['packed_special'] = lgsl_unpack($buffer[9], "C");
$server['e']['damage'] = lgsl_unpack($buffer[10], "C");
$server['e']['packed_rules'] = lgsl_unpack($buffer[11].$buffer[12], "S");
$server['e']['credits1'] = lgsl_unpack($buffer[13], "C");
$server['e']['credits2'] = lgsl_unpack($buffer[14].$buffer[15], "S");
$server['e']['time'] = lgsl_time(lgsl_unpack($buffer[16].$buffer[17], "S"));
$server['e']['laps'] = lgsl_unpack($buffer[18].$buffer[19], "s") / 16;
$buffer = substr($buffer, 23);
$server['e']['vehicles'] = lgsl_get_string($buffer);
// DOES NOT RETURN PLAYER INFORMATION
//---------------------------------------------------------+
$server['s']['password'] = ($server['e']['packed_special'] & 2) ? 1 : 0;
$server['e']['racecast'] = ($server['e']['packed_special'] & 4) ? 1 : 0;
$server['e']['fixedsetups'] = ($server['e']['packed_special'] & 16) ? 1 : 0;
$server['e']['aids'] = "";
if ($server['e']['packed_aids'] & 1) { $server['e']['aids'] .= " TractionControl"; }
if ($server['e']['packed_aids'] & 2) { $server['e']['aids'] .= " AntiLockBraking"; }
if ($server['e']['packed_aids'] & 4) { $server['e']['aids'] .= " StabilityControl"; }
if ($server['e']['packed_aids'] & 8) { $server['e']['aids'] .= " AutoShifting"; }
if ($server['e']['packed_aids'] & 16) { $server['e']['aids'] .= " AutoClutch"; }
if ($server['e']['packed_aids'] & 32) { $server['e']['aids'] .= " Invulnerability"; }
if ($server['e']['packed_aids'] & 64) { $server['e']['aids'] .= " OppositeLock"; }
if ($server['e']['packed_aids'] & 128) { $server['e']['aids'] .= " SteeringHelp"; }
if ($server['e']['packed_aids'] & 256) { $server['e']['aids'] .= " BrakingHelp"; }
if ($server['e']['packed_aids'] & 512) { $server['e']['aids'] .= " SpinRecovery"; }
if ($server['e']['packed_aids'] & 1024) { $server['e']['aids'] .= " AutoPitstop"; }
$server['e']['aids'] = str_replace(" ", " / ", trim($server['e']['aids']));
$server['e']['vehicles'] = str_replace("|", " / ", trim($server['e']['vehicles']));
unset($server['e']['packed_aids']);
unset($server['e']['packed_flags']);
unset($server['e']['packed_special']);
unset($server['e']['packed_rules']);
//---------------------------------------------------------+
return TRUE;
}

View file

@ -1,92 +0,0 @@
/*----------------------------------------------------------------------------------------------------------\
| |
| [ LIVE GAME SERVER LIST ] [ © RICHARD PERRY FROM GREYCUBE.COM ] |
| |
| Released under the terms and conditions of the GNU General Public License Version 3 (http://gnu.org) |
| |
\-----------------------------------------------------------------------------------------------------------*/
function lgsl_query_12(&$server, &$lgsl_need, &$lgsl_fp)
{
//---------------------------------------------------------+
// REFERENCE:
// VICE CITY CURRENTLY ONLY SUPPORTS THE 'i' CHALLENGE
if ($server['b']['type'] == "samp") { $challenge_packet = "SAMP\x21\x21\x21\x21\x00\x00"; }
elseif ($server['b']['type'] == "vcmp") { $challenge_packet = "VCMP\x21\x21\x21\x21\x00\x00"; $lgsl_need['e'] = FALSE; $lgsl_need['p'] = FALSE; }
if ($lgsl_need['s']) { $challenge_packet .= "i"; }
elseif ($lgsl_need['e']) { $challenge_packet .= "r"; }
elseif ($lgsl_need['p']) { $challenge_packet .= "d"; }
fwrite($lgsl_fp, $challenge_packet);
$buffer = fread($lgsl_fp, 4096);
if (!$buffer) { return FALSE; }
//---------------------------------------------------------+
$buffer = substr($buffer, 10); // REMOVE HEADER
$response_type = lgsl_cut_byte($buffer, 1);
//---------------------------------------------------------+
if ($response_type == "i")
{
$lgsl_need['s'] = FALSE;
$server['s']['password'] = ord(lgsl_cut_byte($buffer, 1));
$server['s']['players'] = lgsl_unpack(lgsl_cut_byte($buffer, 2), "S");
$server['s']['playersmax'] = lgsl_unpack(lgsl_cut_byte($buffer, 2), "S");
$server['s']['name'] = lgsl_cut_pascal($buffer, 4);
$server['e']['gamemode'] = lgsl_cut_pascal($buffer, 4);
$server['s']['map'] = lgsl_cut_pascal($buffer, 4);
}
//---------------------------------------------------------+
elseif ($response_type == "r")
{
$lgsl_need['e'] = FALSE;
$item_total = lgsl_unpack(lgsl_cut_byte($buffer, 2), "S");
for ($i=0; $i<$item_total; $i++)
{
if (!$buffer) { return FALSE; }
$data_key = strtolower(lgsl_cut_pascal($buffer));
$data_value = lgsl_cut_pascal($buffer);
$server['e'][$data_key] = $data_value;
}
}
//---------------------------------------------------------+
elseif ($response_type == "d")
{
$lgsl_need['p'] = FALSE;
$player_total = lgsl_unpack(lgsl_cut_byte($buffer, 2), "S");
for ($i=0; $i<$player_total; $i++)
{
if (!$buffer) { return FALSE; }
$server['p'][$i]['pid'] = ord(lgsl_cut_byte($buffer, 1));
$server['p'][$i]['name'] = lgsl_cut_pascal($buffer);
$server['p'][$i]['score'] = lgsl_unpack(lgsl_cut_byte($buffer, 4), "S");
$server['p'][$i]['ping'] = lgsl_unpack(lgsl_cut_byte($buffer, 4), "S");
}
}
//---------------------------------------------------------+
return TRUE;
}

View file

@ -1,92 +0,0 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* $Id: silverback.php,v 1.1 2007/07/11 09:12:31 tombuskens Exp $
*/
[silverback]
status = "\x9e\x4c\x23\x00\x00\xcePiNG"
require_once GAMEQ_BASE . 'Protocol.php';
/**
* Silverback Engine Protocol
* (Savage)
*
* @author Tom Buskens <t.buskens@deviation.nl>
* @version $Revision: 1.1 $
*/
class GameQ_Protocol_silverback extends GameQ_Protocol
{
/*
* status packet
*/
public function status()
{
while ($this->p->getLength()) {
$var = $this->p->readString("\xFE");
if ($var == 'players') break;
$this->r->add($var, $this->p->readString("\xFF"));
}
$this->players();
}
/*
* player / team data
*/
public function players()
{
$team = '';
$players = 0;
while ($this->p->getLength()) {
if ($this->p->lookAhead() == "\x20") {
$this->p->skip();
$this->r->addPlayer('name', $this->p->readString("\x0a"));
$this->r->addPlayer('team', $team);
++$players;
}
else {
$team = $this->p->readString("\x0a");
if ($team != '--empty--') {
$this->r->addTeam('name', $team);
}
}
}
}
/*
* Merge packets
*/
public function preprocess($packets)
{
// Cut off headers and join packets
$return = '';
foreach ($packets as $packet) {
$return .= substr($packet, 12, strlen($packet) - 13);
}
return $return;
}
}
?>

View file

@ -1,66 +0,0 @@
/*----------------------------------------------------------------------------------------------------------\
| |
| [ LIVE GAME SERVER LIST ] [ © RICHARD PERRY FROM GREYCUBE.COM ] |
| |
| Released under the terms and conditions of the GNU General Public License Version 3 (http://gnu.org) |
| |
\-----------------------------------------------------------------------------------------------------------*/
function lgsl_query_17(&$server, &$lgsl_need, &$lgsl_fp)
{
//---------------------------------------------------------+
// REFERENCE: http://masterserver.savage.s2games.com
fwrite($lgsl_fp, "\x9e\x4c\x23\x00\x00\xce\x21\x21\x21\x21");
$buffer = fread($lgsl_fp, 4096);
if (!$buffer) { return FALSE; }
//---------------------------------------------------------+
$buffer = substr($buffer, 12); // REMOVE HEADER
while ($key = strtolower(lgsl_cut_string($buffer, 0, "\xFE")))
{
if ($key == "players") { break; }
$value = lgsl_cut_string($buffer, 0, "\xFF");
$value = str_replace("\x00", "", $value);
$value = lgsl_parse_color($value, $server['b']['type']);
$server['e'][$key] = $value;
}
$server['s']['name'] = $server['e']['name']; unset($server['e']['name']);
$server['s']['map'] = $server['e']['world']; unset($server['e']['world']);
$server['s']['players'] = $server['e']['cnum']; unset($server['e']['cnum']);
$server['s']['playersmax'] = $server['e']['cmax']; unset($server['e']['cnum']);
$server['s']['password'] = $server['e']['pass']; unset($server['e']['cnum']);
//---------------------------------------------------------+
$server['t'][0]['name'] = $server['e']['race1'];
$server['t'][1]['name'] = $server['e']['race2'];
$server['t'][2]['name'] = "spectator";
$team_key = -1;
$player_key = 0;
while ($value = lgsl_cut_string($buffer, 0, "\x0a"))
{
if ($value[0] == "\x00") { break; }
if ($value[0] != "\x20") { $team_key++; continue; }
$server['p'][$player_key]['name'] = lgsl_parse_color(substr($value, 1), $server['b']['type']);
$server['p'][$player_key]['team'] = $server['t'][$team_key]['name'];
$player_key++;
}
//---------------------------------------------------------+
return TRUE;
}

View file

@ -1,278 +0,0 @@
LICENSE: The Artistic License 2.0
/*
* qstat.h
* by Steve Jankowski
* steve@qstat.org
* http://www.qstat.org
*
* Copyright 1996,1997,1998,1999,2000,2001,2002 by Steve Jankowski
*/
unsigned char savage_serverquery[] = {
0x9e,0x4c,0x23,0x00,0x00,0xc8,0x01,0x21,0x00,0x00
};
unsigned char savage_playerquery[] = {
0x9e,0x4c,0x23,0x00,0x00,0xce,0x76,0x46,0x00,0x00
};
{
/* SAVAGE PROTOCOL */
SAVAGE_SERVER, /* id */
"SAS", /* type_prefix */
"sas", /* type_string */
"-sas", /* type_option */
"Savage", /* game_name */
0, /* master */
SAVAGE_DEFAULT_PORT, /* default_port */
0, /* port_offset */
TF_QUERY_ARG, /* flags */
"gametype", /* game_rule */
"SAVAGE", /* template_var */
(char*)savage_serverquery, /* status_packet */
sizeof( savage_serverquery ) - 1, /* status_len */
(char*)savage_playerquery, /* player_packet */
sizeof( savage_playerquery ) - 1, /* player_len */
NULL, /* rule_packet */
0, /* rule_len */
NULL, /* master_packet */
0, /* master_len */
NULL, /* master_protocol */
NULL, /* master_query */
display_savage_player_info, /* display_player_func */
display_server_rules, /* display_rule_func */
raw_display_savage_player_info, /* display_raw_player_func */
raw_display_server_rules, /* display_raw_rule_func */
xml_display_savage_player_info, /* display_xml_player_func */
xml_display_server_rules, /* display_xml_rule_func */
send_savage_request_packet, /* status_query_func */
NULL, /* rule_query_func */
NULL, /* player_query_func */
deal_with_savage_packet, /* packet_func */
},
query_status_t send_savage_request_packet(struct qserver *server)
{
int len;
char *pkt;
if (get_player_info)
{
pkt = server->type->player_packet;
len = server->type->player_len;
}
else
{
pkt = server->type->status_packet;
len = server->type->status_len;
}
return send_packet(server, pkt, len);
}
query_status_t deal_with_savage_packet(struct qserver *server, char *rawpkt, int pktlen)
{
char *s, *key, *value, *end;
debug( 2, "deal_with_savage_packet %p, %d", server, pktlen );
server->n_servers++;
if (NULL == server->server_name)
{
server->ping_total += time_delta(&packet_recv_time, &server->packet_time1);
}
else
{
gettimeofday(&server->packet_time1, NULL);
}
rawpkt[pktlen] = '\0';
end = s = rawpkt;
end += pktlen;
while (*s)
{
// Find the seperator
while (s <= end && *s != '\xFF')
{
s++;
}
if (s >= end)
{
// Hit the end no more
break;
}
// key start
key = ++s;
while (s < end && *s != '\xFE')
{
s++;
}
if (*s != '\xFE')
{
// malformed
break;
}
*s++ = '\0';
// key end
// value start
value = s;
while (s < end && *s != '\xFF')
{
s++;
}
if (*s == '\xFF')
{
*s = '\0';
}
//fprintf( stderr, "'%s' = '%s'\n", key, value );
// Decode current key par
if (0 == strcmp("cmax", key))
{
// Max players
server->max_players = atoi(value);
}
else if (0 == strcmp("cnum", key))
{
// Current players
server->num_players = atoi(value);
}
else if (0 == strcmp("bal", key))
{
// Balance
add_rule(server, "Balance", value, NO_FLAGS);
}
else if (0 == strcmp("world", key))
{
// Current map
server->map_name = strdup(value);
}
else if (0 == strcmp("gametype", key))
{
// Game type
server->game = find_savage_game(value);
add_rule(server, server->type->game_rule, server->game, NO_FLAGS);
}
else if (0 == strcmp("pure", key))
{
// Pure
add_rule(server, "Pure", value, NO_FLAGS);
}
else if (0 == strcmp("time", key))
{
// Current game time
add_rule(server, "Time", value, NO_FLAGS);
}
else if (0 == strcmp("notes", key))
{
// Notes
add_rule(server, "Notes", value, NO_FLAGS);
}
else if (0 == strcmp("needcmdr", key))
{
// Need Commander
add_rule(server, "Need Commander", value, NO_FLAGS);
}
else if (0 == strcmp("name", key))
{
// Server name
server->server_name = strdup(value);
}
else if (0 == strcmp("fw", key))
{
// Firewalled
add_rule(server, "Firewalled", value, NO_FLAGS);
}
else if (0 == strcmp("players", key))
{
// Players names
int player_number = 0;
int team_number = 1;
char *team_name, *player_name, *n;
n = team_name = value;
// team name
n++;
while (*n && *n != '\x0a')
{
n++;
}
if (*n != '\x0a')
{
// Broken data
break;
}
*n = '\0';
player_name = ++n;
while (*n)
{
while (*n && *n != '\x0a')
{
n++;
}
if (*n != '\x0a')
{
// Broken data
break;
}
*n = '\0';
n++;
if (0 == strncmp("Team ", player_name, 5))
{
team_name = player_name;
team_number++;
}
else
{
if (0 != strlen(player_name))
{
struct player *player = add_player(server, player_number);
if (NULL != player)
{
player->name = strdup(player_name);
player->team = team_number;
player->team_name = strdup(team_name);
} player_number++;
}
}
player_name = n;
}
}
*s = '\xFF';
}
return DONE_FORCE;
}
char *find_savage_game(char *gametype)
{
if (0 == strcmp("RTSS", gametype))
{
return strdup("RTSS");
}
else
{
return strdup("Unknown");
}
}

View file

@ -1,55 +0,0 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* $Id: savage2.php,v 1.1 2008/05/22 14:16:11 tombuskens Exp $
*/
[savage2]
status = "\x01"
require_once GAMEQ_BASE . 'Protocol.php';
/**
* Savage 2 Protocol
*
* @author Tom Buskens <t.buskens@deviation.nl>
* @version $Revision: 1.1 $
*/
class GameQ_Protocol_savage2 extends GameQ_Protocol
{
/*
* status packet
*/
public function status()
{
$this->p->skip(12);
$this->r->add('hostname', $this->p->readString());
$this->r->add('num_players', $this->p->readInt8());
$this->r->add('max_players', $this->p->readInt8());
$this->r->add('time', $this->p->readString());
$this->r->add('map', $this->p->readString());
$this->r->add('nextmap', $this->p->readString());
$this->r->add('location', $this->p->readString());
$this->r->add('min_players', $this->p->readInt8());
$this->r->add('gametype', $this->p->readString());
$this->r->add('version', $this->p->readString());
$this->r->add('min_level', $this->p->readInt8());
}
}
?>

View file

@ -1,46 +0,0 @@
/*----------------------------------------------------------------------------------------------------------\
| |
| [ LIVE GAME SERVER LIST ] [ © RICHARD PERRY FROM GREYCUBE.COM ] |
| |
| Released under the terms and conditions of the GNU General Public License Version 3 (http://gnu.org) |
| |
\-----------------------------------------------------------------------------------------------------------*/
//------------------------------------------------------------------------------------------------------------+
//------------------------------------------------------------------------------------------------------------+
function lgsl_query_18(&$server, &$lgsl_need, &$lgsl_fp)
{
//---------------------------------------------------------+
// REFERENCE: http://masterserver.savage2.s2games.com
fwrite($lgsl_fp, "\x01");
$buffer = fread($lgsl_fp, 4096);
if (!$buffer) { return FALSE; }
//---------------------------------------------------------+
$buffer = substr($buffer, 12); // REMOVE HEADER
$server['s']['name'] = lgsl_cut_string($buffer);
$server['s']['players'] = ord(lgsl_cut_byte($buffer, 1));
$server['s']['playersmax'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['time'] = lgsl_cut_string($buffer);
$server['s']['map'] = lgsl_cut_string($buffer);
$server['e']['nextmap'] = lgsl_cut_string($buffer);
$server['e']['location'] = lgsl_cut_string($buffer);
$server['e']['minimum_players'] = ord(lgsl_cut_string($buffer));
$server['e']['gamemode'] = lgsl_cut_string($buffer);
$server['e']['version'] = lgsl_cut_string($buffer);
$server['e']['minimum_level'] = ord(lgsl_cut_byte($buffer, 1));
// DOES NOT RETURN PLAYER INFORMATION
//---------------------------------------------------------+
return TRUE;
}

View file

@ -1,65 +0,0 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* $Id: teeworlds.php,v 1.2 2009/03/09 13:36:32 tombuskens Exp $
*/
[teeworlds]
status = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFgief"
require_once GAMEQ_BASE . 'Protocol.php';
/**
* Teeworlds protocol
*
* @author Tom Buskens <t.buskens@deviation.nl>
* @version $Revision: 1.2 $
*/
class GameQ_Protocol_teeworlds extends GameQ_Protocol
{
/*
* status packet
*/
public function status()
{
$this->p->skip(14);
$this->r->add('version', $this->p->readString());
$this->r->add('hostname', $this->p->readString());
$this->r->add('map', $this->p->readString());
$this->r->add('gametype', $this->p->readString());
$this->r->add('password', $this->p->readString());
$this->r->add('ping', $this->p->readString());
$this->r->add('num_players', $this->p->readString());
$this->r->add('max_players', $this->p->readString());
$this->players();
}
private function players()
{
while ($name = $this->p->readString()) {
$this->r->addPlayer('name', $name);
$this->r->addPlayer('score', $this->p->readString());
}
}
}
?>

View file

@ -1,109 +0,0 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Teeworlds Protocol
*
* @author Marcel Bößendörfer <m.boessendoerfer@marbis.net>
*/
class GameQ_Protocols_Teeworlds extends GameQ_Protocols {
/**
* Array of packets we want to look up.
* Each key should correspond to a defined method in this or a parent class
*
* @var array
*/
protected $packets = array(
self::PACKET_ALL => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x67\x69\x65\x33\x05",
// 0.5 Packet (not compatible, maybe some wants to implement "Teeworldsold")
//self::PACKET_STATUS => "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFgief",
);
/**
* Methods to be run when processing the response(s)
*
* @var array
*/
protected $process_methods = array(
"process_all"
);
/**
* Default port for this server type
*
* @var int
*/
protected $port = 8303; // Default port, used if not set when instanced
/**
* The protocol being used
*
* @var string
*/
protected $protocol = 'teeworlds';
/**
* String name of this protocol class
*
* @var string
*/
protected $name = 'teeworlds';
/**
* Longer string name of this protocol class
*
* @var string
*/
protected $name_long = "Teeworlds";
/*
* Internal methods
*/
protected function process_all() {
if(!$this->hasValidResponse(self::PACKET_ALL))
{
return array();
}
$data = $this->packets_response[self::PACKET_ALL][0];
$buf = new GameQ_Buffer($data);
$result = new GameQ_Result();
$buf->readString();
$result->add('version', $buf->readString());
$result->add('hostname', $buf->readString());
$result->add('map', $buf->readString());
$result->add('game_descr', $buf->readString());
$result->add('flags', $buf->readString()); // not use about that
$result->add('num_players', $buf->readString());
$result->add('maxplayers', $buf->readString());
$result->add('num_players_total', $buf->readString());
$result->add('maxplayers_total', $buf->readString());
// Players
while ($buf->getLength()) {
$result->addPlayer('name', $buf->readString());
$result->addPlayer('clan', $buf->readString());
$result->addPlayer('flag', $buf->readString());
$result->addPlayer('score', $buf->readString());
$result->addPlayer('team', $buf->readString());
}
return $result->fetch();
}
}

View file

@ -1,54 +0,0 @@
/*----------------------------------------------------------------------------------------------------------\
| |
| [ LIVE GAME SERVER LIST ] [ © RICHARD PERRY FROM GREYCUBE.COM ] |
| |
| Released under the terms and conditions of the GNU General Public License Version 3 (http://gnu.org) |
| |
\-----------------------------------------------------------------------------------------------------------*/
function lgsl_query_21(&$server, &$lgsl_need, &$lgsl_fp)
{
//---------------------------------------------------------+
fwrite($lgsl_fp,"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffgief");
$buffer = fread($lgsl_fp, 4096);
$buffer = substr($buffer, 20); // REMOVE HEADER
if (!$buffer) { return FALSE; }
//---------------------------------------------------------+
$server['s']['name'] = lgsl_cut_string($buffer);
$server['s']['map'] = lgsl_cut_string($buffer);
$server['e']['gamemode'] = lgsl_cut_string($buffer);
$server['s']['password'] = lgsl_cut_string($buffer);
$server['e']['progress'] = lgsl_cut_string($buffer)."%";
$server['s']['players'] = lgsl_cut_string($buffer);
$server['s']['playersmax'] = lgsl_cut_string($buffer);
switch ($server['e']['gamemode'])
{
case 0: $server['e']['gamemode'] = "Deathmatch"; break;
case 1: $server['e']['gamemode'] = "Team Deathmatch"; break;
case 2: $server['e']['gamemode'] = "Capture The Flag"; break;
}
//---------------------------------------------------------+
$player_key = 0;
while ($buffer)
{
$server['p'][$player_key]['name'] = lgsl_cut_string($buffer);
$server['p'][$player_key]['score'] = lgsl_cut_string($buffer);
$player_key ++;
}
//---------------------------------------------------------+
return TRUE;
}

View file

@ -1,144 +0,0 @@
LICENSE: The Artistic License 2.0
/*
* qstat.h
* by Steve Jankowski
* steve@qstat.org
* http://www.qstat.org
*
* Copyright 1996,1997,1998,1999,2000,2001,2002 by Steve Jankowski
*/
char tee_serverstatus[14] = { '\x20', '\0', '\0', '\0', '\0', '\0', '\xFF', '\xFF', '\xFF', '\xFF', 'g', 'i', 'e', 'f' };
{
/* Teeworlds */
TEE_SERVER, /* id */
"TEE", /* type_prefix */
"tee", /* type_string */
"-tee", /* type_option */
"Teeworlds", /* game_name */
0, /* master */
35515, /* default_port */
0, /* port_offset */
0, /* flags */
"gametype", /* game_rule */
"TEE", /* template_var */
tee_serverstatus, /* status_packet */
sizeof(tee_serverstatus), /* status_len */
NULL, /* player_packet */
0, /* player_len */
NULL, /* rule_packet */
0, /* rule_len */
NULL, /* master_packet */
0, /* master_len */
NULL, /* master_protocol */
NULL, /* master_query */
display_tee_player_info, /* display_player_func */
display_server_rules, /* display_rule_func */
raw_display_tee_player_info, /* display_raw_player_func */
raw_display_server_rules, /* display_raw_rule_func */
xml_display_tee_player_info, /* display_xml_player_func */
xml_display_server_rules, /* display_xml_rule_func */
send_tee_request_packet, /* status_query_func */
NULL, /* rule_query_func */
NULL, /* player_query_func */
deal_with_tee_packet, /* packet_func */
},
/*
* qstat 2.11
* by Steve Jankowski
*
* Teeworlds protocol
* Copyright 2008 ? Emiliano Leporati
*
* Licensed under the Artistic License, see LICENSE.txt for license terms
*
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "debug.h"
#include "qstat.h"
#include "packet_manip.h"
char tee_serverinfo[8] = { '\xFF', '\xFF', '\xFF', '\xFF', 'i', 'n', 'f', 'o' };
query_status_t send_tee_request_packet( struct qserver *server )
{
return send_packet( server, server->type->status_packet, server->type->status_len );
}
query_status_t deal_with_tee_packet( struct qserver *server, char *rawpkt, int pktlen )
{
// skip unimplemented ack, crc, etc
char *pkt = rawpkt + 6;
char *tok = NULL, *version = NULL;
int i;
struct player* player;
server->ping_total += time_delta(&packet_recv_time, &server->packet_time1);
if (0 == memcmp( pkt, tee_serverinfo, 8))
{
pkt += 8;
// version
version = strdup(pkt); pkt += strlen(pkt) + 1;
// server name
server->server_name = strdup(pkt); pkt += strlen(pkt) + 1;
// map name
server->map_name = strdup(pkt); pkt += strlen(pkt) + 1;
// game type
switch(atoi(pkt)) {
case 0:
add_rule( server, server->type->game_rule, "dm", NO_FLAGS);
break;
case 1:
add_rule( server, server->type->game_rule, "tdm", NO_FLAGS);
break;
case 2:
add_rule( server, server->type->game_rule, "ctf", NO_FLAGS);
break;
default:
add_rule( server, server->type->game_rule, "unknown", NO_FLAGS);
break;
}
pkt += strlen(pkt) + 1;
pkt += strlen(pkt) + 1;
pkt += strlen(pkt) + 1;
// num players
server->num_players = atoi(pkt); pkt += strlen(pkt) + 1;
// max players
server->max_players = atoi(pkt); pkt += strlen(pkt) + 1;
// players
for(i = 0; i < server->num_players; i++)
{
player = add_player( server, i );
player->name = strdup(pkt); pkt += strlen(pkt) + 1;
player->score = atoi(pkt); pkt += strlen(pkt) + 1;
}
// version reprise
server->protocol_version = 0;
if (NULL == (tok = strtok(version, "."))) return -1;
server->protocol_version |= (atoi(tok) & 0x000F) << 12;
if (NULL == (tok = strtok(NULL, "."))) return -1;
server->protocol_version |= (atoi(tok) & 0x000F) << 8;
if (NULL == (tok = strtok(NULL, "."))) return -1;
server->protocol_version |= (atoi(tok) & 0x00FF);
free(version);
return DONE_FORCE;
}
// unknown packet type
return PKT_ERROR;
}

View file

@ -1,104 +0,0 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* $Id: tribes2.php,v 1.1 2007/07/07 14:52:01 tombuskens Exp $
*/
[tribes2]
info = "\x0E\x02\x01\x02\x03\x04"
status = "\x12\x02\x01\x02\x03\x04"
require_once GAMEQ_BASE . 'Protocol.php';
/**
* Tribes 2 protocol
*
* @author Tom Buskens <t.buskens@deviation.nl>
* @version $Revision: 1.1 $
*/
class GameQ_Protocol_tribes2 extends GameQ_Protocol
{
public function info()
{
// Header
$this->p->skip(6);
$this->r->add('version', $this->p->readPascalString());
// TODO: Protocol and build numbers
$this->p->skip(12);
$this->r->add('hostname', $this->p->readPascalString());
}
public function status()
{
// Header
$this->p->skip(6);
// Vars
$this->r->add('mod', $this->p->readPascalString());
$this->r->add('gametype', $this->p->readPascalString());
$this->r->add('map', $this->p->readPascalString());
$this->readBitflag($this->p->read());
$this->r->add('num_players', $this->p->readInt8());
$this->r->add('max_players', $this->p->readInt8());
$this->r->add('num_bots', $this->p->readInt8());
$this->r->add('cpu', $this->p->readInt16());
$this->r->add('info', $this->p->readPascalString());
$this->p->skip(2);
$this->teams();
$this->players();
}
private function teams()
{
$num_teams = $this->p->read();
$this->r->add('num_teams', $num_teams);
$this->p->skip();
for ($i = 0; $i < $num_teams; $i++) {
$this->r->addTeam('name', $this->p->readString("\x09"));
$this->r->addTeam('score', $this->p->readString("\x0a"));
}
}
private function players()
{
// TODO
}
private function readBitflag($flag)
{
$vars = array('dedicated', 'password', 'linux',
'tournament', 'no_alias');
$bit = 1;
foreach ($vars as $var) {
$value = ($flag & $bit) ? 1 : 0;
$this->r->add($var, $value);
$bit *= 2;
}
}
}
?>

View file

@ -1,72 +0,0 @@
/*----------------------------------------------------------------------------------------------------------\
| |
| [ LIVE GAME SERVER LIST ] [ © RICHARD PERRY FROM GREYCUBE.COM ] |
| |
| Released under the terms and conditions of the GNU General Public License Version 3 (http://gnu.org) |
| |
\-----------------------------------------------------------------------------------------------------------*/
function lgsl_query_25(&$server, &$lgsl_need, &$lgsl_fp)
{
//---------------------------------------------------------+
// REFERENCE: http://www.tribesnext.com
fwrite($lgsl_fp,"\x12\x02\x21\x21\x21\x21");
$buffer = fread($lgsl_fp, 4096);
if (!$buffer) { return FALSE; }
$buffer = substr($buffer, 6); // REMOVE HEADER
//---------------------------------------------------------+
$server['s']['game'] = lgsl_cut_pascal($buffer);
$server['e']['gamemode'] = lgsl_cut_pascal($buffer);
$server['s']['map'] = lgsl_cut_pascal($buffer);
$server['e']['bit_flags'] = ord(lgsl_cut_byte($buffer, 1));
$server['s']['players'] = ord(lgsl_cut_byte($buffer, 1));
$server['s']['playersmax'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['bots'] = ord(lgsl_cut_byte($buffer, 1));
$server['e']['cpu'] = lgsl_unpack(lgsl_cut_byte($buffer, 2), "S");
$server['e']['motd'] = lgsl_cut_pascal($buffer);
$server['e']['unknown'] = lgsl_unpack(lgsl_cut_byte($buffer, 2), "S");
$server['e']['dedicated'] = ($server['e']['bit_flags'] & 1) ? "1" : "0";
$server['s']['password'] = ($server['e']['bit_flags'] & 2) ? "1" : "0";
$server['e']['os'] = ($server['e']['bit_flags'] & 4) ? "L" : "W";
$server['e']['tournament'] = ($server['e']['bit_flags'] & 8) ? "1" : "0";
$server['e']['no_alias'] = ($server['e']['bit_flags'] & 16) ? "1" : "0";
unset($server['e']['bit_flags']);
//---------------------------------------------------------+
$team_total = lgsl_cut_string($buffer, 0, "\x0A");
for ($i=0; $i<$team_total; $i++)
{
$server['t'][$i]['name'] = lgsl_cut_string($buffer, 0, "\x09");
$server['t'][$i]['score'] = lgsl_cut_string($buffer, 0, "\x0A");
}
$player_total = lgsl_cut_string($buffer, 0, "\x0A");
for ($i=0; $i<$player_total; $i++)
{
lgsl_cut_byte($buffer, 1); // ? 16
lgsl_cut_byte($buffer, 1); // ? 8 or 14 = BOT / 12 = ALIAS / 11 = NORMAL
if (ord($buffer[0]) < 32) { lgsl_cut_byte($buffer, 1); } // ? 8 PREFIXES SOME NAMES
$server['p'][$i]['name'] = lgsl_cut_string($buffer, 0, "\x11");
lgsl_cut_string($buffer, 0, "\x09"); // ALWAYS BLANK
$server['p'][$i]['team'] = lgsl_cut_string($buffer, 0, "\x09");
$server['p'][$i]['score'] = lgsl_cut_string($buffer, 0, "\x0A");
}
//---------------------------------------------------------+
return TRUE;
}

View file

@ -1,455 +0,0 @@
LICENSE: The Artistic License 2.0
/*
* qstat.h
* by Steve Jankowski
* steve@qstat.org
* http://www.qstat.org
*
* Copyright 1996,1997,1998,1999,2000,2001,2002 by Steve Jankowski
*/
/* TRIBES 2 */
#define TRIBES2_QUERY_GAME_TYPES 2
#define TRIBES2_QUERY_MASTER 6
#define TRIBES2_QUERY_PING 14
#define TRIBES2_QUERY_INFO 18
#define TRIBES2_RESPONSE_GAME_TYPES 4
#define TRIBES2_RESPONSE_MASTER 8
#define TRIBES2_RESPONSE_PING 16
#define TRIBES2_RESPONSE_INFO 20
#define TRIBES2_NO_COMPRESS 2
#define TRIBES2_DEFAULT_PACKET_INDEX 255
#define TRIBES2_STATUS_DEDICATED (1<<0)
#define TRIBES2_STATUS_PASSWORD (1<<1)
#define TRIBES2_STATUS_LINUX (1<<2)
#define TRIBES2_STATUS_TOURNAMENT (1<<3)
#define TRIBES2_STATUS_NOALIAS (1<<4)
#define TRIBES2_STATUS_TEAMDAMAGE (1<<5)
#define TRIBES2_STATUS_TOURNAMENT_VER3 (1<<6)
#define TRIBES2_STATUS_NOALIAS_VER3 (1<<7)
char tribes2_game_types_request[] = { TRIBES2_QUERY_GAME_TYPES, 0, 1,2,3,4 };
char tribes2_ping[] = { TRIBES2_QUERY_PING, TRIBES2_NO_COMPRESS, 1,2,3,4 };
char tribes2_info[] = { TRIBES2_QUERY_INFO, TRIBES2_NO_COMPRESS, 1,2,3,4 };
unsigned char tribes2_masterquery[] = {
TRIBES2_QUERY_MASTER, 128, /* <= build 22228, this was 0 */
11,12,13,14,
255,
3, 'a', 'n', 'y',
3, 'a', 'n', 'y',
0, 255, /* min/max players */
0xff, 0xff, 0xff, 0xff, /* region mask */
0, 0, 0, 0, /* build version */
0, /* status */
255, /* max bots */
0, 0, /* min cpu */
0 /* # buddies */
};
#define TRIBES2_ID_OFFSET 2
{
/* TRIBES 2 */
TRIBES2_SERVER, /* id */
"T2S", /* type_prefix */
"t2s", /* type_string */
"-t2s", /* type_option */
"Tribes 2", /* game_name */
0, /* master */
TRIBES2_DEFAULT_PORT, /* default_port */
0, /* port_offset */
0, /* flags */
"game", /* game_rule */
"TRIBES2", /* template_var */
(char*) &tribes2_ping, /* status_packet */
sizeof( tribes2_ping), /* status_len */
(char*) &tribes2_info, /* player_packet */
sizeof( tribes2_info), /* player_len */
(char*) NULL, /* rule_packet */
0, /* rule_len */
NULL, /* master_packet */
0, /* master_len */
NULL, /* master_protocol */
NULL, /* master_query */
display_tribes2_player_info, /* display_player_func */
display_server_rules, /* display_rule_func */
raw_display_tribes2_player_info, /* display_raw_player_func */
raw_display_server_rules, /* display_raw_rule_func */
xml_display_tribes2_player_info, /* display_xml_player_func */
xml_display_server_rules, /* display_xml_rule_func */
send_tribes2_request_packet, /* status_query_func */
NULL, /* rule_query_func */
NULL, /* player_query_func */
deal_with_tribes2_packet, /* packet_func */
},
query_status_t send_tribes2_request_packet(struct qserver *server)
{
int rc;
if (server->flags &FLAG_BROADCAST && server->server_name == NULL)
{
rc = send_broadcast(server, server->type->status_packet, server->type->status_len);
}
else if (server->server_name == NULL)
{
rc = send(server->fd, server->type->status_packet, server->type->status_len, 0);
}
else
{
rc = send(server->fd, server->type->player_packet, server->type->player_len, 0);
}
if (rc == SOCKET_ERROR)
{
return send_error( server, rc );
}
register_send(server);
return rc;
}
void get_tribes2_player_type(struct player *player)
{
char *name = player->name;
for (; *name; name++)
{
switch (*name)
{
case 0x8:
player->type_flag = PLAYER_TYPE_NORMAL;
continue;
case 0xc:
player->type_flag = PLAYER_TYPE_ALIAS;
continue;
case 0xe:
player->type_flag = PLAYER_TYPE_BOT;
continue;
case 0xb:
break;
default:
continue;
}
name++;
if (isprint(*name))
{
char *n = name;
for (; isprint(*n); n++)
;
player->tribe_tag = strndup(name, n - name);
name = n;
}
if (! *name)
{
break;
}
}
}
query_status_t deal_with_tribes2_packet(struct qserver *server, char *pkt, int pktlen)
{
char str[256], *pktstart = pkt, *term, *start;
unsigned int minimum_net_protocol, build_version, i, t, len, s, status;
unsigned int net_protocol;
unsigned short cpu_speed;
int n_teams = 0, n_players;
struct player **teams = NULL, *player;
struct player **last_player = &server->players;
int query_version;
debug( 2, "deal_with_tribes2_packet %p, %d", server, pktlen );
pkt[pktlen] = '\0';
if (server->server_name == NULL)
{
server->ping_total += time_delta(&packet_recv_time, &server->packet_time1);
}
/*
else
gettimeofday( &server->packet_time1, NULL);
*/
if (pkt[0] == TRIBES2_RESPONSE_PING)
{
if (pkt[6] < 4 || pkt[6] > 12 || strncmp(pkt + 7, "VER", 3) != 0)
{
return PKT_ERROR;
}
strncpy(str, pkt + 10, pkt[6] - 3);
str[pkt[6] - 3] = '\0';
query_version = atoi(str);
add_nrule(server, "queryversion", pkt + 7, pkt[6]);
pkt += 7+pkt[6];
server->protocol_version = query_version;
if (query_version != 3 && query_version != 5)
{
server->server_name = strdup("Unknown query version");
return PKT_ERROR;
}
if (query_version == 5)
{
net_protocol = swap_long_from_little(pkt);
sprintf(str, "%u", net_protocol);
add_rule(server, "net_protocol", str, NO_FLAGS);
pkt += 4;
}
minimum_net_protocol = swap_long_from_little(pkt);
sprintf(str, "%u", minimum_net_protocol);
add_rule(server, "minimum_net_protocol", str, NO_FLAGS);
pkt += 4;
build_version = swap_long_from_little(pkt);
sprintf(str, "%u", build_version);
add_rule(server, "build_version", str, NO_FLAGS);
pkt += 4;
server->server_name = strndup(pkt + 1, *(unsigned char*)(pkt));
/* Always send the player request because the ping packet
* contains very little information */
send_player_request_packet(server);
return 0;
}
else if (pkt[0] != TRIBES2_RESPONSE_INFO)
{
return PKT_ERROR;
}
pkt += 6;
for (i = 0; i < *(unsigned char*)pkt; i++)
if (!isprint(pkt[i + 1]))
{
return PKT_ERROR;
}
add_nrule(server, server->type->game_rule, pkt + 1, *(unsigned char*)pkt);
server->game = strndup(pkt + 1, *(unsigned char*)pkt);
pkt += *pkt + 1;
add_nrule(server, "mission", pkt + 1, *(unsigned char*)pkt);
pkt += *pkt + 1;
server->map_name = strndup(pkt + 1, *(unsigned char*)pkt);
pkt += *pkt + 1;
status = *(unsigned char*)pkt;
sprintf(str, "%u", status);
add_rule(server, "status", str, NO_FLAGS);
if (status &TRIBES2_STATUS_DEDICATED)
{
add_rule(server, "dedicated", "1", NO_FLAGS);
}
if (status &TRIBES2_STATUS_PASSWORD)
{
add_rule(server, "password", "1", NO_FLAGS);
}
if (status &TRIBES2_STATUS_LINUX)
{
add_rule(server, "linux", "1", NO_FLAGS);
}
if (status &TRIBES2_STATUS_TEAMDAMAGE)
{
add_rule(server, "teamdamage", "1", NO_FLAGS);
}
if (server->protocol_version == 3)
{
if (status &TRIBES2_STATUS_TOURNAMENT_VER3)
{
add_rule(server, "tournament", "1", NO_FLAGS);
}
if (status &TRIBES2_STATUS_NOALIAS_VER3)
{
add_rule(server, "no_aliases", "1", NO_FLAGS);
}
}
else
{
if (status &TRIBES2_STATUS_TOURNAMENT)
{
add_rule(server, "tournament", "1", NO_FLAGS);
}
if (status &TRIBES2_STATUS_NOALIAS)
{
add_rule(server, "no_aliases", "1", NO_FLAGS);
}
}
pkt++;
server->num_players = *(unsigned char*)pkt;
pkt++;
server->max_players = *(unsigned char*)pkt;
pkt++;
sprintf(str, "%u", *(unsigned char*)pkt);
add_rule(server, "bot_count", str, NO_FLAGS);
pkt++;
cpu_speed = swap_short_from_little(pkt);
sprintf(str, "%hu", cpu_speed);
add_rule(server, "cpu_speed", str, NO_FLAGS);
pkt += 2;
if (strcmp(server->server_name, "VER3") == 0)
{
free(server->server_name);
server->server_name = strndup(pkt + 1, *(unsigned char*)pkt);
}
else
{
add_nrule(server, "info", pkt + 1, *(unsigned char*)pkt);
}
pkt += *(unsigned char*)pkt + 1;
len = swap_short_from_little(pkt);
pkt += 2;
start = pkt;
if (len + (pkt - pktstart) > pktlen)
{
len -= (len + (pkt - pktstart)) - pktlen;
}
if (len == 0 || pkt - pktstart >= pktlen)
{
goto info_done;
}
term = strchr(pkt, 0xa);
if (!term)
{
goto info_done;
}
*term = '\0';
n_teams = atoi(pkt);
sprintf(str, "%d", n_teams);
add_rule(server, "numteams", str, NO_FLAGS);
pkt = term + 1;
if (pkt - pktstart >= pktlen)
{
goto info_done;
}
teams = (struct player **)calloc(1, sizeof(struct player*) * n_teams);
for (t = 0; t < n_teams; t++)
{
teams[t] = (struct player*)calloc(1, sizeof(struct player));
teams[t]->number = TRIBES_TEAM;
teams[t]->team = t;
/* team name */
term = strchr(pkt, 0x9);
if (!term)
{
n_teams = t;
goto info_done;
} teams[t]->name = strndup(pkt, term - pkt);
pkt = term + 1;
term = strchr(pkt, 0xa);
if (!term)
{
n_teams = t;
goto info_done;
}
*term = '\0';
teams[t]->frags = atoi(pkt);
pkt = term + 1;
if (pkt - pktstart >= pktlen)
{
goto info_done;
}
}
term = strchr(pkt, 0xa);
if (!term || term - start >= len)
{
goto info_done;
}
*term = '\0';
n_players = atoi(pkt);
pkt = term + 1;
for (i = 0; i < n_players && pkt - start < len; i++)
{
pkt++; /* skip first byte (0x10) */
if (pkt - start >= len)
{
break;
}
player = (struct player*)calloc(1, sizeof(struct player));
term = strchr(pkt, 0x11);
if (!term || term - start >= len)
{
free(player);
break;
} player->name = strndup(pkt, term - pkt);
get_tribes2_player_type(player);
pkt = term + 1;
pkt++; /* skip 0x9 */
if (pkt - start >= len)
{
break;
}
term = strchr(pkt, 0x9);
if (!term || term - start >= len)
{
free(player->name);
free(player);
break;
}
for (t = 0; t < n_teams; t++)
{
if (term - pkt == strlen(teams[t]->name) && strncmp(pkt, teams[t]->name, term - pkt) == 0)
{
break;
}
}
if (t == n_teams)
{
player->team = - 1;
player->team_name = "Unassigned";
}
else
{
player->team = t;
player->team_name = teams[t]->name;
}
player->flags |= PLAYER_FLAG_DO_NOT_FREE_TEAM;
pkt = term + 1;
for (s = 0; *pkt != 0xa && pkt - start < len; pkt++)
{
str[s++] = *pkt;
}
str[s] = '\0';
player->frags = atoi(str);
if (*pkt == 0xa)
{
pkt++;
}
*last_player = player;
last_player = &player->next;
}
info_done:
for (t = n_teams; t;)
{
t--;
teams[t]->next = server->players;
server->players = teams[t];
}
if (teams)
{
free(teams);
}
return DONE_FORCE;
}

View file

@ -1,241 +0,0 @@
LICENSE: The Artistic License 2.0
/*
* qstat.h
* by Steve Jankowski
* steve@qstat.org
* http://www.qstat.org
*
* Copyright 1996,1997,1998,1999,2000,2001,2002 by Steve Jankowski
*/
{
/* World in Confict PROTOCOL */
WIC_PROTOCOL_SERVER, /* id */
"WICS", /* type_prefix */
"wics", /* type_string */
"-wics", /* type_option */
"World in Conflict", /* game_name */
0, /* master */
0, /* default_port */
0, /* port_offset */
TF_TCP_CONNECT|TF_QUERY_ARG_REQUIRED|TF_QUERY_ARG, /* flags */
"N/A", /* game_rule */
"WICPROTOCOL", /* template_var */
NULL, /* status_packet */
0, /* status_len */
NULL, /* player_packet */
0, /* player_len */
NULL, /* rule_packet */
0, /* rule_len */
NULL, /* master_packet */
0, /* master_len */
NULL, /* master_protocol */
NULL, /* master_query */
display_wic_player_info, /* display_player_func */
display_server_rules, /* display_rule_func */
raw_display_wic_player_info, /* display_raw_player_func */
raw_display_server_rules, /* display_raw_rule_func */
xml_display_wic_player_info, /* display_xml_player_func */
xml_display_server_rules, /* display_xml_rule_func */
send_wic_request_packet, /* status_query_func */
NULL, /* rule_query_func */
NULL, /* player_query_func */
deal_with_wic_packet, /* packet_func */
},
/*
* qstat 2.8
* by Steve Jankowski
*
* World in Conflict Protocol
* Copyright 2007 Steven Hartland
*
* Licensed under the Artistic License, see LICENSE.txt for license terms
*
*/
#include <sys/types.h>
#ifndef _WIN32
#include <sys/socket.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include "debug.h"
#include "qstat.h"
#include "packet_manip.h"
query_status_t send_wic_request_packet( struct qserver *server )
{
char buf[256];
int serverport = get_param_i_value( server, "port", 0 );
char *password = get_param_value( server, "password", "N/A" );
change_server_port( server, serverport, 1 );
if ( get_player_info )
{
server->flags |= TF_PLAYER_QUERY|TF_RULES_QUERY;
sprintf( buf, "%s\x0d\x0a/listsettings\x0d\x0a/listplayers\x0d\x0a/exit\x0d\x0a", password );
server->saved_data.pkt_index = 2;
}
else
{
server->flags |= TF_STATUS_QUERY;
sprintf( buf, "%s\x0d\x0a/listsettings\x0d\x0a/exit\x0d\x0a", password );
server->saved_data.pkt_index = 1;
}
return send_packet( server, buf, strlen( buf ) );
}
query_status_t deal_with_wic_packet( struct qserver *server, char *rawpkt, int pktlen )
{
char *s, *end, *team = NULL;
int mode = server->n_servers, slot, score;
char name[256], role[256];
debug( 2, "processing n_requests %d, retry1 %d, n_retries %d, delta %d", server->n_requests, server->retry1, n_retries, time_delta( &packet_recv_time, &server->packet_time1 ) );
server->ping_total += time_delta( &packet_recv_time, &server->packet_time1 );
server->n_requests++;
if ( 0 == pktlen )
{
// Invalid password
return REQ_ERROR;
}
gettimeofday( &server->packet_time1, NULL);
rawpkt[pktlen]= '\0';
end = &rawpkt[pktlen];
s = rawpkt;
while ( NULL != s )
{
int len = strlen( s );
*(s + len - 2) = '\0'; // strip off \x0D\x0A
debug( 2, "Line[%d]: %s", mode, s );
if ( 0 == mode )
{
// Settings
// TODO: make parse safe
if ( 0 == strncmp( s, "Settings: ", 9 ) )
{
// Server Rule
char *key = s + 10;
char *value = strchr( key, ' ' );
*value = '\0';
value++;
debug( 2, "key: '%s' = '%s'", key, value );
if ( 0 == strcmp( "myGameName", key ) )
{
server->server_name = strdup( value );
}
else if ( 0 == strcmp( "myMapFilename", key ) )
{
server->map_name = strdup( value );
}
else if ( 0 == strcmp( "myMaxPlayers", key ) )
{
server->max_players = atoi( value );
}
else if ( 0 == strcmp( "myCurrentNumberOfPlayers", key ) )
{
server->num_players = atoi( value);
}
else
{
add_rule( server, key, value, NO_FLAGS );
}
}
else if ( 0 == strcmp( "Listing players", s ) )
{
// end of rules request
server->saved_data.pkt_index--;
mode++;
}
else if ( 0 == strcmp( "Exit confirmed.", s ) )
{
server->n_servers = mode;
return DONE_FORCE;
}
}
else if ( 1 == mode )
{
// Player info
if ( 0 == strncmp( s, "Team: ", 6 ) )
{
team = s + 6;
debug( 2, "Team: %s", team );
}
else if ( 4 == sscanf( s, "Slot: %d Role: %s Score: %d Name: %255[^\x0d\x0a]", &slot, role, &score, name ) )
{
// Player info
struct player *player = add_player( server, server->n_player_info );
if ( NULL != player )
{
player->flags |= PLAYER_FLAG_DO_NOT_FREE_TEAM;
player->name = strdup( name );
player->score = score;
player->team_name = team;
player->tribe_tag = strdup( role );
// Indicate if its a bot
player->type_flag = ( 0 == strcmp( name, "Computer: Balanced" ) ) ? 1 : 0;
}
debug( 2, "player %d, role %s, score %d, name %s", slot, role, score, name );
}
else if ( 3 == sscanf( s, "Slot: %d Role: Score: %d Name: %255[^\x0d\x0a]", &slot, &score, name ) )
{
// Player info
struct player *player = add_player( server, server->n_player_info );
if ( NULL != player )
{
player->flags |= PLAYER_FLAG_DO_NOT_FREE_TEAM;
player->name = strdup( name );
player->score = score;
player->team_name = team;
// Indicate if its a bot
player->type_flag = ( 0 == strcmp( name, "Computer: Balanced" ) ) ? 1 : 0;
}
debug( 2, "player %d, score %d, name %s", slot, score, name );
}
else if ( 0 == strcmp( "Exit confirmed.", s ) )
{
server->n_servers = mode;
return DONE_FORCE;
}
}
s += len;
if ( s + 1 < end )
{
s++; // next line
}
else
{
s = NULL;
}
}
server->n_servers = mode;
if ( 0 == server->saved_data.pkt_index )
{
server->map_name = strdup( "N/A" );
return DONE_FORCE;
}
return INPROGRESS;
}