📄 game.c
字号:
return -1; } if (!game->results) { eventlog(eventlog_level_error,__FUNCTION__,"results array is NULL"); return -1; } if (!game->reported_results) { eventlog(eventlog_level_error,__FUNCTION__,"reported_results array is NULL"); return -1; } for (i=0;i<game->count;i++) { wins = losses = draws = disconnects = reports = 0; for (j=0;j<game->count;j++) { if (game->reported_results[j]) { switch (game->reported_results[j][i]) { case game_result_win: wins++; reports++; break; case game_result_loss: losses++; reports++; break; case game_result_draw: draws++; reports++; break; case game_result_disconnect: disconnects++; reports++; break; default: break; } } } eventlog(eventlog_level_debug,__FUNCTION__,"wins: %u losses: %u draws: %u disconnects: %u",wins,losses,draws,disconnects); //now decide what result we give if (!(reports)) // no results at all - game canceled before starting { game->results[i] = game_result_none; eventlog(eventlog_level_debug,__FUNCTION__,"deciding to give \"none\" to player %d",i); } else if ((disconnects>=draws) && (disconnects>=losses) && (disconnects>=wins)) { game->results[i] = game_result_disconnect; //consider disconnects the worst case... eventlog(eventlog_level_debug,__FUNCTION__,"deciding to give \"disconnect\" to player %d",i); } else if ((losses>=wins) && (losses>=draws)) { game->results[i]=game_result_loss; //losses are also bad... eventlog(eventlog_level_debug,__FUNCTION__,"deciding to give \"loss\" to player %d",i); } else if ((draws>=wins)) { game->results[i]=game_result_draw; eventlog(eventlog_level_debug,__FUNCTION__,"deciding to give \"draw\" to player %d",i); } else if (wins) { game->results[i]=game_result_win; eventlog(eventlog_level_debug,__FUNCTION__,"deciding to give \"win\" to player %d",i); } } return 0;}static int game_match_type(t_game_type type,const char *gametypes){ char *p, *q; int res; if (!gametypes || !gametypes[0]) return 0; gametypes = p = xstrdup(gametypes); res = 0; do { q = strchr(p,','); if (q) *q = '\0'; if (!strcasecmp(p,"topvbot")) { if (type == game_type_topvbot) { res = 1; break; } } else if (!strcasecmp(p,"melee")) { if (type == game_type_melee) { res = 1; break; } } else if (!strcasecmp(p,"ffa")) { if (type == game_type_ffa) { res = 1; break; } } else if (!strcasecmp(p,"oneonone")) { if (type == game_type_oneonone) { res = 1; break; } } if (q) p = q + 1; } while(q); free((void*)gametypes); return res;}static int game_report(t_game * game){ FILE * fp; char * realname; char * tempname; unsigned int i; unsigned int realcount; t_ladder_info * ladder_info=NULL; int discisloss; char clienttag_str[5]; if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return -1; } if (!game->clienttag) { eventlog(eventlog_level_error,__FUNCTION__,"got UNKNOWN clienttag"); return -1; } if (!game->players) { eventlog(eventlog_level_error,__FUNCTION__,"player array is NULL"); return -1; } if (!game->reported_results) { eventlog(eventlog_level_error,__FUNCTION__,"reported_results array is NULL"); return -1; } if (!game->results) { eventlog(eventlog_level_error,__FUNCTION__,"results array is NULL"); return -1; } if (prefs_get_discisloss()==1 || game->option==game_option_ladder_countasloss) discisloss = 1; else discisloss = 0; if (game->clienttag==CLIENTTAG_WARCRAFT3_UINT || game->clienttag==CLIENTTAG_WAR3XP_UINT) // war3 game reporting is done elsewhere, so we can skip this function return 0; if (game->clienttag==CLIENTTAG_DIABLOSHR_UINT || game->clienttag==CLIENTTAG_DIABLORTL_UINT || game->clienttag==CLIENTTAG_DIABLO2ST_UINT || game->clienttag==CLIENTTAG_DIABLO2DV_UINT || game->clienttag==CLIENTTAG_DIABLO2XP_UINT) { if (prefs_get_report_diablo_games() == 1) /* diablo games have transient players and no reported winners/losers */ realcount = 0; else { eventlog(eventlog_level_info,__FUNCTION__,"diablo gamereport disabled: ignoring game"); return 0; } } else { game_evaluate_results(game); // evaluate results from the reported results /* "compact" the game; move all the real players to the top... */ realcount = 0; for (i=0; i<game->count; i++) { if (!game->players[i]) { eventlog(eventlog_level_error,__FUNCTION__,"player slot %u has NULL account",i); continue; } if (game->results[i]!=game_result_none) { game->players[realcount] = game->players[i]; game->results[realcount] = game->results[i]; game->report_heads[realcount] = game->report_heads[i]; game->report_bodies[realcount] = game->report_bodies[i]; realcount++; } } /* then nuke duplicate players after the real players */ for (i=realcount; i<game->count; i++) { game->players[i] = NULL; game->results[i] = game_result_none; game->report_heads[i] = NULL; game->report_bodies[i] = NULL; } if (realcount<1) { eventlog(eventlog_level_info,__FUNCTION__,"ignoring game"); return -1; } } eventlog(eventlog_level_debug,__FUNCTION__,"realcount=%d count=%u",realcount,game->count); if (realcount>=1 && !game->bad) { if (game_is_ladder(game) ) { t_ladder_id id; if (game_get_type(game)==game_type_ironman) id = ladder_id_ironman; else id = ladder_id_normal; for (i=0; i<realcount; i++) { eventlog(eventlog_level_debug,__FUNCTION__,"realplayer %u result=%u",i+1,(unsigned int)game->results[i]); ladder_init_account(game->players[i],game->clienttag,id); switch (game->results[i]) { case game_result_win: account_inc_ladder_wins(game->players[i],game->clienttag,id); account_set_ladder_last_result(game->players[i],game->clienttag,id,game_result_get_str(game_result_win)); break; case game_result_loss: account_inc_ladder_losses(game->players[i],game->clienttag,id); account_set_ladder_last_result(game->players[i],game->clienttag,id,game_result_get_str(game_result_loss)); break; case game_result_draw: account_inc_ladder_draws(game->players[i],game->clienttag,id); account_set_ladder_last_result(game->players[i],game->clienttag,id,game_result_get_str(game_result_draw)); break; case game_result_disconnect: if (discisloss) { account_inc_ladder_losses(game->players[i],game->clienttag,id); account_set_ladder_last_result(game->players[i],game->clienttag,id,game_result_get_str(game_result_loss)); } else {/* FIXME: do the first disconnect only stuff like below */ account_inc_ladder_disconnects(game->players[i],game->clienttag,id); account_set_ladder_last_result(game->players[i],game->clienttag,id,game_result_get_str(game_result_disconnect)); } break; default: eventlog(eventlog_level_error,__FUNCTION__,"bad ladder game realplayer results[%u] = %u",i,game->results[i]); account_inc_ladder_disconnects(game->players[i],game->clienttag,id); account_set_ladder_last_result(game->players[i],game->clienttag,id,game_result_get_str(game_result_disconnect)); } account_set_ladder_last_time(game->players[i],game->clienttag,id,bnettime()); } ladder_info = xmalloc(sizeof(t_ladder_info)*realcount); if (ladder_update(game->clienttag,id, realcount,game->players,game->results,ladder_info, discisloss?ladder_option_disconnectisloss:ladder_option_none)<0) { eventlog(eventlog_level_error,__FUNCTION__,"unable to update ladder stats"); xfree(ladder_info); ladder_info = NULL; } } else { int disc_set=0; for (i=0; i<realcount; i++) { switch (game->results[i]) { case game_result_win: account_inc_normal_wins(game->players[i],game->clienttag); account_set_normal_last_result(game->players[i],game->clienttag,game_result_get_str(game_result_win)); break; case game_result_loss: account_inc_normal_losses(game->players[i],game->clienttag); account_set_normal_last_result(game->players[i],game->clienttag,game_result_get_str(game_result_loss)); break; case game_result_draw: account_inc_normal_draws(game->players[i],game->clienttag); account_set_normal_last_result(game->players[i],game->clienttag,game_result_get_str(game_result_draw)); break; case game_result_disconnect: if (discisloss) { account_inc_normal_losses(game->players[i],game->clienttag); account_set_normal_last_result(game->players[i],game->clienttag,game_result_get_str(game_result_loss)); } else {/* FIXME: Is the missing player always the first one in this array? It seems like it should be the person that created the game */ if (!disc_set) { account_inc_normal_disconnects(game->players[i],game->clienttag); disc_set = 1; } account_set_normal_last_result(game->players[i],game->clienttag,game_result_get_str(game_result_disconnect)); } break; default: eventlog(eventlog_level_error,__FUNCTION__,"bad normal game realplayer results[%u] = %u",i,game->results[i]);/* FIXME: Jung-woo fixed this here but we should find out what value results[i] has... and why "discisloss" isn't set above in game_result_disconnect */#if 0 /* commented out for loose disconnect policy */ /* account_inc_normal_disconnects(game->players[i],game->clienttag); */#endif account_inc_normal_disconnects(game->players[i],game->clienttag); account_set_normal_last_result(game->players[i],game->clienttag,game_result_get_str(game_result_disconnect)); } account_set_normal_last_time(game->players[i],game->clienttag,bnettime()); } } } if (game_get_type(game)!=game_type_ladder && prefs_get_report_all_games()!=1) { eventlog(eventlog_level_debug,__FUNCTION__,"not reporting normal games"); return 0; } { struct tm * tmval; char dstr[64]; if (!(tmval = localtime(&now))) dstr[0] = '\0'; else sprintf(dstr,"%04d%02d%02d%02d%02d%02d", 1900+tmval->tm_year, tmval->tm_mon+1, tmval->tm_mday, tmval->tm_hour, tmval->tm_min, tmval->tm_sec); tempname = xmalloc(strlen(prefs_get_reportdir())+1+1+5+1+2+1+strlen(dstr)+1+6+1); sprintf(tempname,"%s/_bnetd-gr_%s_%06u",prefs_get_reportdir(),dstr,game->id); realname = xmalloc(strlen(prefs_get_reportdir())+1+2+1+strlen(dstr)+1+6+1); sprintf(realname,"%s/gr_%s_%06u",prefs_get_reportdir(),dstr,game->id); } if (!(fp = fopen(tempname,"w"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open report file \"%s\" for writing (fopen: %s)",tempname,pstrerror(errno)); if (ladder_info) xfree(ladder_info); xfree(realname); xfree(tempname); return -1; } if (game->bad) fprintf(fp,"[ game results ignored due to inconsistencies ]\n\n"); fprintf(fp,"name=\"%s\" id="GAMEID_FORMAT"\n", game_get_name(game), game->id); fprintf(fp,"clienttag=%4s type=\"%s\" option=\"%s\"\n", tag_uint_to_str(clienttag_str,game->clienttag), game_type_get_str(game->type), game_option_get_str(game->option)); { struct tm * gametime; char timetemp[GAME_TIME_MAXLEN]; if (!(gametime = localtime(&game->create_time))) strcpy(timetemp,"?"); else strftime(timetemp,sizeof(timetemp),GAME_TIME_FORMAT,gametime); fprintf(fp,"created=\"%s\" ",timetemp); if (!(gametime = localtime(&game->start_time))) strcpy(timetemp,"?"); else strftime(timetemp,sizeof(timetemp),GAME_TIME_FORMAT,gametime); fprintf(fp,"started=\"%s\" ",timetemp); if (!(gametime = localtime(&now))) strcpy(timetemp,"?"); else strftime(timetemp,sizeof(timetemp),GAME_TIME_FORMAT,gametime); fprintf(fp,"ended=\"%s\"\n",timetemp); } { char const * mapname; if (!(mapname = game_get_mapname(game))) mapname = "?"; fprintf(fp,"mapfile=\"%s\" mapauth=\"%s\" mapsize=%ux%u tileset=\"%s\"\n", mapname, game_maptype_get_str(game_get_maptype(game)), game_get_mapsize_x(game),game_get_mapsize_y(game), game_tileset_get_str(game_get_tileset(game))); } fprintf(fp,"joins=%u maxplayers=%u\n", game_get_count(game), game_get_maxplayers(game)); if (!prefs_get_hide_addr()) fprintf(fp,"host=%s\n",addr_num_to_addr_str(game_get_addr(game),game_get_port(game))); fprintf(fp,"\n\n"); if (game->clienttag==CLIENTTAG_DIABLORTL_UINT) for (i=0; i<game->count; i++) fprintf(fp,"%-16s JOINED\n",account_get_name(game->players[i])); else if (ladder_info) for (i=0; i<realcount; i++) fprintf(fp,"%-16s %-8s rating=%u [#%05u] prob=%4.1f%% K=%2u adj=%+d\n", account_get_name(game->players[i]), game_result_get_str(game->results[i]), ladder_info[i].oldrating, ladder_info[i].oldrank, ladder_info[i].prob*100.0, ladder_info[i].k, ladder_info[i].adj); else for (i=0; i<realcount; i++) fprintf(fp,"%-16s %-8s\n", account_get_name(game->players[i]), game_result_get_str(game->results[i])); fprintf(fp,"\n\n"); if (ladder_info) xfree(ladder_info); for (i=0; i<realcount; i++) { if (game->report_heads[i]) fprintf(fp,"%s\n",game->report_heads[i]); else fprintf(fp,"[ game report header not available for player %u (\"%s\") ]\n",i+1,account_get_name(game->players[i])); if (game->report_bodies[i]) fprintf(fp,"%s\n",game->report_bodies[i]); else fprintf(fp,"[ game report body not available for player %u (\"%s\") ]\n\n",i+1,account_get_name(game->players[i])); } fprintf(fp,"\n\n"); if (game->clienttag==CLIENTTAG_STARCRAFT_UINT || game->clienttag==CLIENTTAG_SHAREWARE_UINT || game->clienttag==CLIENTTAG_BROODWARS_UINT || game->clienttag==CLIENTTAG_WARCIIBNE_UINT) { for (i=0; i<realcount; i++) fprintf(fp,"%s's normal record is now %u/%u/%u (%u draws)\n", account_get_name(game->players[i]), account_get_normal_wins(game->players[i],game->clienttag), account_get_normal_losses(game->players[i],game->clienttag), account_get_normal_disconnects(game->players[i],game->clienttag), account_get_normal_draws(game->players[i],game->clienttag)); } if (game->clienttag==CLIENTTAG_STARCRAFT_UINT || game->clienttag==CLIENTTAG_BROODWARS_UINT || game->clienttag==CLIENTTAG_WARCIIBNE_UINT) { fprintf(fp,"\n"); for (i=0; i<realcount; i++) fprintf(fp,"%s's standard ladder record is now %u/%u/%u (rating %u [#%05u]) (%u draws)\n", account_get_name(game->players[i]), account_get_ladder_wins(game->players[i],game->clienttag,ladder_id_normal), account_get_ladder_losses(game->players[i],game->clienttag,ladder_id_normal), account_get_ladder_disconnects(game->players[i],game->clienttag,ladder_id_normal), account_get_ladder_rating(game->players[i],game->clienttag,ladder_id_normal), account_get_ladder_rank(game->players[i],game->clienttag,ladder_id_normal), account_get_ladder_draws(game->players[i],game->clienttag,ladder_id_normal)); } if (game->clienttag==CLIENTTAG_WARCIIBNE_UINT) { fprintf(fp,"\n"); for (i=0; i<realcount; i++) fprintf(fp,"%s's ironman ladder record is now %u/%u/%u (rating %u [#%05u]) (%u draws)\n", account_get_name(game->players[i]), account_get_ladder_wins(game->players[i],game->clienttag,ladder_id_ironman), account_get_ladder_losses(game->players[i],game->clienttag,ladder_id_ironman), account_get_ladder_disconnects(game->players[i],game->clienttag,ladder_id_ironman), account_get_ladder_rating(game->players[i],game->clienttag,ladder_id_ironman), account_get_ladder_rank(game->players[i],game->clienttag,ladder_id_ironman), account_get_ladder_draws(game->players[i],game->clienttag,ladder_id_ironman)); } fprintf(fp,"\nThis game lasted %lu minutes (elapsed).\n",((unsigned long int)difftime(now,game->start_time))/60); if (fclose(fp)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not close report file \"%s\" after writing (fclose: %s)",tempname,pstrerror(errno)); xfree(realname); xfree(tempname); return -1; } if (p_rename(tempname,realname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not rename report file to \"%s\" (rename: %s)",realname,pstrerror(errno)); xfree(realname); xfree(tempname); return -1; } eventlog(eventlog_level_debug,__FUNCTION__,"game report saved as \"%s\"",realname); xfree(realname); xfree(tempname); return 0;}extern unsigned int game_get_id(t_game const * game){ if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return 0; } return game->id;}extern char const * game_get_name(t_game const * game){ if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return NULL; } return game->name ? game->name : "BNet";}extern t_game_type game_get_type(t_game const * game){ if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return 0; } return game->type;}extern t_game_maptype game_get_maptype(t_game const * game){ if (!game) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); return game_maptype_none; } return game->maptype;}extern int game_set_maptype(t_game * game, t_game_maptype maptype){ if (!game) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -