From 3284dcb2a5984b4609cc261882b21e9412c21b0d Mon Sep 17 00:00:00 2001 From: meag Date: Thu, 17 Sep 2020 09:56:23 +0100 Subject: [PATCH 01/12] PARSING: Support FTE's sv_bigcoords extension --- net_msg.c | 13 +++++++++++++ net_msg.h | 1 + netmsg_parser.c | 21 ++++++++++++++++++++- qw_protocol.h | 11 +++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/net_msg.c b/net_msg.c index e63dbf3..a17c8bb 100644 --- a/net_msg.c +++ b/net_msg.c @@ -4,6 +4,8 @@ #include "qw_protocol.h" #include "net_msg.h" +static qbool use_bigcoords = false; + sizebuf_t net_message; int msg_readcount; qbool msg_badread; @@ -162,11 +164,17 @@ char *MSG_ReadStringLine(void) float MSG_ReadCoord (void) { + if (use_bigcoords) { + return MSG_ReadFloat(); + } return MSG_ReadShort() * (1.0f / 8); } float MSG_ReadAngle (void) { + if (use_bigcoords) { + return MSG_ReadAngle16(); + } return MSG_ReadChar() * (360.0f / 256); } @@ -237,3 +245,8 @@ void MSG_ReadDeltaUsercmd(usercmd_t *from, usercmd_t *move, int protoversion) move->msec = MSG_ReadByte (); // always sent } } + +void MSG_SetBigCoordSupport(qbool enabled) +{ + use_bigcoords = enabled; +} diff --git a/net_msg.h b/net_msg.h index 0a5c9ca..01a4311 100644 --- a/net_msg.h +++ b/net_msg.h @@ -26,5 +26,6 @@ float MSG_ReadAngle16 (void); #define CM_MSEC (1 << 7) // same as CM_ANGLE2 void MSG_ReadDeltaUsercmd(usercmd_t *from, usercmd_t *move, int protoversion); +void MSG_SetBigCoordSupport(qbool enabled); #endif // __NET_MSG_H__ diff --git a/netmsg_parser.c b/netmsg_parser.c index 4f5af98..1edc61e 100644 --- a/netmsg_parser.c +++ b/netmsg_parser.c @@ -818,7 +818,26 @@ static void NetMsg_Parser_Parse_svc_setangle(void) static void NetMsg_Parser_Parse_svc_serverdata(mvd_info_t *mvd) { - mvd->serverinfo.protocol_version = MSG_ReadLong(); + int protocol; + + while (true) { + protocol = MSG_ReadLong(); + if (protocol == PROTOCOL_VERSION_FTE) { + mvd->extension_flags_fte1 = MSG_ReadLong(); + MSG_SetBigCoordSupport(mvd->extension_flags_fte1 & FTE_PEXT_FLOATCOORDS); + } + else if (protocol == PROTOCOL_VERSION_FTE2) { + mvd->extension_flags_fte2 = MSG_ReadLong(); + } + else if (protocol == PROTOCOL_VERSION_MVD1) { + mvd->extension_flags_mvd = MSG_ReadLong(); + } + else { + break; + } + } + + mvd->serverinfo.protocol_version = protocol; mvd->serverinfo.servercount = MSG_ReadLong(); // Gamedir. diff --git a/qw_protocol.h b/qw_protocol.h index 055d989..d75634b 100644 --- a/qw_protocol.h +++ b/qw_protocol.h @@ -546,6 +546,10 @@ typedef struct mvd_info_s log_event_t *log_events_tail; log_event_t *log_events_head; + + unsigned int extension_flags_fte1; + unsigned int extension_flags_fte2; + unsigned int extension_flags_mvd; } mvd_info_t; // usercmd button bits @@ -584,4 +588,11 @@ typedef struct temp_entity_list_s temp_entity_list_t temp_entities; +// Protocol extensions +#define PROTOCOL_VERSION_FTE (('F'<<0) + ('T'<<8) + ('E'<<16) + ('X' << 24)) //fte extensions. +#define PROTOCOL_VERSION_FTE2 (('F'<<0) + ('T'<<8) + ('E'<<16) + ('2' << 24)) //fte extensions. +#define PROTOCOL_VERSION_MVD1 (('M'<<0) + ('V'<<8) + ('D'<<16) + ('1' << 24)) //mvdsv extensions. + +#define FTE_PEXT_FLOATCOORDS 0x00008000 + #endif // __QW_PROTOCOL_H__ From f15c2c9e08384a2d4e4523f0e491d708d026e346 Mon Sep 17 00:00:00 2001 From: meag Date: Thu, 17 Sep 2020 10:01:16 +0100 Subject: [PATCH 02/12] BUILD: Visual Studio update --- .gitignore | 4 ++ mvdparser.sln | 11 +++- mvdparser.vcxproj | 122 ++++++++++++++++++++++++++++++++++++++ mvdparser.vcxproj.filters | 81 +++++++++++++++++++++++++ shared.c | 3 +- 5 files changed, 217 insertions(+), 4 deletions(-) create mode 100644 .gitignore create mode 100644 mvdparser.vcxproj create mode 100644 mvdparser.vcxproj.filters diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1da14b5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.vs +Debug +Release +*.vcxproj.user diff --git a/mvdparser.sln b/mvdparser.sln index 4cc9b95..d5e8e56 100644 --- a/mvdparser.sln +++ b/mvdparser.sln @@ -1,7 +1,9 @@  -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mvdparser", "mvdparser.vcproj", "{116496EC-DD8D-4C48-8965-0D4961C76504}" +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30309.148 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mvdparser", "mvdparser.vcxproj", "{116496EC-DD8D-4C48-8965-0D4961C76504}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,4 +19,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B18BE4CC-108E-4DB5-9241-BC6FBCBA96EC} + EndGlobalSection EndGlobal diff --git a/mvdparser.vcxproj b/mvdparser.vcxproj new file mode 100644 index 0000000..f101c90 --- /dev/null +++ b/mvdparser.vcxproj @@ -0,0 +1,122 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {116496EC-DD8D-4C48-8965-0D4961C76504} + mvdparser + Win32Proj + + + + Application + v142 + Unicode + true + + + Application + v142 + Unicode + + + + + + + + + + + + + <_ProjectFileVersion>16.0.30028.132 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + CompileAsC + + + winmm.lib;%(AdditionalDependencies) + true + Console + 500000000 + 500000000 + MachineX86 + + + + + WIN32;_CONSOLE;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + + Level3 + ProgramDatabase + + + winmm.lib;%(AdditionalDependencies) + NotSet + $(OutDir)$(ProjectName).exe + false + Console + 500000000 + 500000000 + true + true + MachineX86 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mvdparser.vcxproj.filters b/mvdparser.vcxproj.filters new file mode 100644 index 0000000..da8c11c --- /dev/null +++ b/mvdparser.vcxproj.filters @@ -0,0 +1,81 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/shared.c b/shared.c index bc4c27c..46d2424 100644 --- a/shared.c +++ b/shared.c @@ -186,7 +186,8 @@ size_t strlcat(char *dst, const char *src, size_t siz) return(dlen + (s - src)); /* count does not include NUL */ } -#ifdef _MSC_VER +// Implemented in later versions of Visual Studio (https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010) +#if defined(_MSC_VER) && _MSC_VER < 1900 int snprintf(char *buffer, size_t count, char const *format, ...) { int ret; From de93b9d3c5c203bb4d26e992576846c6552b3d85 Mon Sep 17 00:00:00 2001 From: meag Date: Thu, 17 Sep 2020 17:18:54 +0100 Subject: [PATCH 03/12] FRAGFILES: Support 2009+ ezQuake format (with tracker image) https://github.com/ezQuake/ezquake-source/commit/32fdd0bde4fbe6172891e1425d1c7deba932e6c2#diff-2809769a47bfa0633caa4c0a7f5afb78 --- frag_parser.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frag_parser.c b/frag_parser.c index 2ecd48e..a20d5c2 100644 --- a/frag_parser.c +++ b/frag_parser.c @@ -203,6 +203,12 @@ static void InitFragDefs(void) goto nextline; \ } +#define FRAGS_CHECKARGS3(x, y, z) \ + if (c != x && c != y && c != z) { \ + Sys_PrintError("Fragfile warning (line %d): %d, %d or %d tokens expected\n", line, x, y, z); \ + goto nextline; \ + } + #define FRAGS_CHECK_VERSION_DEFINED() \ if (!gotversion) { \ Sys_PrintError("Fragfile error: #FRAGFILE VERSION must be defined at the head of the file\n"); \ @@ -345,7 +351,7 @@ qbool LoadFragFile(char *filename, qbool quiet) if (!strcasecmp(Cmd_Argv(1), "WEAPON_CLASS") || !strcasecmp(Cmd_Argv(1), "WC")) { - FRAGS_CHECKARGS2(4, 5); + FRAGS_CHECKARGS3(4, 5, 6); token = Cmd_Argv(2); if (!strcasecmp(token, "NOWEAPON") || !strcasecmp(token, "NONE") || !strcasecmp(token, "NULL")) From a224e1d3068856e71c275f238f0060151d2f8d9b Mon Sep 17 00:00:00 2001 From: meag Date: Thu, 17 Sep 2020 17:20:41 +0100 Subject: [PATCH 04/12] OUTPUT: Support player separators & match terminator --- logger.c | 8 ++++++++ logger.h | 4 +++- mvd_parser.c | 6 ++++++ netmsg_parser.c | 6 ++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/logger.c b/logger.c index a24b4f7..820b0e8 100644 --- a/logger.c +++ b/logger.c @@ -102,6 +102,14 @@ static log_eventlogger_type_t Log_ParseEventloggerType(const char *event_logger_ { return LOG_MATCHEND_ALL; } + else if (!strcasecmp(event_logger_type, "MATCHEND_ALL_BETWEEN")) + { + return LOG_MATCHEND_ALL_BETWEEN; + } + else if (!strcasecmp(event_logger_type, "MATCHEND_FINAL")) + { + return LOG_MATCHEND_FINAL; + } else if (!strcasecmp(event_logger_type, "DEMOSTART")) { return LOG_DEMOSTART; diff --git a/logger.h b/logger.h index bfffb77..4eebb07 100644 --- a/logger.h +++ b/logger.h @@ -29,7 +29,9 @@ typedef enum log_eventlogger_type_s LOG_DEMOEND, LOG_SPAWN, LOG_ITEMPICKUP, - LOG_WEAPONDROP + LOG_WEAPONDROP, + LOG_MATCHEND_FINAL, + LOG_MATCHEND_ALL_BETWEEN } log_eventlogger_type_t; typedef struct log_outputfile_template_s diff --git a/mvd_parser.c b/mvd_parser.c index 6e766cd..8257583 100644 --- a/mvd_parser.c +++ b/mvd_parser.c @@ -485,6 +485,7 @@ qbool MVD_Parser_StartParse(char *demopath, byte *mvdbuf, long filelen) if (!mvd.serverinfo.match_ended) { int i; + qbool any = false; Log_Event(&logger, &mvd, LOG_MATCHEND, -1); @@ -496,8 +497,13 @@ qbool MVD_Parser_StartParse(char *demopath, byte *mvdbuf, long filelen) continue; } + if (any) + Log_Event(&logger, &mvd, LOG_MATCHEND_ALL_BETWEEN, i); Log_Event(&logger, &mvd, LOG_MATCHEND_ALL, i); + any = true; } + + Log_Event(&logger, &mvd, LOG_MATCHEND_FINAL, -1); } Log_Event(&logger, &mvd, LOG_DEMOEND, -1); diff --git a/netmsg_parser.c b/netmsg_parser.c index 1edc61e..4c5dfc2 100644 --- a/netmsg_parser.c +++ b/netmsg_parser.c @@ -711,6 +711,7 @@ static void NetMsg_Parser_Parse_svc_print(mvd_info_t *mvd) else if (!strncmp(str, "The match is over", 17)) { int i; + qbool any = false; mvd->serverinfo.match_ended = true; Log_Event(&logger, mvd, LOG_MATCHEND, -1); @@ -723,8 +724,13 @@ static void NetMsg_Parser_Parse_svc_print(mvd_info_t *mvd) continue; } + if (any) + Log_Event(&logger, mvd, LOG_MATCHEND_ALL_BETWEEN, i); Log_Event(&logger, mvd, LOG_MATCHEND_ALL, i); + any = true; } + + Log_Event(&logger, mvd, LOG_MATCHEND_FINAL, -1); } else if (strstr(str, "overtime follows")) { From 3b285e2473362d2d96fa00ed4f9f430525c985ac Mon Sep 17 00:00:00 2001 From: meag Date: Thu, 17 Sep 2020 17:20:55 +0100 Subject: [PATCH 05/12] PARSING: newlines stripped from end of line --- netmsg_parser.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/netmsg_parser.c b/netmsg_parser.c index 4c5dfc2..27dbd8b 100644 --- a/netmsg_parser.c +++ b/netmsg_parser.c @@ -659,6 +659,9 @@ static void NetMsg_Parser_Parse_svc_print(mvd_info_t *mvd) strlcpy(str, MSG_ReadString(), sizeof(str)); // TODO : Check for frag messages spread over several svc_prints older mods/servers does this crap :( + if (str[strlen(str) - 1] == '\n') { + str[strlen(str) - 1] = '\0'; + } Sys_PrintDebug(5, "svc_print: (%s) RAW: %s\n", print_strings[level], str); Sys_PrintDebug(1, "svc_print: (%s) %s\n", print_strings[level], Sys_RedToWhite(str)); From 879d4b86990c6b0911413322a53a4f63808e05ef Mon Sep 17 00:00:00 2001 From: meag Date: Thu, 17 Sep 2020 17:22:02 +0100 Subject: [PATCH 06/12] FORMATS: Support encoding values in xml/json Based on file extension --- logger.c | 190 +++++++++++++++++++++++++++++++++++++++++++++++++++---- logger.h | 9 +++ 2 files changed, 185 insertions(+), 14 deletions(-) diff --git a/logger.c b/logger.c index 820b0e8..b9b5773 100644 --- a/logger.c +++ b/logger.c @@ -6,7 +6,7 @@ logger_t logger; -char *LogVarValueAsString(mvd_info_t *mvd, const char *varname, int player_num); +char *LogVarValueAsString(mvd_info_t *mvd, const char *varname, int player_num, encoding_mode_t encoding); #define LOG_CHECK_NUMARGS(num) \ { \ @@ -412,7 +412,7 @@ qbool Log_ParseOutputTemplates(logger_t *logger, const char *template_file) return true; } -char *Log_ExpandTemplateString(logger_t *logger, mvd_info_t *mvd, const char *template_string, int player_num, int *output_len) +char *Log_ExpandTemplateString(logger_t *logger, mvd_info_t *mvd, const char *template_string, int player_num, int *output_len, encoding_mode_t encoding) { char var_value[1024]; char tmp[1024]; @@ -466,7 +466,7 @@ char *Log_ExpandTemplateString(logger_t *logger, mvd_info_t *mvd, const char *te // Expand the variable based on the current mvd context / player. snprintf(tmp, min((var_end - var_start), sizeof(tmp)), "%s", var_start); - strlcpy(var_value, LogVarValueAsString(mvd, tmp, player_num), sizeof(var_value)); + strlcpy(var_value, LogVarValueAsString(mvd, tmp, player_num, encoding), sizeof(var_value)); // Add the value to the output string. vv = var_value; @@ -554,10 +554,11 @@ void Log_Event(logger_t *logger, mvd_info_t *mvd, log_eventlogger_type_t type, i int i; int j; int p; + int e; int player_start = player_num; int player_count = 1; - int output_len = 0; - char *output = NULL; + int output_len[encoding_count] = { 0, 0, 0 }; + char *output[encoding_count] = { NULL }; char *expanded_filename = NULL; log_eventlogger_t *eventlogger = NULL; log_outputfile_t *output_file = NULL; @@ -590,7 +591,10 @@ void Log_Event(logger_t *logger, mvd_info_t *mvd, log_eventlogger_type_t type, i } // Expand the event loggers template string into an output string. - output = Q_strdup(Log_ExpandTemplateString(logger, mvd, eventlogger->output_template_string, player_num, &output_len)); + for (j = 0; j < encoding_count; ++j) { + output_len[j] = 0; + output[j] = Q_strdup(Log_ExpandTemplateString(logger, mvd, eventlogger->output_template_string, player_num, &output_len[j], j)); + } // See the above comment for setting player_count for explination. // TODO : Make this more readable by making the stuff inside the for-loop a separate function, and calling it in two separate if-cases instead. @@ -605,7 +609,7 @@ void Log_Event(logger_t *logger, mvd_info_t *mvd, log_eventlogger_type_t type, i // and then write the output to the files. for (j = 0; j < eventlogger->templates_count; j++) { - expanded_filename = Log_ExpandTemplateString(logger, mvd, eventlogger->outputfile_templates[j]->name, p, NULL); + expanded_filename = Log_ExpandTemplateString(logger, mvd, eventlogger->outputfile_templates[j]->name, p, NULL, normal_encoding); // Search for the expanded filename in the output_hashtable. output_file = Log_OutputFilesHashTable_GetValue(logger, expanded_filename); @@ -617,11 +621,23 @@ void Log_Event(logger_t *logger, mvd_info_t *mvd, log_eventlogger_type_t type, i output_file->filename = Q_strdup(expanded_filename); output_file->file = fopen(expanded_filename, "w"); + if (strstr(expanded_filename, ".xml")) { + output_file->encoding = xml_encoding; + } + else if (strstr(expanded_filename, ".json")) { + output_file->encoding = json_encoding; + } + else { + output_file->encoding = normal_encoding; + } + if (!output_file->file) { Q_free(output_file->filename); Q_free(output_file); - Q_free(output); + for (j = 0; j < encoding_count; ++j) { + Q_free(output[j]); + } Sys_Error("Log_Event: Failed to open the file %s (expanded from %s) for output.\n", output_file->filename, eventlogger->outputfile_templates[j]->name); } @@ -652,17 +668,18 @@ void Log_Event(logger_t *logger, mvd_info_t *mvd, log_eventlogger_type_t type, i num_written_to++; }*/ - if (output_len > 0) - { + if (output_len[output_file->encoding] > 0) { // Write the expanded output to the file. - fwrite(output, sizeof(char), output_len, output_file->file); + fwrite(output[output_file->encoding], sizeof(char), output_len[output_file->encoding], output_file->file); fflush(output_file->file); } } } } - Q_free(output); + for (j = 0; j < encoding_count; ++j) { + Q_free(output[j]); + } } void Log_OutputFilesHashTable_Clear(logger_t *logger) @@ -1388,7 +1405,140 @@ void LogVarHashTable_AddValue(logvar_t **hashtable, logvar_t *logvar) } } -char *LogVarValueAsString(mvd_info_t *mvd, const char *varname, int player_num) +#define MAX_STRINGS 128 + +static char* json_string(const char* input) +{ + // >>>> like va(...) ... eugh + static char string[MAX_STRINGS][1024]; + static int index = 0; + char* ch, * start; + + index %= MAX_STRINGS; + // <<<< + + start = ch = string[index++]; + while (*input) { + unsigned char current = *input; + + if (ch - start >= 1000) { + break; + } + + if (current == '\\' || current == '"') { + *ch++ = '\\'; + *ch++ = current; + } + else if (current == '\n') { + *ch++ = '\\'; + *ch++ = 'n'; + } + else if (current == '\r') { + *ch++ = '\\'; + *ch++ = 'r'; + } + else if (current == '\b') { + *ch++ = '\\'; + *ch++ = 'b'; + } + else if (current == '\t') { + *ch++ = '\\'; + *ch++ = 't'; + } + else if (current == '\f') { + *ch++ = '\\'; + *ch++ = 'f'; + } + else if (current < ' ' || current >= 128) { + *ch++ = '\\'; + *ch++ = 'u'; + *ch++ = '0'; + *ch++ = '0'; + if (current < 16) { + *ch++ = '0'; + *ch++ = "0123456789ABCDEF"[(int)current]; + } + else { + *ch++ = "0123456789ABCDEF"[((int)(current)) >> 4]; + *ch++ = "0123456789ABCDEF"[((int)(current)) & 15]; + } + } + else { + *ch++ = current; + } + ++input; + } + *ch = '\0'; + return start; +} + +char* xml_string(const char* original) +{ + static char string[MAX_STRINGS][1024]; + static int index = 0; + int length = strlen(original); + int newlength = 0; + int i = 0; + + index %= MAX_STRINGS; + + memset(string[index], 0, sizeof(string[0])); + + for (i = 0; i < length; ++i) { + unsigned char ch = (unsigned char)original[i]; + + if (ch == '<') { + if (newlength < sizeof(string[0]) - 4) { + string[index][newlength++] = '&'; + string[index][newlength++] = 'l'; + string[index][newlength++] = 't'; + string[index][newlength++] = ';'; + } + } + else if (ch == '>') { + if (newlength < sizeof(string[0]) - 4) { + string[index][newlength++] = '&'; + string[index][newlength++] = 'g'; + string[index][newlength++] = 't'; + string[index][newlength++] = ';'; + } + } + else if (ch == '"') { + if (newlength < sizeof(string[0]) - 5) { + string[index][newlength++] = '&'; + string[index][newlength++] = '#'; + string[index][newlength++] = '3'; + string[index][newlength++] = '4'; + string[index][newlength++] = ';'; + } + } + else if (ch == '&') { + if (newlength < sizeof(string[0]) - 5) { + string[index][newlength++] = '&'; + string[index][newlength++] = 'a'; + string[index][newlength++] = 'm'; + string[index][newlength++] = 'p'; + string[index][newlength++] = ';'; + } + } + else if (ch == '\'') { + if (newlength < sizeof(string[0]) - 5) { + string[index][newlength++] = '&'; + string[index][newlength++] = '#'; + string[index][newlength++] = '3'; + string[index][newlength++] = '9'; + string[index][newlength++] = ';'; + } + } + else { + string[index][newlength++] = ch; + } + } + + return string[index++]; +} + +char *LogVarValueAsString(mvd_info_t *mvd, const char *varname, int player_num, encoding_mode_t encoding) { logvar_t *logvar = LogVarHashTable_GetValue(logvar_hashtable, varname); @@ -1415,7 +1565,19 @@ char *LogVarValueAsString(mvd_info_t *mvd, const char *varname, int player_num) return ""; } - return logvar->func(mvd, logvar->name, player_num); + if (encoding == xml_encoding) { + const char* source = logvar->func(mvd, logvar->name, player_num); + + return xml_string(source); + } + else if (encoding == json_encoding) { + const char* source = logvar->func(mvd, logvar->name, player_num); + + return json_string(source); + } + else { + return logvar->func(mvd, logvar->name, player_num); + } } void LogVarHashTable_Init(void) diff --git a/logger.h b/logger.h index 4eebb07..246840f 100644 --- a/logger.h +++ b/logger.h @@ -7,11 +7,20 @@ #define LOG_OUTPUTFILES_HASHTABLE_SIZE 512 #define LOG_MAX_ID_LENGTH 32 +typedef enum encoding_mode_s { + normal_encoding, + json_encoding, + xml_encoding, + + encoding_count +} encoding_mode_t; + typedef struct log_outputfile_s { char *filename; // Expanded filename. FILE *file; // The file pointer to the opened file. unsigned long filename_hash; // A hash of the expanded filename. + encoding_mode_t encoding; // format to encode strings struct log_outputfile_s *next; // Pointer to the next outputfile (if there's a collision in the hash table). } log_outputfile_t; From 6c5ee776a86b216546ad768a3151b2a3c7a79ec4 Mon Sep 17 00:00:00 2001 From: meag Date: Thu, 17 Sep 2020 17:26:55 +0100 Subject: [PATCH 07/12] TEMPLATE: Add .json template, with suicides & teamkills --- logger.c | 14 ++++++++- template.dat | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/logger.c b/logger.c index b9b5773..27a89cc 100644 --- a/logger.c +++ b/logger.c @@ -709,6 +709,16 @@ void Log_OutputFilesHashTable_Clear(logger_t *logger) // Log variables // ============================================================================ +static char* LogVar_suicides(mvd_info_t* mvd, const char* varname, int player_num) +{ + return va("%d", mvd->fragstats[player_num].suicides); +} + +static char* LogVar_teamkills(mvd_info_t* mvd, const char* varname, int player_num) +{ + return va("%d", mvd->fragstats[player_num].teamkills); +} + static char *LogVar_name(mvd_info_t *mvd, const char *varname, int player_num) { return mvd->players[player_num].name; @@ -1360,7 +1370,9 @@ logvar_t logvar_list[] = LOGVAR_DEFINE(topcolor, LOGVAR_PLAYER), LOGVAR_DEFINE(bottomcolor, LOGVAR_PLAYER), LOGVAR_DEFINE(droppedweapon, LOGVAR_PLAYER), - LOGVAR_DEFINE(droppedweaponstr, LOGVAR_PLAYER) + LOGVAR_DEFINE(droppedweaponstr, LOGVAR_PLAYER), + LOGVAR_DEFINE(teamkills, LOGVAR_PLAYER), + LOGVAR_DEFINE(suicides, LOGVAR_PLAYER) }; #define LOGVARS_LIST_SIZE (sizeof(logvar_list) / sizeof(logvar_t)) diff --git a/template.dat b/template.dat index a798be3..8fc4153 100644 --- a/template.dat +++ b/template.dat @@ -128,3 +128,89 @@ demotime=%demotime%;matchtime=%matchtime%;quake_loc_x=%posx%;quake_loc_y=%posy%; //////////////////////////////////////////////////////////// +#FILE json %demoname%.json + +#EVENT MATCHEND 6 +{ + "hostname": "%hostname%", + "map_name": "%map%", + "map_file": "??", + "gamedir": "%gamedir%", + "serverinfo": "%serverinfo%", + "fraglimit": "%fraglimit%", + "timelimit": "%timelimit%", + "deathmatch": "%deathmatchmode%", + "maxfps": "%maxfps%", + "teamplay": "%teamplay%", + "z_ext": "%zext%", + "fpd": "%fpd%", + "maxclients": "%maxclients%", + "maxspectators": "%maxspectators%", + "watervis": "%watervis%", + "gametype": "unknown", + "version": "%serverversion%", + "mod": "%mod%", + "players": [ +#EVENT_END + +#EVENT MATCHEND_ALL 7 + { + "client": "%client%", + "name_sanatized": "%name%", + "name_raw": "%nameraw%", + "player_num": "%playernum%", + "player_id": "%playerid%", + "frags": "%frags%", + "spectator": "%spectator%", + "userinfo": "%userinfo%", + "top_color": "%topcolor%", + "bottom_color": "%bottomcolor%", + "team_sanatized": "%team%", + "team_raw": "%teamraw%", + "avg_packetloss": "%avgpl%", + "max_packetloss": "%maxpl%", + "min_packetloss": "%minpl%", + "avg_ping": "%avgping%", + "max_ping": "%maxping%", + "min_ping": "%minping%", + "sg_shots": "%sgshots%", + "avg_speed": "%avgspeed%", + "max_speed": "%maxspeed%", + "distance_moved": "%distancemoved%", + "stats": { + "Axe":{"Damage":0,"Drop":0,"Pickup":0}, + "Deaths": "%deaths%", + "GreenArmor":{"Damage_Absorbed":0,"Pickup":%gacount%}, + "GrenadeLauncher":{"Damage":0,"Drop":%gldrop%,"Pickup":%glcount%,"Shots":%glshots%}, + "Kills":27, + "LightningGun":{"Damage":0,"Drop":%lgdrop%,"Pickup":%lgcount%,"Shots":%lgshots%}, + "MegaHealth":{"Drop":0,"Pickup":%mhcount%}, + "NailGun":{"Damage":0,"Drop":%ngdrop%,"Pickup":%ngcount%,"Shots":%ngshots%}, + "Pentagram":{"Drop":0,"Pickup":%pentcount%}, + "Quad":{"Drop":0,"Pickup":%quadcount%}, + "RedArmor":{"Damage_Absorbed":0,"Pickup":%racount%}, + "Ring":{"Drop":0,"Pickup":%ringcount%}, + "RocketLauncher":{"Damage":0,"Drop":%rldrop%,"Pickup":%rlcount%,"Shots":%rlshots%}, + "Shotgun":{"Damage":0,"Drop":0,"Pickup":0}, + "Suicides":%suicides%, + "SuperNailGun":{"Damage":0,"Drop":%sngdrop%,"Pickup":%sngcount%,"Shots":%sngshots%}, + "SuperShotgun":{"Damage":0,"Drop":%ssgdrop%,"Pickup":%ssgcount%,"Shots":%ssgshots%}, + "Teamkills":%teamkills%, + "YellowArmor":{"Damage_Absorbed":0,"Pickup":%yacount%} + } + } +#EVENT_END + +#EVENT MATCHEND_ALL_BETWEEN 8 + , +#EVENT_END + +#EVENT MATCHEND_FINAL 9 + ] +} +#EVENT_END + +#OUTPUT 6 json +#OUTPUT 7 json +#OUTPUT 8 json +#OUTPUT 9 json From 8e80b18cdd25c97ca388d7885657c600a075585d Mon Sep 17 00:00:00 2001 From: meag Date: Thu, 17 Sep 2020 20:52:21 +0100 Subject: [PATCH 08/12] FRAGS: Only increase deaths if weapon unknown (/kill?) --- frag_parser.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/frag_parser.c b/frag_parser.c index a20d5c2..5472d0d 100644 --- a/frag_parser.c +++ b/frag_parser.c @@ -681,8 +681,12 @@ void Frags_Parse(mvd_info_t *mvd, char *fragmessage, int level) case mt_suicide : { mvd->fragstats[p1->pnum].suicides++; - p1->death_count++; - Log_Event(&logger, mvd, LOG_DEATH, p1->pnum); + + // If it's a normal suicide then it'll get picked up by health < 0 + if (!mess->wclass_index) { + p1->death_count++; + Log_Event(&logger, mvd, LOG_DEATH, p1->pnum); + } break; } case mt_fragged : From c10f38fefd8354d9a4b1d73be66476b3b7baa7cb Mon Sep 17 00:00:00 2001 From: meag Date: Fri, 18 Sep 2020 09:31:39 +0100 Subject: [PATCH 09/12] VARIABLES: Store map filename & friendly name differently used to return mapname from svc_serverdata and then overwrite with file from serverinfo for consistency with old templates, %map% is still the filename %mapname% is the friendly version shown when connecting --- logger.c | 7 ++++++ netmsg_parser.c | 2 +- qw_protocol.h | 57 +++++++++++++++++++++++++------------------------ 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/logger.c b/logger.c index 27a89cc..9d3a07f 100644 --- a/logger.c +++ b/logger.c @@ -1196,6 +1196,12 @@ static char *LogVar_teamplay(mvd_info_t *mvd, const char *varname, int player_nu } static char *LogVar_map(mvd_info_t *mvd, const char *varname, int player_num) +{ + // to keep old templates correct: used to return mapname from svc_serverdata and then overwrite with file from serverinfo + return mvd->serverinfo.mapfile; +} + +static char* LogVar_mapname(mvd_info_t* mvd, const char* varname, int player_num) { return mvd->serverinfo.mapname; } @@ -1289,6 +1295,7 @@ logvar_t logvar_list[] = LOGVAR_DEFINE(matchtime, LOGVAR_DEMO), LOGVAR_DEFINE(mvdframe, LOGVAR_DEMO), LOGVAR_DEFINE(map, LOGVAR_DEMO), + LOGVAR_DEFINE(mapname, LOGVAR_DEMO), LOGVAR_DEFINE(gamedir, LOGVAR_DEMO), LOGVAR_DEFINE(maxfps, LOGVAR_DEMO), LOGVAR_DEFINE(zext, LOGVAR_DEMO), diff --git a/netmsg_parser.c b/netmsg_parser.c index 27dbd8b..cbc8df6 100644 --- a/netmsg_parser.c +++ b/netmsg_parser.c @@ -791,7 +791,7 @@ static void NetMsg_Parser_ParseServerInfo(mvd_info_t *mvd) snprintf(mvd->serverinfo.mod, sizeof(mvd->serverinfo.mod), "KTX %s build %s", tmp, Info_ValueForKey(mvd->serverinfo.serverinfo, "xbuild")); } - strlcpy(mvd->serverinfo.mapname, Info_ValueForKey(mvd->serverinfo.serverinfo, "map"), sizeof(mvd->serverinfo.mapname)); + strlcpy(mvd->serverinfo.mapfile, Info_ValueForKey(mvd->serverinfo.serverinfo, "map"), sizeof(mvd->serverinfo.mapfile)); strlcpy(mvd->serverinfo.serverversion, Info_ValueForKey(mvd->serverinfo.serverinfo, "*version"), sizeof(mvd->serverinfo.serverversion)); strlcpy(mvd->serverinfo.status, Info_ValueForKey(mvd->serverinfo.serverinfo, "status"), sizeof(mvd->serverinfo.status)); } diff --git a/qw_protocol.h b/qw_protocol.h index d75634b..3a171de 100644 --- a/qw_protocol.h +++ b/qw_protocol.h @@ -462,34 +462,35 @@ typedef struct movevars_s typedef struct server_s { - char serverinfo[2 * MAX_SERVERINFO_STRING]; // Make it larger than allowed. - int protocol_version; - int servercount; - float demotime; - int timelimit; - int fraglimit; - int teamplay; - int deathmatch; - qbool watervis; - char serverversion[MAX_INFO_KEY]; - int maxclients; - int maxspectators; - char mapname[MAX_INFO_KEY]; - int fpd; - char status[MAX_INFO_KEY]; - char gamedir[MAX_QPATH]; - movevars_t movevars; - qbool countdown; - qbool match_started; - qbool match_ended; - qbool match_overtime; - int overtime_minutes; - int maxfps; - int zext; - char hostname[MAX_INFO_STRING]; - char mod[MAX_INFO_STRING]; - qbool player_timed_out; - int player_timout_frame; + char serverinfo[2 * MAX_SERVERINFO_STRING]; // Make it larger than allowed. + int protocol_version; + int servercount; + float demotime; + int timelimit; + int fraglimit; + int teamplay; + int deathmatch; + qbool watervis; + char serverversion[MAX_INFO_KEY]; + int maxclients; + int maxspectators; + char mapname[MAX_INFO_KEY]; // now the friendly name (Blood Run) + char mapfile[MAX_INFO_KEY]; // now the name of the file (ztndm3) + int fpd; + char status[MAX_INFO_KEY]; + char gamedir[MAX_QPATH]; + movevars_t movevars; + qbool countdown; + qbool match_started; + qbool match_ended; + qbool match_overtime; + int overtime_minutes; + int maxfps; + int zext; + char hostname[MAX_INFO_STRING]; + char mod[MAX_INFO_STRING]; + qbool player_timed_out; + int player_timout_frame; } server_t; typedef enum log_eventtype_s From e4beb63eae6fea500d45a67c3be7acd5df418161 Mon Sep 17 00:00:00 2001 From: meag Date: Fri, 18 Sep 2020 09:32:21 +0100 Subject: [PATCH 10/12] MINOR: template.dat saved with CRLF --- template.dat | 432 +++++++++++++++++++++++++-------------------------- 1 file changed, 216 insertions(+), 216 deletions(-) diff --git a/template.dat b/template.dat index 8fc4153..ae735bf 100644 --- a/template.dat +++ b/template.dat @@ -1,216 +1,216 @@ - -//////////////////////////////////////////////////////////// - -#FILE server %demoname%-server.log - -#EVENT MATCHEND 0 -hostname=%hostname% -description="" -address="" -#EVENT_END - -#OUTPUT 0 server - -//////////////////////////////////////////////////////////// - -#FILE map %demoname%-map.log - -#EVENT MATCHEND 1 -map=%map% -#EVENT_END - -#OUTPUT 1 map - -//////////////////////////////////////////////////////////// - -#FILE serversettings %demoname%-serversettings.log - -// STR_TO_DATE('%matchstartyear%-%matchstartmonth%-%matchstartdate% %matchstarthour%:%matchstartminute%', '%%Y-%%c-%%e %%k:%%i') - -#EVENT MATCHEND 2 -gamedir=%gamedir% -serverinfo=%serverinfo% -fraglimit=%fraglimit% -timelimit=%timelimit% -deathmatch=%deathmatchmode% -maxfps=%maxfps% -teamplay=%teamplay% -z_ext=%zext% -fpd=%fpd% -maxclients=%maxclients% -maxspectators=%maxspectators% -watervis=%watervis% -gametype=unknown -version=%serverversion% -mod=%mod% -#EVENT_END - -#OUTPUT 2 serversettings - -//////////////////////////////////////////////////////////// - -#FILE demo %demoname%-demo.log - -#EVENT MATCHEND 3 -mvdframe=%mvdframe% -demotime=%demotime% -matchstartdate=%matchstartfulldate% -#EVENT_END - -#OUTPUT 3 demo - -//////////////////////////////////////////////////////////// - -#FILE player %demoname%-%playernum%-player.log - -#EVENT MATCHEND_ALL 4 -client=%client% -name=%name% -name_raw=%nameraw% -player_num=%playernum% -player_id=%playerid% -frags=%frags% -spectator=%spectator% -userinfo=%userinfo% -top_color=%topcolor% -bottom_color=%bottomcolor% -teamname=%team% -teamname_raw=%teamraw% -deaths=%deaths% -avg_packetloss=%avgpl% -max_packetloss=%maxpl% -min_packetloss=%minpl% -avg_ping=%avgping% -max_ping=%maxping% -min_ping=%minping% -ga_count=%gacount% -ya_count=%yacount% -ra_count=%racount% -ssg_count=%ssgcount% -ng_count=%ngcount% -sng_count=%sngcount% -gl_count=%glcount% -rl_count=%rlcount% -lg_count=%lgcount% -ssg_drop=%ssgdrop% -ng_drop=%ngdrop% -sng_drop=%sngdrop% -gl_drop=%gldrop% -rl_drop=%rldrop% -lg_drop=%lgdrop% -sg_shots=%sgshots% -ssg_shots=%ssgshots% -ng_shots=%ngshots% -sng_shots=%sngshots% -gl_shots=%glshots% -rl_shots=%rlshots% -lg_shots=%lgshots% -mh_count=%mhcount% -quad_count=%quadcount% -pent_count=%pentcount% -ring_count=%ringcount% -avg_speed=%avgspeed% -max_speed=%maxspeed% -distance_moved=%distancemoved% -#EVENT_END - -#OUTPUT 4 player - -//////////////////////////////////////////////////////////// - -#FILE events %demoname%-%playernum%-events.log - -#EVENT DEATH 5 -demotime=%demotime%;matchtime=%matchtime%;quake_loc_x=%posx%;quake_loc_y=%posy%;quake_loc_z=%posz%;player=%playernum%;type=DEATH -#EVENT_END - -#OUTPUT 5 events - -//////////////////////////////////////////////////////////// - -#FILE json %demoname%.json - -#EVENT MATCHEND 6 -{ - "hostname": "%hostname%", - "map_name": "%map%", - "map_file": "??", - "gamedir": "%gamedir%", - "serverinfo": "%serverinfo%", - "fraglimit": "%fraglimit%", - "timelimit": "%timelimit%", - "deathmatch": "%deathmatchmode%", - "maxfps": "%maxfps%", - "teamplay": "%teamplay%", - "z_ext": "%zext%", - "fpd": "%fpd%", - "maxclients": "%maxclients%", - "maxspectators": "%maxspectators%", - "watervis": "%watervis%", - "gametype": "unknown", - "version": "%serverversion%", - "mod": "%mod%", - "players": [ -#EVENT_END - -#EVENT MATCHEND_ALL 7 - { - "client": "%client%", - "name_sanatized": "%name%", - "name_raw": "%nameraw%", - "player_num": "%playernum%", - "player_id": "%playerid%", - "frags": "%frags%", - "spectator": "%spectator%", - "userinfo": "%userinfo%", - "top_color": "%topcolor%", - "bottom_color": "%bottomcolor%", - "team_sanatized": "%team%", - "team_raw": "%teamraw%", - "avg_packetloss": "%avgpl%", - "max_packetloss": "%maxpl%", - "min_packetloss": "%minpl%", - "avg_ping": "%avgping%", - "max_ping": "%maxping%", - "min_ping": "%minping%", - "sg_shots": "%sgshots%", - "avg_speed": "%avgspeed%", - "max_speed": "%maxspeed%", - "distance_moved": "%distancemoved%", - "stats": { - "Axe":{"Damage":0,"Drop":0,"Pickup":0}, - "Deaths": "%deaths%", - "GreenArmor":{"Damage_Absorbed":0,"Pickup":%gacount%}, - "GrenadeLauncher":{"Damage":0,"Drop":%gldrop%,"Pickup":%glcount%,"Shots":%glshots%}, - "Kills":27, - "LightningGun":{"Damage":0,"Drop":%lgdrop%,"Pickup":%lgcount%,"Shots":%lgshots%}, - "MegaHealth":{"Drop":0,"Pickup":%mhcount%}, - "NailGun":{"Damage":0,"Drop":%ngdrop%,"Pickup":%ngcount%,"Shots":%ngshots%}, - "Pentagram":{"Drop":0,"Pickup":%pentcount%}, - "Quad":{"Drop":0,"Pickup":%quadcount%}, - "RedArmor":{"Damage_Absorbed":0,"Pickup":%racount%}, - "Ring":{"Drop":0,"Pickup":%ringcount%}, - "RocketLauncher":{"Damage":0,"Drop":%rldrop%,"Pickup":%rlcount%,"Shots":%rlshots%}, - "Shotgun":{"Damage":0,"Drop":0,"Pickup":0}, - "Suicides":%suicides%, - "SuperNailGun":{"Damage":0,"Drop":%sngdrop%,"Pickup":%sngcount%,"Shots":%sngshots%}, - "SuperShotgun":{"Damage":0,"Drop":%ssgdrop%,"Pickup":%ssgcount%,"Shots":%ssgshots%}, - "Teamkills":%teamkills%, - "YellowArmor":{"Damage_Absorbed":0,"Pickup":%yacount%} - } - } -#EVENT_END - -#EVENT MATCHEND_ALL_BETWEEN 8 - , -#EVENT_END - -#EVENT MATCHEND_FINAL 9 - ] -} -#EVENT_END - -#OUTPUT 6 json -#OUTPUT 7 json -#OUTPUT 8 json -#OUTPUT 9 json + +//////////////////////////////////////////////////////////// + +#FILE server %demoname%-server.log + +#EVENT MATCHEND 0 +hostname=%hostname% +description="" +address="" +#EVENT_END + +#OUTPUT 0 server + +//////////////////////////////////////////////////////////// + +#FILE map %demoname%-map.log + +#EVENT MATCHEND 1 +map=%map% +#EVENT_END + +#OUTPUT 1 map + +//////////////////////////////////////////////////////////// + +#FILE serversettings %demoname%-serversettings.log + +// STR_TO_DATE('%matchstartyear%-%matchstartmonth%-%matchstartdate% %matchstarthour%:%matchstartminute%', '%%Y-%%c-%%e %%k:%%i') + +#EVENT MATCHEND 2 +gamedir=%gamedir% +serverinfo=%serverinfo% +fraglimit=%fraglimit% +timelimit=%timelimit% +deathmatch=%deathmatchmode% +maxfps=%maxfps% +teamplay=%teamplay% +z_ext=%zext% +fpd=%fpd% +maxclients=%maxclients% +maxspectators=%maxspectators% +watervis=%watervis% +gametype=unknown +version=%serverversion% +mod=%mod% +#EVENT_END + +#OUTPUT 2 serversettings + +//////////////////////////////////////////////////////////// + +#FILE demo %demoname%-demo.log + +#EVENT MATCHEND 3 +mvdframe=%mvdframe% +demotime=%demotime% +matchstartdate=%matchstartfulldate% +#EVENT_END + +#OUTPUT 3 demo + +//////////////////////////////////////////////////////////// + +#FILE player %demoname%-%playernum%-player.log + +#EVENT MATCHEND_ALL 4 +client=%client% +name=%name% +name_raw=%nameraw% +player_num=%playernum% +player_id=%playerid% +frags=%frags% +spectator=%spectator% +userinfo=%userinfo% +top_color=%topcolor% +bottom_color=%bottomcolor% +teamname=%team% +teamname_raw=%teamraw% +deaths=%deaths% +avg_packetloss=%avgpl% +max_packetloss=%maxpl% +min_packetloss=%minpl% +avg_ping=%avgping% +max_ping=%maxping% +min_ping=%minping% +ga_count=%gacount% +ya_count=%yacount% +ra_count=%racount% +ssg_count=%ssgcount% +ng_count=%ngcount% +sng_count=%sngcount% +gl_count=%glcount% +rl_count=%rlcount% +lg_count=%lgcount% +ssg_drop=%ssgdrop% +ng_drop=%ngdrop% +sng_drop=%sngdrop% +gl_drop=%gldrop% +rl_drop=%rldrop% +lg_drop=%lgdrop% +sg_shots=%sgshots% +ssg_shots=%ssgshots% +ng_shots=%ngshots% +sng_shots=%sngshots% +gl_shots=%glshots% +rl_shots=%rlshots% +lg_shots=%lgshots% +mh_count=%mhcount% +quad_count=%quadcount% +pent_count=%pentcount% +ring_count=%ringcount% +avg_speed=%avgspeed% +max_speed=%maxspeed% +distance_moved=%distancemoved% +#EVENT_END + +#OUTPUT 4 player + +//////////////////////////////////////////////////////////// + +#FILE events %demoname%-%playernum%-events.log + +#EVENT DEATH 5 +demotime=%demotime%;matchtime=%matchtime%;quake_loc_x=%posx%;quake_loc_y=%posy%;quake_loc_z=%posz%;player=%playernum%;type=DEATH +#EVENT_END + +#OUTPUT 5 events + +//////////////////////////////////////////////////////////// + +#FILE json %demoname%.json + +#EVENT MATCHEND 6 +{ + "hostname": "%hostname%", + "map_name": "%mapname%", + "map_file": "maps/%map%.bsp", + "gamedir": "%gamedir%", + "serverinfo": "%serverinfo%", + "fraglimit": "%fraglimit%", + "timelimit": "%timelimit%", + "deathmatch": "%deathmatchmode%", + "maxfps": "%maxfps%", + "teamplay": "%teamplay%", + "z_ext": "%zext%", + "fpd": "%fpd%", + "maxclients": "%maxclients%", + "maxspectators": "%maxspectators%", + "watervis": "%watervis%", + "gametype": "unknown", + "version": "%serverversion%", + "mod": "%mod%", + "players": [ +#EVENT_END + +#EVENT MATCHEND_ALL 7 + { + "client": "%client%", + "name_sanatized": "%name%", + "name_raw": "%nameraw%", + "player_num": "%playernum%", + "player_id": "%playerid%", + "frags": "%frags%", + "spectator": "%spectator%", + "userinfo": "%userinfo%", + "top_color": "%topcolor%", + "bottom_color": "%bottomcolor%", + "team_sanatized": "%team%", + "team_raw": "%teamraw%", + "avg_packetloss": "%avgpl%", + "max_packetloss": "%maxpl%", + "min_packetloss": "%minpl%", + "avg_ping": "%avgping%", + "max_ping": "%maxping%", + "min_ping": "%minping%", + "sg_shots": "%sgshots%", + "avg_speed": "%avgspeed%", + "max_speed": "%maxspeed%", + "distance_moved": "%distancemoved%", + "stats": { + "Axe":{"Damage":0,"Drop":0,"Pickup":0}, + "Deaths": "%deaths%", + "GreenArmor":{"Damage_Absorbed":0,"Pickup":%gacount%}, + "GrenadeLauncher":{"Damage":0,"Drop":%gldrop%,"Pickup":%glcount%,"Shots":%glshots%}, + "Kills":27, + "LightningGun":{"Damage":0,"Drop":%lgdrop%,"Pickup":%lgcount%,"Shots":%lgshots%}, + "MegaHealth":{"Drop":0,"Pickup":%mhcount%}, + "NailGun":{"Damage":0,"Drop":%ngdrop%,"Pickup":%ngcount%,"Shots":%ngshots%}, + "Pentagram":{"Drop":0,"Pickup":%pentcount%}, + "Quad":{"Drop":0,"Pickup":%quadcount%}, + "RedArmor":{"Damage_Absorbed":0,"Pickup":%racount%}, + "Ring":{"Drop":0,"Pickup":%ringcount%}, + "RocketLauncher":{"Damage":0,"Drop":%rldrop%,"Pickup":%rlcount%,"Shots":%rlshots%}, + "Shotgun":{"Damage":0,"Drop":0,"Pickup":0}, + "Suicides":%suicides%, + "SuperNailGun":{"Damage":0,"Drop":%sngdrop%,"Pickup":%sngcount%,"Shots":%sngshots%}, + "SuperShotgun":{"Damage":0,"Drop":%ssgdrop%,"Pickup":%ssgcount%,"Shots":%ssgshots%}, + "Teamkills":%teamkills%, + "YellowArmor":{"Damage_Absorbed":0,"Pickup":%yacount%} + } + } +#EVENT_END + +#EVENT MATCHEND_ALL_BETWEEN 8 + , +#EVENT_END + +#EVENT MATCHEND_FINAL 9 + ] +} +#EVENT_END + +#OUTPUT 6 json +#OUTPUT 7 json +#OUTPUT 8 json +#OUTPUT 9 json From 13e28fbb2b1033617d9a9e9023c7f42064dc235d Mon Sep 17 00:00:00 2001 From: meag Date: Fri, 18 Sep 2020 10:33:14 +0100 Subject: [PATCH 11/12] BUFFER OVERRUNS: Null-terminate input files --- shared.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shared.c b/shared.c index 46d2424..8d61354 100644 --- a/shared.c +++ b/shared.c @@ -289,7 +289,8 @@ qbool COM_ReadFile(const char *filename, byte **data, long *filelen) return false; } - (*data) = Q_malloc(sizeof(byte) * len); + (*data) = Q_malloc(sizeof(byte) * (len + 1)); + (*data)[len] = '\0'; num_read = fread((*data), 1, len, f); From 72485cff9b22601ecf8ab2718d012f6ee8e13e58 Mon Sep 17 00:00:00 2001 From: meag Date: Fri, 18 Sep 2020 10:33:58 +0100 Subject: [PATCH 12/12] BUFFER OVERRUNS: Stop if replacing token at end of event text --- logger.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/logger.c b/logger.c index 9d3a07f..1c462f3 100644 --- a/logger.c +++ b/logger.c @@ -482,6 +482,10 @@ char *Log_ExpandTemplateString(logger_t *logger, mvd_info_t *mvd, const char *te } input = var_end; + + if (!input[0]) { + break; + } } } @@ -554,7 +558,6 @@ void Log_Event(logger_t *logger, mvd_info_t *mvd, log_eventlogger_type_t type, i int i; int j; int p; - int e; int player_start = player_num; int player_count = 1; int output_len[encoding_count] = { 0, 0, 0 };