| 528 | } |
| 529 | |
| 530 | char *formatdemofilename(const char *demoformat, const char *timestampformat, const char *map, int mode, int srvclock, int secondsplayed, int secondsremaining, enet_uint32 ip, char *buf) |
| 531 | { |
| 532 | vector<char> d; |
| 533 | // we use the following internal mapping of formatchars: |
| 534 | // %g : gamemode (int) %G : gamemode (chr) %F : gamemode (full) |
| 535 | // %m : minutes remaining %M : minutes played |
| 536 | // %s : seconds remaining %S : seconds played |
| 537 | // %h : IP of server %H : hostname of server (client only) |
| 538 | // %n : mapName |
| 539 | // %w : timestamp "when" |
| 540 | bool did_map = false, did_mode = false, did_ts = false; |
| 541 | for(const char *s = demoformat; *s; s++) |
| 542 | { |
| 543 | if(*s == '%') |
| 544 | { |
| 545 | switch(*++s) |
| 546 | { |
| 547 | case 'F': cvecconcat(d, fullmodestr(mode)); did_mode = true; break; |
| 548 | case 'g': cvecprintf(d, "%d", mode); did_mode = true; break; |
| 549 | case 'G': cvecconcat(d, acronymmodestr(mode)); did_mode = true; break; |
| 550 | case 'H': |
| 551 | if(!isdedicated) |
| 552 | { |
| 553 | #ifndef STANDALONE |
| 554 | ENetAddress a = { htonl(ip), 0 }; |
| 555 | cvecconcat(d, !enet_address_get_host(&a, buf, MAXSTRLEN) ? buf : "unknown"); |
| 556 | break; |
| 557 | #endif |
| 558 | } // fallthrough to "IP" on dedicated servers |
| 559 | case 'h': cvecconcat(d, ip ? iptoa(ip, buf) : "local"); break; |
| 560 | case 'm': cvecprintf(d, "%d", secondsremaining / 60); break; |
| 561 | case 'M': cvecprintf(d, "%d", secondsplayed / 60); break; |
| 562 | case 'n': cvecconcat(d, map); did_map = true; break; |
| 563 | case 's': cvecprintf(d, "%d", secondsremaining); break; |
| 564 | case 'S': cvecprintf(d, "%d", secondsplayed); break; |
| 565 | case 'w': |
| 566 | { |
| 567 | time_t t = ((time_t) srvclock) * 60; |
| 568 | bool utc = *timestampformat == 'U'; |
| 569 | cvecconcat(d, timestring(t, !utc, timestampformat + int(utc), buf)); |
| 570 | did_ts = true; |
| 571 | break; |
| 572 | } |
| 573 | default: |
| 574 | if(*s) d.add(*s); |
| 575 | break; |
| 576 | } |
| 577 | } |
| 578 | else d.add(*s); |
| 579 | } |
| 580 | d.add('\0'); |
| 581 | filtertext(buf, d.getbuf(), FTXT__DEMONAME); |
| 582 | 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); |
| 583 | } |
| 584 | |
| 585 | int cmpiprange(const struct iprange *a, const struct iprange *b) |
| 586 | { |
no test coverage detected