⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 anongame.c

📁 打魔兽战网的都知道他是什么
💻 C
📖 第 1 页 / 共 5 页
字号:
		else if (level[i * 4 + 3] >= level[i * 4 + 2] && level[i * 4 + 2] >= level[i * 4 + 1] && level[i * 4 + 1] >= level[i * 4]) {		    ;		/* nothing to do */		}	    }			/* end 4 teams */	}			/* end ppt loop */    }				/* end "if" statement */    return 0;}static int _anongame_match(t_connection * c, int queue){    int level = _anongame_level_by_queue(c, queue);    int delta = 0;    int i;    t_matchdata *md;    t_elem *curr;    int diff;    t_anongame *a = conn_get_anongame(c);    t_uint32 cur_prefs = a->map_prefs;    t_connection *inv_c[ANONGAME_MAX_TEAMS];    int maxlevel, minlevel;    int teams = 0;    players[queue] = 0;    eventlog(eventlog_level_trace, __FUNCTION__, "[%d] matching started for level %d player in queue %d", conn_get_socket(c), level, queue);    diff = war3_get_maxleveldiff();    maxlevel = level + diff;    minlevel = (level - diff < 0) ? 0 : level - diff;    while (abs(delta) < (diff + 1)) {	if ((level + delta <= maxlevel) && (level + delta >= minlevel)) {	    eventlog(eventlog_level_trace, __FUNCTION__, "Traversing level %d players", level + delta);	    LIST_TRAVERSE(matchlists[queue][level + delta], curr) {		md = elem_get_data(curr);		if (md->versiontag && _conn_get_versiontag(c) && !strcmp(md->versiontag, _conn_get_versiontag(c)) && (cur_prefs & md->map_prefs)) {		    /* set maxlevel and minlevel to keep all players within 6 levels */		    maxlevel = (level + delta + diff < maxlevel) ? level + delta + diff : maxlevel;		    minlevel = (level + delta - diff > minlevel) ? level + delta - diff : minlevel;		    cur_prefs &= md->map_prefs;		    /* AT match */		    if (anongame_arranged(queue)) {			/* set the inv_c for unqueueing later */			inv_c[teams] = md->c;			a = conn_get_anongame(md->c);			/* add all the players on the team to player[][] */			for (i = 0; i < _anongame_totalplayers(queue) / _anongame_totalteams(queue); i++) {			    player[queue][teams + i * _anongame_totalteams(queue)] = a->tc[i];			    players[queue]++;			}			teams++;			/* check for enough players */			if (players[queue] == _anongame_totalplayers(queue)) {			    /* unqueue just the single team entry */			    for (i = 0; i < teams; i++)				anongame_unqueue(inv_c[i], queue);			    mapname = _get_map_from_prefs(queue, cur_prefs, conn_get_clienttag(c));			    return 0;			}			/* PG match */		    } else {			player[queue][players[queue]++] = md->c;			if (players[queue] == _anongame_totalplayers(queue)) {			    /* first sort queue by level */			    qsort(player[queue], players[queue], sizeof(t_connection *), _anongame_compare_level);			    /* next call reodering function */			    _anongame_order_queue(queue);			    /* unqueue players */			    for (i = 0; i < players[queue]; i++)				anongame_unqueue(player[queue][i], queue);			    mapname = _get_map_from_prefs(queue, cur_prefs, conn_get_clienttag(c));			    return 0;			}		    }		}	    }	}	if (delta <= 0 || level - delta < 0)	    delta = abs(delta) + 1;	else	    delta = -delta;	if (level + delta > MAX_LEVEL)	    delta = -delta;	if (level + delta < 0)	    break;		/* cant really happen */    }    eventlog(eventlog_level_trace, __FUNCTION__, "[%d] Matching finished, not enough players (found %d)", conn_get_socket(c), players[queue]);    mapname = NULL;    return 0;}static int w3routeip = -1;	/* changed by dizzy to show the w3routeshow addr if available */static unsigned short w3routeport = BNETD_W3ROUTE_PORT;static int _anongame_search_found(int queue){    t_packet *rpacket;    t_anongameinfo *info;    t_anongame *a;    int i, j;    t_saf_pt2 *pt2;    /* FIXME: maybe periodically lookup w3routeaddr to support dynamic ips?     * (or should dns lookup be even quick enough to do it everytime?)     */    if (w3routeip == -1) {	t_addr *routeraddr;	routeraddr = addr_create_str(prefs_get_w3route_addr(), 0, BNETD_W3ROUTE_PORT);	if (!routeraddr) {	    eventlog(eventlog_level_error, __FUNCTION__, "error getting w3route_addr");	    return -1;	}	w3routeip = addr_get_ip(routeraddr);	w3routeport = addr_get_port(routeraddr);	addr_destroy(routeraddr);    }    info = anongameinfo_create(_anongame_totalplayers(queue));    if (!info) {	eventlog(eventlog_level_error, __FUNCTION__, "anongameinfo_create failed");	return -1;    }    /* create data to be appended to end of packet */    pt2 = xmalloc(sizeof(t_saf_pt2));    bn_int_set(&pt2->unknown1, 0xFFFFFFFF);    bn_int_set(&pt2->anongame_string, _anongame_get_gametype_tab(queue));    bn_byte_set(&pt2->totalplayers, _anongame_totalplayers(queue));    bn_byte_set(&pt2->totalteams, _anongame_totalteams(queue));	/* 1v1 & sffa are set to zero in _anongame_totalteams() */    bn_short_set(&pt2->unknown2, 0);    bn_byte_set(&pt2->visibility, 2);	/* visibility. 0x01 - dark 0x02 - default */    bn_byte_set(&pt2->unknown3, 2);    /* send found packet to each of the players */    for (i = 0; i < players[queue]; i++) {	if (!(a = conn_get_anongame(player[queue][i]))) {	    eventlog(eventlog_level_error, __FUNCTION__, "no anongame struct for queued player");	    xfree(pt2);	    return -1;	}	a->info = info;	a->playernum = i + 1;	for (j = 0; j < players[queue]; j++) {	    a->info->player[j] = player[queue][j];	    a->info->account[j] = conn_get_account(player[queue][j]);	}	if (!(rpacket = packet_create(packet_class_bnet))) {	    xfree(pt2);	    return -1;	}	packet_set_size(rpacket, sizeof(t_server_anongame_found));	packet_set_type(rpacket, SERVER_ANONGAME_FOUND);	bn_byte_set(&rpacket->u.server_anongame_found.option, 1);	bn_int_set(&rpacket->u.server_anongame_found.count, a->count);	bn_int_set(&rpacket->u.server_anongame_found.unknown1, 0);	{			/* trans support */	    unsigned int w3ip = w3routeip;	    unsigned short w3port = w3routeport;	    trans_net(conn_get_addr(player[queue][i]), &w3ip, &w3port);	    /* if ip to send is 0.0.0.0 (which will not work anyway) try 	     * to guess the reachable IP of pvpgn by using the local 	     * endpoing address of the bnet class connection */	    if (!w3ip)		w3ip = conn_get_real_local_addr(player[queue][i]);	    bn_int_nset(&rpacket->u.server_anongame_found.ip, w3ip);	    bn_short_set(&rpacket->u.server_anongame_found.port, w3port);	}	bn_byte_set(&rpacket->u.server_anongame_found.unknown2, i + 1);	bn_byte_set(&rpacket->u.server_anongame_found.unknown3, queue);	bn_short_set(&rpacket->u.server_anongame_found.unknown4, 0);	bn_int_set(&rpacket->u.server_anongame_found.id, 0xdeadbeef);	bn_byte_set(&rpacket->u.server_anongame_found.unknown5, 6);	bn_byte_set(&rpacket->u.server_anongame_found.type, a->type);	bn_byte_set(&rpacket->u.server_anongame_found.gametype, a->gametype);	packet_append_string(rpacket, mapname);	packet_append_data(rpacket, pt2, sizeof(t_saf_pt2));	conn_push_outqueue(player[queue][i], rpacket);	packet_del_ref(rpacket);    }    /* clear queue */    players[queue] = 0;    xfree(pt2);    return 0;}/**********************************************************************************//* external functions *//**********************************************************************************/extern int anongame_matchlists_create(){    int i, j;    for (i = 0; i < ANONGAME_TYPES; i++) {	for (j = 0; j < MAX_LEVEL; j++) {	    matchlists[i][j] = NULL;	}    }    return 0;}extern int anongame_matchlists_destroy(){    int i, j;    for (i = 0; i < ANONGAME_TYPES; i++) {	for (j = 0; j < MAX_LEVEL; j++) {	    if (matchlists[i][j]) {		list_destroy(matchlists[i][j]);	    }	}    }    return 0;}/**********/extern int handle_anongame_search(t_connection * c, t_packet const *packet){    return _handle_anongame_search(c, packet);}extern int anongame_unqueue(t_connection * c, int queue){    int i;    t_elem *curr;    t_matchdata *md;    if (queue < 0) {	eventlog(eventlog_level_error, __FUNCTION__, "got negative queue id (%d)", queue);	return -1;    }    if (queue >= ANONGAME_TYPES) {	eventlog(eventlog_level_error, __FUNCTION__, "unknown queue: %d", queue);	return -1;    }    if (conn_get_anongame_search_starttime(c) != ((time_t) 0)) {	average_anongame_search_time *= anongame_search_count;	average_anongame_search_time += (long) difftime(time(NULL), conn_get_anongame_search_starttime(c));	anongame_search_count++;	average_anongame_search_time /= anongame_search_count;	if (anongame_search_count > 20000)	    anongame_search_count = anongame_search_count / 2;	/* to prevent an overflow of the average time */	conn_set_anongame_search_starttime(c, ((time_t) 0));    }    for (i = 0; i < MAX_LEVEL; i++) {	if (matchlists[queue][i] == NULL)	    continue;	LIST_TRAVERSE(matchlists[queue][i], curr) {	    md = elem_get_data(curr);	    if (md->c == c) {		eventlog(eventlog_level_trace, __FUNCTION__, "unqueued player [%d] level %d", conn_get_socket(c), i);		list_remove_elem(matchlists[queue][i], &curr);		xfree(md);		return 0;	    }	}    }    /* Output error to log for PG queues, AT players are queued with single     * entry. Because anongame_unqueue() is called for each player, only the first     * time called will the team be removed, the rest are therefore not an error.     * [Omega]     */    if (anongame_arranged(queue) == 0) {	eventlog(eventlog_level_trace, __FUNCTION__, "[%d] player not found in \"%s\" queue", conn_get_socket(c), _anongame_queue_to_string(queue));	return -1;    }    return 0;}/**********/extern char anongame_arranged(int queue){    switch (queue) {	case ANONGAME_TYPE_AT_2V2:	case ANONGAME_TYPE_AT_3V3:	case ANONGAME_TYPE_AT_4V4:	case ANONGAME_TYPE_AT_2V2V2:	    return 1;	case ANONGAME_TYPE_TY:	    return tournament_is_arranged();	default:	    return 0;    }}extern int anongame_evaluate_results(t_anongame * anongame){    int i, j, number;    int wins[ANONGAME_MAX_GAMECOUNT];    int losses[ANONGAME_MAX_GAMECOUNT];    int result;    t_anongame_gameresult *results;    t_anongameinfo *anoninfo = anongame->info;    for (i = 0; i < ANONGAME_MAX_GAMECOUNT; i++) {	wins[i] = 0;	losses[i] = 0;    }    for (i = 0; i < anongame_get_totalplayers(anongame); i++) {	if ((results = anoninfo->results[i])) {	    for (j = 0; j < gameresult_get_number_of_results(results); j++) {		number = gameresult_get_player_number(results, j) - 1;		result = gameresult_get_player_result(results, j);		if ((result == W3_GAMERESULT_WIN))		    wins[number]++;		if ((result == W3_GAMERESULT_LOSS))		    losses[number]++;	    }	}    }    for (i = 0; i < anongame_get_totalplayers(anongame); i++) {	if ((wins[i] > losses[i])) {	    if ((anoninfo->result[i] != W3_GAMERESULT_WIN)) {		eventlog(eventlog_level_trace, __FUNCTION__, "player %d reported DISC/LOSS for self, but others agree on WIN", i + 1);		anoninfo->result[i] = W3_GAMERESULT_WIN;	    }	} else {	    if ((anoninfo->result[i] != W3_GAMERESULT_LOSS)) {		eventlog(eventlog_level_trace, __FUNCTION__, "player %d reported DISC/WIN for self, but others agree on LOSS", i + 1);		anoninfo->result[i] = W3_GAMERESULT_LOSS;	    }	}    }    return 0;}extern int anongame_stats(t_connection * c){    int i;    int wins = 0, losses = 0, discs = 0;    t_connection *gamec = conn_get_routeconn(c);    t_anongame *a = conn_get_anongame(gamec);    int tp = anongame_get_totalplayers(a);    int oppon_level[ANONGAME_MAX_GAMECOUNT];    t_uint8 gametype = a->queue;    t_uint8 plnum = a->playernum;    t_clienttag ct = conn_get_clienttag(c);    int tt = _anongame_totalteams(gametype);    /* do nothing till all other players have w3route conn closed */    for (i = 0; i < tp; i++)	if (i + 1 != plnum && a->info->player[i])	    if (conn_get_routeconn(a->info->player[i]))		return 0;    anongame_evaluate_results(a);    /* count wins, losses, discs */    for (i = 0; i < tp; i++) {	if (a->info->result[i] == W3_GAMERESULT_WIN)	    wins++;	else if (a->info->result[i] == W3_GAMERESULT_LOSS)	    losses++;	else	    discs++;    }    /* do some sanity checking (hack prevention) */    switch (gametype) {	case ANONGAME_TYPE_SMALL_FFA:	    if (wins != 1) {		eventlog(eventlog_level_info, __FUNCTION__, "bogus game result: wins != 1 in small ffa game");		return -1;	    }	    break;	case ANONGAME_TYPE_TEAM_FFA:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -