X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=protocol.c;h=71cfa159190fb5aaccae78facd2e2b79df351137;hb=be511c50c3e4e5fa25e56fb957690072d51314c5;hp=848ad7c7f2357bdab1682b6e501e413c6fdef396;hpb=9e883a148a3370e139b78a19d2ee645fba8db8d1;p=xonotic%2Fdarkplaces.git diff --git a/protocol.c b/protocol.c index 848ad7c7..71cfa159 100644 --- a/protocol.c +++ b/protocol.c @@ -9,11 +9,17 @@ entity_state_t defaultstate = {0,0,0},//float netcenter[3]; // ! for network prioritization, this is the center of the bounding box (which may differ from the origin) {0,0,0},//float origin[3]; {0,0,0},//float angles[3]; - 0,//int number; // entity number this state is for 0,//int effects; + 0,//unsigned int customizeentityforclient; // ! + 0,//unsigned short number; // entity number this state is for 0,//unsigned short modelindex; 0,//unsigned short frame; 0,//unsigned short tagentity; + 0,//unsigned short specialvisibilityradius; // ! larger if it has effects/light + 0,//unsigned short viewmodelforclient; // ! + 0,//unsigned short exteriormodelforclient; // ! not shown if first person viewing from this entity, shown in all other cases + 0,//unsigned short nodrawtoclient; // ! + 0,//unsigned short drawonlytoclient; // ! {0,0,0,0},//unsigned short light[4]; // color*256 (0.00 to 255.996), and radius*1 0,//unsigned char active; // true if a valid state 0,//unsigned char lightstyle; @@ -29,7 +35,7 @@ entity_state_t defaultstate = 0,//unsigned char tagindex; {32, 32, 32},//unsigned char colormod[3]; // padding to a multiple of 8 bytes (to align the double time) - 0//unsigned char unused; // ! + {0,0,0,0,0}//unsigned char unused[5]; // ! }; // LordHavoc: I own protocol ranges 96, 97, 3500-3599 @@ -52,7 +58,10 @@ protocolversioninfo[] = {15, "QUAKEDP"}, {250, "NEHAHRAMOVIE"}, {15, "QUAKE"}, - {28, "QUAKEWORLD"}, + {28, "QW"}, + {10000, "NEHAHRABJP"}, + {10001, "NEHAHRABJP2"}, + {10002, "NEHAHRABJP3"}, {0, NULL} }; @@ -93,8 +102,8 @@ void Protocol_Names(char *buffer, size_t buffersize) for (i = 1;protocolversioninfo[i].name;i++) { if (i > 1) - strlcat(buffer, " ", sizeof(buffer)); - strlcat(buffer, protocolversioninfo[i].name, sizeof(buffer)); + strlcat(buffer, " ", buffersize); + strlcat(buffer, protocolversioninfo[i].name, buffersize); } } @@ -149,7 +158,13 @@ void EntityFrameQuake_ReadEntity(int bits) s.number = num; s.time = cl.mtime[0]; s.flags = 0; - if (bits & U_MODEL) s.modelindex = (s.modelindex & 0xFF00) | MSG_ReadByte(); + if (bits & U_MODEL) + { + if (cls.protocol == PROTOCOL_NEHAHRABJP || cls.protocol == PROTOCOL_NEHAHRABJP2 || cls.protocol == PROTOCOL_NEHAHRABJP3) + s.modelindex = (unsigned short) MSG_ReadShort(); + else + s.modelindex = (s.modelindex & 0xFF00) | MSG_ReadByte(); + } if (bits & U_FRAME) s.frame = (s.frame & 0xFF00) | MSG_ReadByte(); if (bits & U_COLORMAP) s.colormap = MSG_ReadByte(); if (bits & U_SKIN) s.skin = MSG_ReadByte(); @@ -387,33 +402,62 @@ void Protocol_UpdateClientStats(const int *stats) } } +// only a few stats are within the 32 stat limit of Quake, and most of them +// are sent every frame in svc_clientdata messages, so we only send the +// remaining ones here +static const int sendquakestats[] = +{ +// quake did not send these secrets/monsters stats in this way, but doing so +// allows a mod to increase STAT_TOTALMONSTERS during the game, and ensures +// that STAT_SECRETS and STAT_MONSTERS are always correct (even if a client +// didn't receive an svc_foundsecret or svc_killedmonster), which may be most +// valuable if randomly seeking around in a demo +STAT_TOTALSECRETS, // never changes during game +STAT_TOTALMONSTERS, // changes in some mods +STAT_SECRETS, // this makes svc_foundsecret unnecessary +STAT_MONSTERS, // this makes svc_killedmonster unnecessary +STAT_VIEWHEIGHT, // sent just for FTEQW clients +STAT_VIEWZOOM, // this rarely changes +-1, +}; + void Protocol_WriteStatsReliable(void) { - int i; + int i, j; if (!host_client->netconnection) return; // detect changes in stats and write reliable messages - for (i = 0;i < MAX_CL_STATS;i++) + // this only deals with 32 stats because the older protocols which use + // this function can only cope with 32 stats, + // they also do not support svc_updatestatubyte which was introduced in + // DP6 protocol (except for QW) + for (j = 0;sendquakestats[j] >= 0;j++) { - // quickly skip zero bytes - if (!host_client->statsdeltabits[i >> 3]) - { - i |= 7; - continue; - } + i = sendquakestats[j]; // check if this bit is set if (host_client->statsdeltabits[i >> 3] & (1 << (i & 7))) { host_client->statsdeltabits[i >> 3] -= (1 << (i & 7)); // send the stat as a byte if possible - if (host_client->stats[i] >= 0 && host_client->stats[i] < 256) + if (sv.protocol == PROTOCOL_QUAKEWORLD) { - MSG_WriteByte(&host_client->netconnection->message, svc_updatestatubyte); - MSG_WriteByte(&host_client->netconnection->message, i); - MSG_WriteByte(&host_client->netconnection->message, host_client->stats[i]); + if (host_client->stats[i] >= 0 && host_client->stats[i] < 256) + { + MSG_WriteByte(&host_client->netconnection->message, qw_svc_updatestat); + MSG_WriteByte(&host_client->netconnection->message, i); + MSG_WriteByte(&host_client->netconnection->message, host_client->stats[i]); + } + else + { + MSG_WriteByte(&host_client->netconnection->message, qw_svc_updatestatlong); + MSG_WriteByte(&host_client->netconnection->message, i); + MSG_WriteLong(&host_client->netconnection->message, host_client->stats[i]); + } } else { + // this could make use of svc_updatestatubyte in DP6 and later + // protocols but those protocols do not use this function MSG_WriteByte(&host_client->netconnection->message, svc_updatestat); MSG_WriteByte(&host_client->netconnection->message, i); MSG_WriteLong(&host_client->netconnection->message, host_client->stats[i]); @@ -492,7 +536,7 @@ void EntityFrameQuake_WriteFrame(sizebuf_t *msg, int numstates, const entity_sta if (baseline.modelindex != s->modelindex) { bits |= U_MODEL; - if (s->modelindex & 0xFF00) + if ((s->modelindex & 0xFF00) && sv.protocol != PROTOCOL_NEHAHRABJP && sv.protocol != PROTOCOL_NEHAHRABJP2 && sv.protocol != PROTOCOL_NEHAHRABJP3) bits |= U_MODEL2; } if (baseline.alpha != s->alpha) @@ -503,6 +547,8 @@ void EntityFrameQuake_WriteFrame(sizebuf_t *msg, int numstates, const entity_sta bits |= U_GLOWSIZE; if (baseline.glowcolor != s->glowcolor) bits |= U_GLOWCOLOR; + if (!VectorCompare(baseline.colormod, s->colormod)) + bits |= U_COLORMOD; // if extensions are disabled, clear the relevant update flags if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_NEHAHRAMOVIE) @@ -522,12 +568,21 @@ void EntityFrameQuake_WriteFrame(sizebuf_t *msg, int numstates, const entity_sta MSG_WriteByte (&buf, bits); if (bits & U_MOREBITS) MSG_WriteByte(&buf, bits>>8); - if (bits & U_EXTEND1) MSG_WriteByte(&buf, bits>>16); - if (bits & U_EXTEND2) MSG_WriteByte(&buf, bits>>24); + if (sv.protocol != PROTOCOL_NEHAHRAMOVIE) + { + if (bits & U_EXTEND1) MSG_WriteByte(&buf, bits>>16); + if (bits & U_EXTEND2) MSG_WriteByte(&buf, bits>>24); + } if (bits & U_LONGENTITY) MSG_WriteShort(&buf, s->number); else MSG_WriteByte(&buf, s->number); - if (bits & U_MODEL) MSG_WriteByte(&buf, s->modelindex); + if (bits & U_MODEL) + { + if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) + MSG_WriteShort(&buf, s->modelindex); + else + MSG_WriteByte(&buf, s->modelindex); + } if (bits & U_FRAME) MSG_WriteByte(&buf, s->frame); if (bits & U_COLORMAP) MSG_WriteByte(&buf, s->colormap); if (bits & U_SKIN) MSG_WriteByte(&buf, s->skin); @@ -2180,7 +2235,7 @@ void EntityFrame5_LostFrame(entityframe5_database_t *d, int framenum) { d->deltabits[s->number] |= bits; // if it was a very important update, set priority higher - if (bits & (E5_FULLUPDATE | E5_ATTACHMENT | E5_MODEL || E5_COLORMAP)) + if (bits & (E5_FULLUPDATE | E5_ATTACHMENT | E5_MODEL | E5_COLORMAP)) d->priorities[s->number] = max(d->priorities[s->number], 4); else d->priorities[s->number] = max(d->priorities[s->number], 1); @@ -2323,7 +2378,7 @@ void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int num packetlog->packetnumber = framenum; packetlog->numstates = 0; // write stat updates - if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5) + if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_NEHAHRABJP && sv.protocol != PROTOCOL_NEHAHRABJP2 && sv.protocol != PROTOCOL_NEHAHRABJP3 && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5) { for (i = 0;i < MAX_CL_STATS && msg->cursize + 6 + 11 <= msg->maxsize;i++) {