X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fcommon%2Fplayerstats.qc;h=0fcd70dfc08fd8e7afd9bdc2cd2b31c063331c79;hb=d865de7a9a17c5a1d9286aec40f68c3530697660;hp=ec2f7cad3ddf3d4fc9ca8ae568824b37d216854c;hpb=eac60648c4017e495060dd3ba9e50ac4bad5000a;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/common/playerstats.qc b/qcsrc/common/playerstats.qc index ec2f7cad3..0fcd70dfc 100644 --- a/qcsrc/common/playerstats.qc +++ b/qcsrc/common/playerstats.qc @@ -1,13 +1,14 @@ +#include "playerstats.qh" #if defined(CSQC) #elif defined(MENUQC) #elif defined(SVQC) #include "constants.qh" #include "util.qh" - #include - #include "../server/weapons/accuracy.qh" + #include + #include "../server/anticheat.qh" #include "../server/defs.qh" - #include "playerstats.qh" #include "../server/scores.qh" + #include "../server/weapons/accuracy.qh" #endif #ifdef SVQC @@ -21,14 +22,14 @@ void PlayerStats_GameReport_AddPlayer(entity e) if((PS_GR_OUT_DB < 0) || (e.playerstats_id)) { return; } // set up player identification - string s = string_null; + string s = ""; - if((e.crypto_idfp != "") && (e.cvar_cl_allow_uidtracking == 1)) + if((e.crypto_idfp != "") && (CS(e).cvar_cl_allow_uidtracking == 1)) { s = e.crypto_idfp; } else if(IS_BOT_CLIENT(e)) { s = sprintf("bot#%g#%s", skill, e.cleanname); } - if((s == "") || find(world, playerstats_id, s)) // already have one of the ID - next one can't be tracked then! + if((s == "") || find(NULL, playerstats_id, s)) // already have one of the ID - next one can't be tracked then! { if(IS_BOT_CLIENT(e)) { s = sprintf("bot#%d", e.playerid); } @@ -92,7 +93,6 @@ void PlayerStats_GameReport_AddEvent(string event_id) } } -// referred to by PS_GR_P_ADDVAL and PS_GR_T_ADDVAL float PlayerStats_GameReport_Event(string prefix, string event_id, float value) { if((prefix == "") || PS_GR_OUT_DB < 0) { return 0; } @@ -107,7 +107,8 @@ float PlayerStats_GameReport_Event(string prefix, string event_id, float value) void PlayerStats_GameReport_Accuracy(entity p) { #define ACCMAC(suffix, field) \ - PS_GR_P_ADDVAL(p, sprintf("acc-%s-%s", it.netname, suffix), p.accuracy.(field[i-1])); + PlayerStats_GameReport_Event_Player(p, \ + sprintf("acc-%s-%s", it.netname, suffix), CS(p).accuracy.(field[i-1])); FOREACH(Weapons, it != WEP_Null, { ACCMAC("hit", accuracy_hit) ACCMAC("fired", accuracy_fired) @@ -125,29 +126,31 @@ void PlayerStats_GameReport_FinalizePlayer(entity p) // add global info! if(p.alivetime) { - PS_GR_P_ADDVAL(p, PLAYERSTATS_ALIVETIME, time - p.alivetime); + PlayerStats_GameReport_Event_Player(p, PLAYERSTATS_ALIVETIME, time - p.alivetime); p.alivetime = 0; } db_put(PS_GR_OUT_DB, sprintf("%s:_playerid", p.playerstats_id), ftos(p.playerid)); - if(p.cvar_cl_allow_uid2name == 1 || IS_BOT_CLIENT(p)) - db_put(PS_GR_OUT_DB, sprintf("%s:_netname", p.playerstats_id), p.netname); + if(CS(p).cvar_cl_allow_uid2name == 1 || IS_BOT_CLIENT(p)) + db_put(PS_GR_OUT_DB, sprintf("%s:_netname", p.playerstats_id), playername(p, false)); if(teamplay) db_put(PS_GR_OUT_DB, sprintf("%s:_team", p.playerstats_id), ftos(p.team)); if(stof(db_get(PS_GR_OUT_DB, sprintf("%s:%s", p.playerstats_id, PLAYERSTATS_ALIVETIME))) > 0) - PS_GR_P_ADDVAL(p, PLAYERSTATS_JOINS, 1); + PlayerStats_GameReport_Event_Player(p, PLAYERSTATS_JOINS, 1); PlayerStats_GameReport_Accuracy(p); + anticheat_report_to_playerstats(p); if(IS_REAL_CLIENT(p)) { - if(p.latency_cnt) + if(CS(p).latency_cnt) { - float latency = (p.latency_sum / p.latency_cnt); - if(latency) { PS_GR_P_ADDVAL(p, PLAYERSTATS_AVGLATENCY, latency); } + float latency = (CS(p).latency_sum / CS(p).latency_cnt); + if(latency) + PlayerStats_GameReport_Event_Player(p, PLAYERSTATS_AVGLATENCY, latency); } } @@ -165,16 +168,16 @@ void PlayerStats_GameReport(float finished) FOREACH_CLIENT(true, { // add personal score rank - PS_GR_P_ADDVAL(it, PLAYERSTATS_RANK, it.score_dummyfield); + PlayerStats_GameReport_Event_Player(it, PLAYERSTATS_RANK, it.score_dummyfield); // scoreboard data if(it.scoreboard_pos) { // scoreboard is valid! - PS_GR_P_ADDVAL(it, PLAYERSTATS_SCOREBOARD_VALID, 1); + PlayerStats_GameReport_Event_Player(it, PLAYERSTATS_SCOREBOARD_VALID, 1); // add scoreboard position - PS_GR_P_ADDVAL(it, PLAYERSTATS_SCOREBOARD_POS, it.scoreboard_pos); + PlayerStats_GameReport_Event_Player(it, PLAYERSTATS_SCOREBOARD_POS, it.scoreboard_pos); // add scoreboard data PlayerScore_PlayerStats(it); @@ -182,8 +185,8 @@ void PlayerStats_GameReport(float finished) // if the match ended normally, add winning info if(finished) { - PS_GR_P_ADDVAL(it, PLAYERSTATS_WINS, it.winning); - PS_GR_P_ADDVAL(it, PLAYERSTATS_MATCHES, 1); + PlayerStats_GameReport_Event_Player(it, PLAYERSTATS_WINS, it.winning); + PlayerStats_GameReport_Event_Player(it, PLAYERSTATS_MATCHES, 1); } } @@ -198,7 +201,7 @@ void PlayerStats_GameReport(float finished) autocvar_g_playerstats_gamereport_uri, FILE_APPEND, PlayerStats_GameReport_Handler, - world + NULL ); } else @@ -249,10 +252,26 @@ void PlayerStats_GameReport_Init() // initiated before InitGameplayMode so that PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_BOTLIKE); PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD); PlayerStats_GameReport_AddEvent(PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM); + + anticheat_register_to_playerstats(); } else { PlayerStats_GameReport_DelayMapVote = false; } } +// this... is a hack, a temporary one until we get a proper duel gametype +string PlayerStats_GetGametype() +{ + if(IS_GAMETYPE(DEATHMATCH) && autocvar_g_maxplayers == 2) + { + // probably duel, but let's make sure + int plcount = 0; + FOREACH_CLIENT(IS_PLAYER(it), ++plcount); + if(plcount <= 2) + return "duel"; + } + return GetGametype(); +} + void PlayerStats_GameReport_Handler(entity fh, entity pass, float status) { string t, tn; @@ -309,7 +328,7 @@ void PlayerStats_GameReport_Handler(entity fh, entity pass, float status) #ifdef WATERMARK url_fputs(fh, sprintf("R %s\n", WATERMARK)); #endif - url_fputs(fh, sprintf("G %s\n", GetGametype())); + url_fputs(fh, sprintf("G %s\n", PlayerStats_GetGametype())); url_fputs(fh, sprintf("O %s\n", modname)); url_fputs(fh, sprintf("M %s\n", GetMapname())); url_fputs(fh, sprintf("I %s\n", matchid)); @@ -379,9 +398,9 @@ void PlayerStats_GameReport_Handler(entity fh, entity pass, float status) { // url_fclose is processing, we got a response for writing the data // this must come from HTTP - LOG_TRACE("Got response from player stats server:\n"); - while((s = url_fgets(fh))) { LOG_TRACE(" ", s, "\n"); } - LOG_TRACE("End of response.\n"); + LOG_TRACE("Got response from player stats server:"); + while((s = url_fgets(fh))) { LOG_TRACE(" ", s); } + LOG_TRACE("End of response."); url_fclose(fh); break; } @@ -389,7 +408,7 @@ void PlayerStats_GameReport_Handler(entity fh, entity pass, float status) case URL_READY_CLOSED: { // url_fclose has finished - LOG_TRACE("Player stats written\n"); + LOG_TRACE("Player stats written"); PlayerStats_GameReport_DelayMapVote = false; if(PS_GR_OUT_DB >= 0) { @@ -402,7 +421,7 @@ void PlayerStats_GameReport_Handler(entity fh, entity pass, float status) case URL_READY_ERROR: default: { - LOG_INFO("Player stats writing failed: ", ftos(status), "\n"); + LOG_INFO("Player stats writing failed: ", ftos(status)); PlayerStats_GameReport_DelayMapVote = false; if(PS_GR_OUT_DB >= 0) { @@ -416,19 +435,21 @@ void PlayerStats_GameReport_Handler(entity fh, entity pass, float status) void PlayerStats_PlayerBasic(entity joiningplayer, float newrequest) { + GameRules_scoring_add(joiningplayer, ELO, -1); // http://stats.xonotic.org/player/GgXRw6piDtFIbMArMuiAi8JG4tiin8VLjZgsKB60Uds=/elo.txt if(autocvar_g_playerstats_playerbasic_uri != "") { string uri = autocvar_g_playerstats_playerbasic_uri; - if(joiningplayer.crypto_idfp != "") - { + if (joiningplayer.crypto_idfp == "") { + GameRules_scoring_add(joiningplayer, ELO, -1); + } else { // create the database if it doesn't already exist if(PS_B_IN_DB < 0) PS_B_IN_DB = db_create(); // now request the information uri = strcat(uri, "/player/", uri_escape(uri_escape(uri_escape(joiningplayer.crypto_idfp))), "/elo.txt"); - LOG_TRACE("Retrieving playerstats from URL: ", uri, "\n"); + LOG_TRACE("Retrieving playerstats from URL: ", uri); url_single_fopen( uri, FILE_APPEND, @@ -452,6 +473,7 @@ void PlayerStats_PlayerBasic(entity joiningplayer, float newrequest) else { // server has this disabled, kill the DB and set status to idle + GameRules_scoring_add(joiningplayer, ELO, -1); if(PS_B_IN_DB >= 0) { db_close(PS_B_IN_DB); @@ -466,12 +488,10 @@ void PlayerStats_PlayerBasic_CheckUpdate(entity joiningplayer) { // determine whether we should retrieve playerbasic information again - #if 0 - LOG_INFOF("PlayerStats_PlayerBasic_CheckUpdate('%s'): %f\n", + LOG_TRACEF("PlayerStats_PlayerBasic_CheckUpdate('%s'): %f", joiningplayer.netname, time ); - #endif // TODO: check to see if this playerid is inside the database already somehow... // for now we'll just check the field, but this won't work for players who disconnect and reconnect properly @@ -491,7 +511,7 @@ void PlayerStats_PlayerBasic_Handler(entity fh, entity p, float status) { case URL_READY_CANWRITE: { - LOG_TRACE("-- Sending data to player stats server\n"); + LOG_TRACE("-- Sending data to player stats server"); /*url_fputs(fh, "V 1\n"); #ifdef WATERMARK url_fputs(fh, sprintf("R %s\n", WATERMARK)); @@ -503,85 +523,86 @@ void PlayerStats_PlayerBasic_Handler(entity fh, entity p, float status) url_fputs(fh, sprintf("m %s %s\n", cvar_string("_cl_playermodel"), cvar_string("_cl_playerskin"))); // model/skin */url_fputs(fh, "\n"); url_fclose(fh); - break; + return; } case URL_READY_CANREAD: { - string s = ""; - LOG_TRACE("-- Got response from player stats server:\n"); - //string gametype = string_null; - while((s = url_fgets(fh))) - { - LOG_TRACE(" ", s, "\n"); - /* + bool handled = false; + string gt = string_null; + for (string s = ""; (s = url_fgets(fh)); ) { + int n = tokenizebyseparator(s, " "); // key value? data + if (n == 1) continue; string key = "", value = "", data = ""; - - n = tokenizebyseparator(s, " "); // key (value) data - if (n == 1) - continue; - else if (n == 2) - { - key = argv(0); - data = argv(1); - } - else if (n >= 3) - { - key = argv(0); - value = argv(1); - data = argv(2); - } - - if (data == "") - continue; - - if (key == "#") - continue; - else if (key == "V") - PlayerInfo_AddItem(p, "_version", data); - else if (key == "R") - PlayerInfo_AddItem(p, "_release", data); - else if (key == "T") - PlayerInfo_AddItem(p, "_time", data); - else if (key == "S") - PlayerInfo_AddItem(p, "_statsurl", data); - else if (key == "P") - PlayerInfo_AddItem(p, "_hashkey", data); - else if (key == "n") - PlayerInfo_AddItem(p, "_playernick", data); - else if (key == "i") - PlayerInfo_AddItem(p, "_playerid", data); - else if (key == "G") - gametype = data; - else if (key == "e" && value != "") - { - if (gametype == "") - PlayerInfo_AddItem(p, value, data); - else - PlayerInfo_AddItem(p, sprintf("%s/%s", gametype, value), data); + if (n == 2) { + key = argv(0); + data = argv(1); + } else if (n >= 3) { + key = argv(0); + value = argv(1); + data = argv(2); } - else - continue; - */ + switch (key) { + case "V": + // PlayerInfo_AddItem(p, "_version", data); + break; + case "R": + // PlayerInfo_AddItem(p, "_release", data); + break; + case "T": + // PlayerInfo_AddItem(p, "_time", data); + break; + case "S": + // PlayerInfo_AddItem(p, "_statsurl", data); + break; + case "P": + // PlayerInfo_AddItem(p, "_hashkey", data); + break; + case "n": + // PlayerInfo_AddItem(p, "_playernick", data); + break; + case "i": + // PlayerInfo_AddItem(p, "_playerid", data); + // p.xonstat_id = stof(data); + break; + case "G": + gt = data; + break; + case "e": + LOG_TRACE("G: ", gt); + LOG_TRACE("e: ", data); + if (gt == PlayerStats_GetGametype()) { + handled = true; + float e = stof(data); + GameRules_scoring_add(p, ELO, +1 + e); + } + if (gt == "") { + // PlayerInfo_AddItem(p, value, data); + } else { + // PlayerInfo_AddItem(p, sprintf("%s/%s", gt, value), data); + } + break; + } } - LOG_TRACE("-- End of response.\n"); url_fclose(fh); + if (handled) return; break; } case URL_READY_CLOSED: { // url_fclose has finished - LOG_INFO("Player stats synchronized with server\n"); - break; + LOG_INFO("Player stats synchronized with server"); + return; } case URL_READY_ERROR: default: { - LOG_INFO("Receiving player stats failed: ", ftos(status), "\n"); + LOG_INFO("Receiving player stats failed: ", ftos(status)); break; } } + GameRules_scoring_add(p, ELO, -1); } #endif // SVQC @@ -593,7 +614,7 @@ void PlayerStats_PlayerBasic_Handler(entity fh, entity p, float status) float i = 0; for(e = PS_D_IN_EVL; (en = db_get(PS_D_IN_DB, e)) != ""; e = en) { - LOG_INFO(sprintf("%d:%s:%s\n", i, e, db_get(PS_D_IN_DB, sprintf("#%s", e)))); + LOG_INFOF("%d:%s:%s", i, e, db_get(PS_D_IN_DB, sprintf("#%s", e))); ++i; } #endif @@ -617,7 +638,7 @@ void PlayerStats_PlayerDetail_AddItem(string event, string data) // now actually set the event data db_put(PS_D_IN_DB, sprintf("#%s", event), data); - LOG_TRACE("Added item ", sprintf("#%s", event), "=", data, " to PS_D_IN_DB\n"); + LOG_TRACE("Added item ", sprintf("#%s", event), "=", data, " to PS_D_IN_DB"); } void PlayerStats_PlayerDetail() @@ -630,12 +651,12 @@ void PlayerStats_PlayerDetail() PS_D_IN_DB = db_create(); //uri = strcat(uri, "/player/", uri_escape(crypto_getmyidfp(0))); - LOG_TRACE("Retrieving playerstats from URL: ", autocvar_g_playerstats_playerdetail_uri, "\n"); + LOG_TRACE("Retrieving playerstats from URL: ", autocvar_g_playerstats_playerdetail_uri); url_single_fopen( autocvar_g_playerstats_playerdetail_uri, FILE_APPEND, PlayerStats_PlayerDetail_Handler, - world + NULL ); PlayerStats_PlayerDetail_Status = PS_D_STATUS_WAITING; @@ -659,7 +680,7 @@ void PlayerStats_PlayerDetail_CheckUpdate() float gamecount = cvar("cl_matchcount"); #if 0 - LOG_INFOF("PlayerStats_PlayerDetail_CheckUpdate(): %f >= %f, %d > %d\n", + LOG_INFOF("PlayerStats_PlayerDetail_CheckUpdate(): %f >= %f, %d > %d", time, PS_D_NEXTUPDATETIME, PS_D_LASTGAMECOUNT, @@ -685,7 +706,7 @@ void PlayerStats_PlayerDetail_Handler(entity fh, entity unused, float status) { case URL_READY_CANWRITE: { - LOG_TRACE("PlayerStats_PlayerDetail_Handler(): Sending data to player stats server...\n"); + LOG_TRACE("PlayerStats_PlayerDetail_Handler(): Sending data to player stats server..."); url_fputs(fh, "V 1\n"); #ifdef WATERMARK url_fputs(fh, sprintf("R %s\n", WATERMARK)); @@ -762,7 +783,7 @@ void PlayerStats_PlayerDetail_Handler(entity fh, entity unused, float status) "PlayerStats_PlayerDetail_Handler(): ERROR: " "Key went unhandled? Is our version outdated?\n" "PlayerStats_PlayerDetail_Handler(): " - "Key '%s', Event '%s', Data '%s'\n", + "Key '%s', Event '%s', Data '%s'", key, event, data @@ -772,13 +793,13 @@ void PlayerStats_PlayerDetail_Handler(entity fh, entity unused, float status) } #if 0 - LOG_INFO(sprintf( + LOG_INFOF( "PlayerStats_PlayerDetail_Handler(): " - "Key '%s', Event '%s', Data '%s'\n", + "Key '%s', Event '%s', Data '%s'", key, event, data - )); + ); #endif } //print("PlayerStats_PlayerDetail_Handler(): End of response.\n"); @@ -791,14 +812,14 @@ void PlayerStats_PlayerDetail_Handler(entity fh, entity unused, float status) case URL_READY_CLOSED: { // url_fclose has finished - LOG_INFO("PlayerStats_PlayerDetail_Handler(): Player stats synchronized with server.\n"); + LOG_INFO("PlayerStats_PlayerDetail_Handler(): Player stats synchronized with server."); break; } case URL_READY_ERROR: default: { - LOG_INFO("PlayerStats_PlayerDetail_Handler(): Receiving player stats failed: ", ftos(status), "\n"); + LOG_INFO("PlayerStats_PlayerDetail_Handler(): Receiving player stats failed: ", ftos(status)); PlayerStats_PlayerDetail_Status = PS_D_STATUS_ERROR; if(PS_D_IN_DB >= 0) { @@ -1013,7 +1034,7 @@ void PlayerInfo_Details() //uri = strcat(uri, "/player/", uri_escape(crypto_getmyidfp(0))); uri = strcat(uri, "/player/me"); print("Retrieving playerstats from URL: ", uri, "\n"); - url_single_fopen(uri, FILE_APPEND, PlayerInfo_ready, world); + url_single_fopen(uri, FILE_APPEND, PlayerInfo_ready, NULL); } } #endif