node-gamedig/reference/descent3/qstat.txt
2014-10-29 02:02:03 -05:00

223 lines
6.8 KiB
Text

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;
}