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

