📄 anongame.c
字号:
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 + -