Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MVDPARSER: sv_bigcoords support, fragfile definition update, .json/xml output, some bugfixes #4

Merged
merged 12 commits into from
Sep 19, 2020
Merged
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.vs
Debug
Release
*.vcxproj.user
16 changes: 13 additions & 3 deletions frag_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"); \
Expand Down Expand Up @@ -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"))
Expand Down Expand Up @@ -675,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 :
Expand Down
222 changes: 207 additions & 15 deletions logger.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
{ \
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -404,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];
Expand Down Expand Up @@ -458,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;
Expand All @@ -474,6 +482,10 @@ char *Log_ExpandTemplateString(logger_t *logger, mvd_info_t *mvd, const char *te
}

input = var_end;

if (!input[0]) {
break;
}
}
}

Expand Down Expand Up @@ -548,8 +560,8 @@ void Log_Event(logger_t *logger, mvd_info_t *mvd, log_eventlogger_type_t type, i
int p;
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;
Expand Down Expand Up @@ -582,7 +594,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.
Expand All @@ -597,7 +612,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);
Expand All @@ -609,11 +624,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);
}

Expand Down Expand Up @@ -644,17 +671,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)
Expand Down Expand Up @@ -684,6 +712,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;
Expand Down Expand Up @@ -1161,6 +1199,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;
}
Expand Down Expand Up @@ -1254,6 +1298,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),
Expand Down Expand Up @@ -1335,7 +1380,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))
Expand Down Expand Up @@ -1380,7 +1427,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);

Expand All @@ -1407,7 +1587,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)
Expand Down
Loading