From 319d07d4fc823b6621196790e30526bfff4888b5 Mon Sep 17 00:00:00 2001 From: Jan Behrens Date: Sun, 4 Aug 2013 20:05:15 +0200 Subject: [PATCH] WIP commit; retrieving data from xonstats works --- qcsrc/client/Main.qc | 26 ++-- qcsrc/client/autocvars.qh | 2 +- qcsrc/client/progs.src | 2 + qcsrc/common/playerstats.qc | 238 ++++++++++++++++++++++++--------- qcsrc/common/playerstats.qh | 8 +- qcsrc/menu/command/menu_cmd.qc | 9 ++ qcsrc/menu/progs.src | 2 +- 7 files changed, 212 insertions(+), 75 deletions(-) diff --git a/qcsrc/client/Main.qc b/qcsrc/client/Main.qc index 42fadc0c1..f6339ac38 100644 --- a/qcsrc/client/Main.qc +++ b/qcsrc/client/Main.qc @@ -81,7 +81,7 @@ void CSQC_Init(void) //registercommand("hud_configure"); //registercommand("hud_save"); //registercommand("menu_action"); - + ConsoleCommand_macro_init(); registercvar("hud_usecsqc", "1"); @@ -125,13 +125,13 @@ void CSQC_Init(void) turrets_precache(); Tuba_Precache(); CSQCPlayer_Precache(); - + if(autocvar_cl_reticle) { if(autocvar_cl_reticle_item_normal) { precache_pic("gfx/reticle_normal"); } if(autocvar_cl_reticle_item_nex) { precache_pic("gfx/reticle_nex"); } } - + get_mi_min_max_texcoords(1); // try the CLEVER way first minimapname = strcat("gfx/", mi_shortname, "_radar.tga"); shortmapname = mi_shortname; @@ -156,6 +156,12 @@ void CSQC_Init(void) hud_configure_prev = -1; draw_currentSkin = strzone(strcat("gfx/menu/", cvar_string("menu_skin"))); + + + //// WIP - zykure + + PlayerInfo_Init(); + PlayerInfo_Retrieve(self.owner); } // CSQC_Shutdown : Called every time the CSQC code is shutdown (changing maps, quitting, etc) @@ -651,7 +657,7 @@ void Ent_ReadSpawnPoint(float is_new) // entity for spawnpoint spn_origin_x = ReadShort(); spn_origin_y = ReadShort(); spn_origin_z = ReadShort(); - + if(is_new) { self.origin = spn_origin; @@ -682,7 +688,7 @@ void Ent_ReadSpawnPoint(float is_new) // entity for spawnpoint } } else { self.cnt = particleeffectnum("spawn_point_neutral"); } - + self.draw = Spawn_Draw; } } @@ -696,7 +702,7 @@ void Ent_ReadSpawnEvent(float is_new) // this way the server can disable the sending of // spawn origin or such to clients if wanted. float entnum = ReadByte(); - + if(entnum) { self.origin_x = ReadShort(); @@ -724,7 +730,7 @@ void Ent_ReadSpawnEvent(float is_new) } } } - + // local spawn actions if(is_new && (!entnum || (entnum == player_localentnum))) { @@ -737,7 +743,7 @@ void Ent_ReadSpawnEvent(float is_new) button_zoom = FALSE; } } - + //print(sprintf("Ent_ReadSpawnEvent(is_new = %d); origin = %s, entnum = %d, localentnum = %d\n", is_new, vtos(self.origin), entnum, player_localentnum)); } @@ -822,9 +828,9 @@ void CSQC_Ent_Update(float bIsNewEntity) case ENT_CLIENT_GAUNTLET: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_GAUNTLET); break; case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break; case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break; - case ENT_CLIENT_TURRET: ent_turret(); break; + case ENT_CLIENT_TURRET: ent_turret(); break; case ENT_CLIENT_MODEL: CSQCModel_Read(bIsNewEntity); break; - case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break; + case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break; case ENT_CLIENT_BUMBLE_RAYGUN: bumble_raygun_read(bIsNewEntity); break; case ENT_CLIENT_SPAWNPOINT: Ent_ReadSpawnPoint(bIsNewEntity); break; case ENT_CLIENT_SPAWNEVENT: Ent_ReadSpawnEvent(bIsNewEntity); break; diff --git a/qcsrc/client/autocvars.qh b/qcsrc/client/autocvars.qh index 8175695ab..403792020 100644 --- a/qcsrc/client/autocvars.qh +++ b/qcsrc/client/autocvars.qh @@ -337,7 +337,7 @@ float autocvar_hud_panel_weapons_timeout; float autocvar_hud_panel_weapons_timeout_effect; float autocvar_hud_panel_weapons_timeout_fadebgmin; float autocvar_hud_panel_weapons_timeout_fadefgmin; -var float autocvar_hud_panel_weapons_timeout_speed_in = 0.25; +var float autocvar_hud_panel_weapons_timeout_speed_in = 0.25; var float autocvar_hud_panel_weapons_timeout_speed_out = 0.75; float autocvar_hud_progressbar_alpha; float autocvar_hud_showbinds; diff --git a/qcsrc/client/progs.src b/qcsrc/client/progs.src index 114f0a5b5..1bae6f980 100644 --- a/qcsrc/client/progs.src +++ b/qcsrc/client/progs.src @@ -14,6 +14,7 @@ Defs.qc ../warpzonelib/common.qh ../warpzonelib/client.qh +../common/playerstats.qh ../common/teams.qh ../common/util.qh ../common/test.qh @@ -102,6 +103,7 @@ noise.qc ../common/test.qc ../common/util.qc +../common/playerstats.qc ../common/notifications.qc ../common/command/markup.qc ../common/command/rpn.qc diff --git a/qcsrc/common/playerstats.qc b/qcsrc/common/playerstats.qc index b6f795ed8..7389a61ca 100644 --- a/qcsrc/common/playerstats.qc +++ b/qcsrc/common/playerstats.qc @@ -433,82 +433,176 @@ void PlayerStats_EndMatch(float finished) } } +#endif // SVQC + //// WIP -zykure -/* - format spec: +float playerinfo_db; +string playerinfo_last; +string playerinfo_events_last; +.float playerid; - A collection of lines of the format SPACE NEWLINE, where - is always a single character. +void PlayerInfo_AddPlayer(entity e) +{ + string s; - The following keys are defined: + if(playerinfo_db < 0) + return; - V: format version (always a fixed number) - this MUST be the first line! - #: comment (MUST be ignored by any parser) - R: release information on the server - T: time at which the game ended - G: game type - O: mod name (icon request) as in server browser - M: map name - I: match ID (see "matchid" in g_world.qc - S: "hostname" of the server - C: number of "unpure" cvar changes - U: UDP port number of the server - D: duration of the match - P: player ID of an existing player; this also sets the owner for all following "n", "e" and "t" lines (lower case!) - Q: team number of an existing team (format: team#NN); this also sets the owner for all following "e" lines (lower case!) - n: nickname of the player (optional) - t: team ID - i: player index - e: followed by an event name, a space, and the event count/score - event names can be: - alivetime: total playing time of the player - avglatency: average network latency compounded throughout the match - wins: number of games won (can only be set if matches is set) - matches: number of matches played to the end (not aborted by map switch) - joins: number of matches joined (always 1 unless player never played during the match) - scoreboardvalid: set to 1 if the player was there at the end of the match - total-: total score of that scoreboard item - scoreboard-: end-of-game score of that scoreboard item (can differ in non-team games) - achievement-: achievement counters (their "count" is usually 1 if nonzero at all) - kills-: number of kills against the indexed player - rank : rank of player - acc--hit: total damage dealt - acc--fired: total damage that all fired projectiles *could* have dealt - acc--cnt-hit: amount of shots that actually hit - acc--cnt-fired: amount of fired shots - acc--frags: amount of frags dealt by weapon + s = sprintf("#%d", e.playerid); - Response format (not used yet): see https://gist.github.com/4284222 -*/ -/* -void PlayerStatsEntity_ready(entity fh, entity player_stats, float status) + string key; + key = sprintf("%s:*", s); + + string p; + p = db_get(playerinfo_db, key); + if(p == "") + { + if(playerinfo_last) + { + db_put(playerinfo_db, key, playerinfo_last); + strunzone(playerinfo_last); + } + else + db_put(playerinfo_db, key, "#"); + playerinfo_last = strzone(ftos(e.playerid)); + print(" Added player ", s, " to playerinfo_db\n"); + } +} + +void PlayerInfo_AddItem(entity e, string item_id, string val) { + if(playerinfo_db < 0) + return; + + string key; + key = sprintf("*:%s", item_id); + + string p; + p = db_get(playerinfo_db, key); + if(p == "") + { + if(playerinfo_events_last) + { + db_put(playerinfo_db, key, playerinfo_events_last); + strunzone(playerinfo_events_last); + } + else + db_put(playerinfo_db, key, "#"); + playerinfo_events_last = strzone(item_id); + } + + key = sprintf("#%d:%s", e.playerid, item_id); + db_put(playerinfo_db, key, val); + + print("Added event ", key, "=", val, " to playerinfo_db\n"); +} + +string PlayerInfo_GetItem(entity e, string item_id) +{ + if(playerinfo_db < 0) + return string_null; + + string key; + key = sprintf("#%d:%s", e.playerid, item_id); + return db_get(playerinfo_db, key); +} + +void PlayerInfo_ready(entity fh, entity p, float status) +{ + float n; string s; - string key, value; + + PlayerInfo_AddPlayer(p); switch(status) { case URL_READY_CANREAD: - print("Got response from player stats server:\n"); + print("-- Got response from player stats server:\n"); + float in_group = FALSE; + string gametype = string_null; while((s = url_fgets(fh))) { - print(" ", s, "\n"); + print(" >> ", s, "\n"); + + string key = string_null, value = string_null, data = string_null; + + n = tokenizebyseparator(s, " "); // key (value) data + if (n == 1) + { + if (argv(0) == "}") + in_group = FALSE; + } + else if (n == 2) + { + key = argv(0); + data = argv(1); + } + else if (n == 3) + { + if (argv(0) == "{") + { + in_group = TRUE; + key = argv(1); + data = argv(2); + } + else + { + key = argv(0); + value = argv(1); + data = argv(2); + } + } + else if (n == 4) + { + key = argv(0); + value = argv(1); + data = argv(2); + } + else + continue; + + if (data == "") + continue; - key = substring(s, 0, 1); - value = substring(s, 2, -1); if (key == "#") + // comment continue; else if (key == "V") // version - continue; + PlayerInfo_AddItem(p, "_version", data); + else if (key == "R") + // watermark + PlayerInfo_AddItem(p, "_release", data); + else if (key == "T") + // timestamp + PlayerInfo_AddItem(p, "_time", data); + else if (key == "S") + // stats page URL + PlayerInfo_AddItem(p, "_statsurl", data); else if (key == "P") - player_stats.playerid = stof(value); + // player hashkey + PlayerInfo_AddItem(p, "_hashkey", data); else if (key == "n") - player_stats.playernick = value; + // player nick + PlayerInfo_AddItem(p, "_playernick", data); + else if (key == "i") + // xonstats id + PlayerInfo_AddItem(p, "_playerid", data); + else if (key == "G" && in_group) + gametype = data; + else if (key == "e" && value != "") + { + if (gametype == "") + PlayerInfo_AddItem(p, value, data); + else + PlayerInfo_AddItem(p, sprintf("%s-%s", gametype, value), data); + } + else + continue; } - print("End of response.\n"); + print("-- End of response.\n"); url_fclose(fh); break; case URL_READY_CLOSED: @@ -522,16 +616,40 @@ void PlayerStatsEntity_ready(entity fh, entity player_stats, float status) } } -void PlayerStats_GetPlayerInfo(entity p) +void PlayerInfo_Init() { - string uri; + playerinfo_db = -1; + playerinfo_db = db_create(); +} + +void PlayerInfo_Retrieve(entity p) +{ + if(playerinfo_db < 0) + return; + string uri = "", hash = ""; +/* +#ifdef SVQC uri = autocvar_g_playerstats_uri; - if(uri != "") + hash = p.crypto_idfp; +#endif +#ifdef CSQC + uri = "http://stats.xonotic.org"; // FIXME! + hash = "pQBWJrkNzHCMtndkICJacPENGctTNR59rmFS4x91FFo="; // FIXME! +#endif +*/ +#ifdef MENUQC + uri = "http://stats.xonotic.org"; // FIXME! + hash = crypto_getmyidfp(0); + if (hash == "") + print("Error: could not retrive hashkey for player (status: ", ftos(crypto_getmyidstatus(0)), ")\n"); +#endif + print("Checking for player hashkey: <", hash, "> (playerid=", ftos(p.playerid), ")\n"); + + if(uri != "" && hash != "") { - url_single_fopen(strcat(uri, "/"), FILE_READ, PlayerStatsEntity_ready, p.player_stats); + uri = strcat(uri, "/hashkey/", uri_escape(hash)); + print("Retrieving playerstats from URL: ", uri, "\n"); + url_single_fopen(uri, FILE_READ, PlayerInfo_ready, p); } } -*/ - -#endif // SVQC diff --git a/qcsrc/common/playerstats.qh b/qcsrc/common/playerstats.qh index 1cc088545..dcc916e1e 100644 --- a/qcsrc/common/playerstats.qh +++ b/qcsrc/common/playerstats.qh @@ -56,9 +56,11 @@ void PlayerStats_AddGlobalInfo(entity p); // call this at the end of the match void PlayerStats_EndMatch(float finished); +#endif //SVQC -//// WIP -zykure -//void PlayerStats_GetPlayerInfo(entity p); +//// WIP -zykure -#endif //SVQC +string PlayerInfo_GetItem(entity e, string item_id); +void PlayerInfo_Init(); +void PlayerInfo_Retrieve(entity p); diff --git a/qcsrc/menu/command/menu_cmd.qc b/qcsrc/menu/command/menu_cmd.qc index 2c0b1edf3..b78108756 100644 --- a/qcsrc/menu/command/menu_cmd.qc +++ b/qcsrc/menu/command/menu_cmd.qc @@ -110,5 +110,14 @@ void GameCommand(string theCommand) return; } + if(argv(0) == "debugstats") + { + entity p = spawn(); + //p.crypto_idfp = "pQBWJrkNzHCMtndkICJacPENGctTNR59rmFS4x91FFo="; // Antibody's hashkey + PlayerInfo_Init(); + PlayerInfo_Retrieve(p); + return; + } + print(_("Invalid command. For a list of supported commands, try menu_cmd help.\n")); } diff --git a/qcsrc/menu/progs.src b/qcsrc/menu/progs.src index b6ea698cd..f0e0bd748 100644 --- a/qcsrc/menu/progs.src +++ b/qcsrc/menu/progs.src @@ -11,10 +11,10 @@ config.qh ../warpzonelib/mathlib.qh ../common/util.qh ../common/test.qh -../common/playerstats.qh oo/base.h +../common/playerstats.qh ../common/teams.qh ../common/constants.qh ../common/mapinfo.qh -- 2.39.2