diff --git a/changelog.txt b/changelog.txt index 58a9b0dc..1e0915c7 100644 --- a/changelog.txt +++ b/changelog.txt @@ -83,6 +83,7 @@ Demos / Spectating [*] Fix broken demo-viewer not able to change to SPECTATOR. [*] Servers now choose a unique file name for the temporary demo file ("demorecord__") [*] Hitsound while spectating +[*] Experimental compatibility mode for 1.1.0.4 demos Sounds / Audio --------------------- diff --git a/source/src/client.cpp b/source/src/client.cpp index bfbc0dbd..2f950487 100644 --- a/source/src/client.cpp +++ b/source/src/client.cpp @@ -8,7 +8,6 @@ VAR(connected, 1, 0, 0); ENetHost *clienthost = NULL; ENetPeer *curpeer = NULL, *connpeer = NULL; int connmillis = 0, connattempts = 0, discmillis = 0; -bool watchingdemo = false; SVAR(curdemofile, "n/a"); extern bool clfail, cllock; extern int searchlan; @@ -66,7 +65,6 @@ void connectserv_(const char *servername, const char *serverport = NULL, const c { const char *defaultport = "28763"; if (!serverport) serverport = defaultport; - extern void enddemoplayback(); if(watchingdemo) enddemoplayback(); if(!clfail && cllock && searchlan<2) return; diff --git a/source/src/clientgame.cpp b/source/src/clientgame.cpp index a020a570..a84a3286 100644 --- a/source/src/clientgame.cpp +++ b/source/src/clientgame.cpp @@ -275,6 +275,13 @@ ICOMMANDF(curplayers, ARG_IVAL, (void) { return players.length() + 1; }); VARP(showscoresondeath, 0, 1, 1); VARP(autoscreenshot, 0, 0, 1); +void stopdemo() +{ + if(watchingdemo) enddemoplayback(); + else conoutf(_("not playing a demo")); +} +COMMAND(stopdemo, ARG_NONE); + // macros for playerinfo() & teaminfo(). Use this to replace pstats_xxx ? #define ATTR_INT(name, attribute) if(!strcmp(attr, #name)) { intret(attribute); return; } #define ATTR_FLOAT(name, attribute) if(!strcmp(attr, #name)) { floatret(attribute); return; } diff --git a/source/src/clients2c.cpp b/source/src/clients2c.cpp index 8fed1e0a..65fbb4c9 100644 --- a/source/src/clients2c.cpp +++ b/source/src/clients2c.cpp @@ -382,7 +382,7 @@ void onChangeVote(int mod, int id) VARP(voicecomsounds, 0, 1, 2); bool medals_arrived=0; medalsst a_medals[END_MDS]; -void parsemessages(int cn, playerent *d, ucharbuf &p) +void parsemessages(int cn, playerent *d, ucharbuf &p, bool demo = false) { static char text[MAXTRANS]; int type, joining = 0; @@ -392,6 +392,17 @@ void parsemessages(int cn, playerent *d, ucharbuf &p) { type = getint(p); + if(demo && watchingdemo && demoprotocol == 1132) + { + if(type >= SV_TEXTPRIVATE) ++type; // SV_TEXTPRIVATE added + if(type == SV_SWITCHNAME) // SV_SPECTCN removed + { + getint(p); + continue; + } + else if(type > SV_SWITCHNAME) --type; + } + #ifdef _DEBUG if(type!=SV_POS && type!=SV_CLIENTPING && type!=SV_PING && type!=SV_PONG && type!=SV_CLIENT) { @@ -405,7 +416,7 @@ void parsemessages(int cn, playerent *d, ucharbuf &p) switch(type) { - case SV_SERVINFO: // welcome messsage from the server + case SV_SERVINFO: // welcome message from the server { int mycn = getint(p), prot = getint(p); if(prot!=CUR_PROTOCOL_VERSION && !(watchingdemo && prot == -PROTOCOL_VERSION)) @@ -433,7 +444,7 @@ void parsemessages(int cn, playerent *d, ucharbuf &p) { int cn = getint(p), len = getuint(p); ucharbuf q = p.subbuf(len); - parsemessages(cn, getclient(cn), q); + parsemessages(cn, getclient(cn), q, demo); break; } @@ -853,7 +864,9 @@ void parsemessages(int cn, playerent *d, ucharbuf &p) { int cn = getint(p); if(p.overread() || cn<0) break; - int state = getint(p), lifesequence = getint(p), primary = getint(p), gunselect = getint(p), flagscore = getint(p), frags = getint(p), deaths = getint(p), health = getint(p), armour = getint(p), points = getint(p), teamkills = getint(p); + int state = getint(p), lifesequence = getint(p), primary = getint(p), gunselect = getint(p), flagscore = getint(p), frags = getint(p), deaths = getint(p), health = getint(p), armour = getint(p), points = getint(p); + int teamkills = 0; + if(!demo || !watchingdemo || demoprotocol != 1132) teamkills = getint(p); int ammo[NUMGUNS], mag[NUMGUNS]; loopi(NUMGUNS) ammo[i] = getint(p); loopi(NUMGUNS) mag[i] = getint(p); @@ -1219,6 +1232,8 @@ void parsemessages(int cn, playerent *d, ucharbuf &p) break; case SA_STOPDEMO: + // compatibility + break; case SA_REMBANS: case SA_SHUFFLETEAMS: v = newvotedisplayinfo(d, type, NULL, NULL); @@ -1299,8 +1314,16 @@ void parsemessages(int cn, playerent *d, ucharbuf &p) { string demofile; extern char *curdemofile; - getstring(demofile, p, MAXSTRLEN); - watchingdemo = demoplayback = demofile[0] != '\0'; + if(demo && watchingdemo && demoprotocol == 1132) + { + watchingdemo = demoplayback = getint(p)!=0; + copystring(demofile, "n/a"); + } + else + { + getstring(demofile, p, MAXSTRLEN); + watchingdemo = demoplayback = demofile[0] != '\0'; + } DELETEA(curdemofile); if(demoplayback) { @@ -1467,19 +1490,19 @@ void receivefile(uchar *data, int len) } } -void servertoclient(int chan, uchar *buf, int len) // processes any updates from the server +void servertoclient(int chan, uchar *buf, int len, bool demo) // processes any updates from the server { ucharbuf p(buf, len); switch(chan) { case 0: parsepositions(p); break; - case 1: parsemessages(-1, NULL, p); break; + case 1: parsemessages(-1, NULL, p, demo); break; case 2: receivefile(p.buf, p.maxlen); break; } } -void localservertoclient(int chan, uchar *buf, int len) // processes any updates from the server +void localservertoclient(int chan, uchar *buf, int len, bool demo) // processes any updates from the server { // pktlogger.queue(enet_packet_create (buf, len, 0)); // log local & demo packets - servertoclient(chan, buf, len); + servertoclient(chan, buf, len, demo); } diff --git a/source/src/command.cpp b/source/src/command.cpp index 0106bed7..047e023e 100644 --- a/source/src/command.cpp +++ b/source/src/command.cpp @@ -1495,7 +1495,6 @@ COMMAND(sealcontexts, ARG_NONE); #ifndef STANDALONE void _watchingdemo() { - extern bool watchingdemo; intret(watchingdemo); } COMMANDN(watchingdemo, _watchingdemo, ARG_NONE); diff --git a/source/src/protos.h b/source/src/protos.h index 2717bc7b..829b92bc 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -376,7 +376,6 @@ extern int sessionid; extern int gametimecurrent; extern int gametimemaximum; extern int lastgametimeupdate; -extern bool watchingdemo; struct serverstate { int autoteam; int mastermode; int matchteamsize; void reset() { autoteam = mastermode = matchteamsize = 0; }}; extern struct serverstate servstate; extern void updateworld(int curtime, int lastmillis); @@ -790,8 +789,8 @@ extern int screenshottype; // server extern int modeacronyms; -extern void servertoclient(int chan, uchar *buf, int len); -extern void localservertoclient(int chan, uchar *buf, int len); +extern void servertoclient(int chan, uchar *buf, int len, bool demo = false); +extern void localservertoclient(int chan, uchar *buf, int len, bool demo = false); extern const char *modestr(int n, bool acronyms = false); extern const char *voteerrorstr(int n); extern const char *mmfullname(int n); @@ -854,6 +853,11 @@ struct demoheader }; #define DEFDEMOFILEFMT "%w_%h_%n_%Mmin_%G" #define DEFDEMOTIMEFMT "%Y%m%d_%H%M" + +extern bool watchingdemo; +extern int demoprotocol; +extern void enddemoplayback(); + // logging enum { ACLOG_DEBUG = 0, ACLOG_VERBOSE, ACLOG_INFO, ACLOG_WARNING, ACLOG_ERROR, ACLOG_NUM }; diff --git a/source/src/server.cpp b/source/src/server.cpp index c7825704..97983407 100644 --- a/source/src/server.cpp +++ b/source/src/server.cpp @@ -85,7 +85,7 @@ void cleanworldstate(ENetPacket *packet) } } -void sendpacket(int n, int chan, ENetPacket *packet, int exclude) +void sendpacket(int n, int chan, ENetPacket *packet, int exclude, bool demopacket) { if(n<0) { @@ -102,7 +102,7 @@ void sendpacket(int n, int chan, ENetPacket *packet, int exclude) } case ST_LOCAL: - localservertoclient(chan, packet->data, (int)packet->dataLength); + localservertoclient(chan, packet->data, (int)packet->dataLength, demopacket); break; } } @@ -396,9 +396,9 @@ void sendextras() sendpacket(-1, 1, p.finalize()); } -void sendservmsg(const char *msg, int client=-1) +void sendservmsg(const char *msg, int cn = -1) { - sendf(client, 1, "ris", SV_SERVMSG, msg); + sendf(cn, 1, "ris", SV_SERVMSG, msg); } void sendspawn(client *c) @@ -720,11 +720,15 @@ void senddemo(int cn, int num) sendpacket(cn, 2, p.finalize()); } +int demoprotocol; +bool watchingdemo = false; + void enddemoplayback() { if(!demoplayback) return; delete demoplayback; demoplayback = NULL; + watchingdemo = false; loopv(clients) sendf(i, 1, "risi", SV_DEMOPLAYBACK, "", i); @@ -749,7 +753,9 @@ void setupdemoplayback() lilswap(&hdr.version, 1); lilswap(&hdr.protocol, 1); if(hdr.version!=DEMO_VERSION) formatstring(msg)("demo \"%s\" requires an %s version of AssaultCube", file, hdr.versionread(&nextplayback, sizeof(nextplayback))!=sizeof(nextplayback)) { @@ -791,7 +798,7 @@ void readdemo() enddemoplayback(); return; } - sendpacket(-1, chan, packet); + sendpacket(-1, chan, packet, -1, true); if(!packet->referenceCount) enet_packet_destroy(packet); if(demoplayback->read(&nextplayback, sizeof(nextplayback))!=sizeof(nextplayback)) { @@ -3433,7 +3440,7 @@ void process(ENetPacket *packet, int sender, int chan) vi->action = new recorddemoaction((vi->num = getint(p))!=0); break; case SA_STOPDEMO: - vi->action = new stopdemoaction(); + // compatibility break; case SA_CLEARDEMOS: vi->action = new cleardemosaction(vi->num = getint(p)); @@ -4178,7 +4185,7 @@ void initserver(bool dedicated, int argc, char **argv) #ifdef STANDALONE -void localservertoclient(int chan, uchar *buf, int len) {} +void localservertoclient(int chan, uchar *buf, int len, bool demo) {} void fatal(const char *s, ...) { defvformatstring(msg,s,s); diff --git a/source/src/server.h b/source/src/server.h index 0546fdf6..f6263770 100644 --- a/source/src/server.h +++ b/source/src/server.h @@ -401,7 +401,7 @@ void senddisconnectedscores(int cn); void process(ENetPacket *packet, int sender, int chan); void welcomepacket(packetbuf &p, int n); void sendwelcome(client *cl, int chan = 1); -void sendpacket(int n, int chan, ENetPacket *packet, int exclude = -1); +void sendpacket(int n, int chan, ENetPacket *packet, int exclude = -1, bool demopacket = false); int numclients(); bool updateclientteam(int cln, int newteam, int ftr); void forcedeath(client *cl);