cleaned up demo filename nonsense

If a filename does not contain at least mode, map and timestamp (due to
messed up format strings), the default format is used to ensure unique
filenames.

server side: added server parameters

  demo_max_number
    number of demo files to hold in RAM

  demo_save
    enable/disable writing of demos to file

  demo_path
    demo file path and filename prefix

  demo_filenameformat
    format string to assemble demo information to a filename
    %g : gamemode (int)
    %G : gamemode (chr)
    %F : gamemode (full)
    %m : minutes remaining
    %M : minutes played
    %s : seconds remaining
    %S : seconds played
    %h : IP of server
    %H : hostname of server (client only)
    %n : mapName
    %w : timestamp (formatted by demo_timestampformat)

  demo_timestampformat
    timestamp format string (see strftime() for format options)
    if the string starts with 'U', UTC is used - otherwise local time

client side:

changed demonameformat and demotimeformat to SVARs

  demonameformat
    like demo_filenameformat

  demotimeformat
    like demo_timestampformat

removed demotimelocal getdemonameformat getdemotimeformat getdemotimelocal

DOCREF demonameformat demotimeformat
DOCREF demotimelocal getdemonameformat getdemotimeformat getdemotimelocal
This commit is contained in:
ac-stef
2017-06-27 15:15:24 +02:00
parent 2b10bf1e68
commit 7d1edd0fa1
10 changed files with 123 additions and 180 deletions
+64 -1
View File
@@ -2,6 +2,8 @@
#include "cube.h"
extern bool isdedicated;
#ifdef NO_POSIX_R
char *strtok_r(char *s, const char *delim, char **b)
{
@@ -516,6 +518,61 @@ const char *iprtoa(const struct iprange &ipr, char *b)
return b;
}
char *formatdemofilename(const char *demoformat, const char *timestampformat, const char *map, int mode, int srvclock, int secondsplayed, int secondsremaining, enet_uint32 ip, char *buf)
{
vector<char> d;
// we use the following internal mapping of formatchars:
// %g : gamemode (int) %G : gamemode (chr) %F : gamemode (full)
// %m : minutes remaining %M : minutes played
// %s : seconds remaining %S : seconds played
// %h : IP of server %H : hostname of server (client only)
// %n : mapName
// %w : timestamp "when"
bool did_map = false, did_mode = false, did_ts = false;
for(const char *s = demoformat; *s; s++)
{
if(*s == '%')
{
switch(*++s)
{
case 'F': cvecconcat(d, fullmodestr(mode)); did_mode = true; break;
case 'g': cvecprintf(d, "%d", mode); did_mode = true; break;
case 'G': cvecconcat(d, acronymmodestr(mode)); did_mode = true; break;
case 'H':
if(!isdedicated)
{
#ifndef STANDALONE
ENetAddress a = { htonl(ip), 0 };
cvecconcat(d, !enet_address_get_host(&a, buf, MAXSTRLEN) ? buf : "unknown");
break;
#endif
} // fallthrough to "IP" on dedicated servers
case 'h': cvecconcat(d, ip ? iptoa(ip, buf) : "local"); break;
case 'm': cvecprintf(d, "%d", secondsremaining / 60); break;
case 'M': cvecprintf(d, "%d", secondsplayed / 60); break;
case 'n': cvecconcat(d, map); did_map = true; break;
case 's': cvecprintf(d, "%d", secondsremaining); break;
case 'S': cvecprintf(d, "%d", secondsplayed); break;
case 'w':
{
time_t t = ((time_t) srvclock) * 60;
bool utc = *timestampformat == 'U';
cvecconcat(d, timestring(t, !utc, timestampformat + int(utc), buf));
did_ts = true;
break;
}
default:
if(*s) d.add(*s);
break;
}
}
else d.add(*s);
}
d.add('\0');
filtertext(buf, d.getbuf(), FTXT__DEMONAME);
return did_map && did_mode && did_ts ? buf : formatdemofilename("%w_%h_%n_%G", "%Y%m%d_%H%M", map, mode, srvclock, secondsplayed, secondsremaining, ip, buf);
}
int cmpiprange(const struct iprange *a, const struct iprange *b)
{
if(a->lr < b->lr) return -1;
@@ -542,6 +599,13 @@ int cvecprintf(vector<char> &v, const char *s, ...)
return len;
}
int cvecconcat(vector<char> &v, const char *s)
{
int len = strlen(s);
if(len) v.put(s, len);
return len;
}
const char *hiddenpwd(const char *pwd, int showchars)
{
static int sc = 3;
@@ -563,7 +627,6 @@ int getlistindex(const char *key, const char *list[], bool acceptnumeric, int de
}
#if !defined(STANDALONE) && defined(_DEBUG)
char *opts = conc(list, -1, true);
extern bool isdedicated;
if(!isdedicated && *key) clientlogf("warning: unknown token \"%s\" (not in list [%s])", key, opts);
delstring(opts);
#endif