From aae52e1ca3b4e490fa7f118ea37024131cc765e8 Mon Sep 17 00:00:00 2001 From: g-cont Date: Wed, 8 Feb 2017 00:00:00 +0300 Subject: [PATCH] 08 Feb 2017 --- engine/client/cl_game.c | 2 +- engine/client/cl_parse.c | 96 +++++++++++++++--------------- engine/common/common.h | 5 -- engine/common/net_buffer.c | 23 ++++---- engine/common/net_buffer.h | 2 - engine/common/net_chan.c | 29 ++++++---- engine/common/net_encode.c | 18 +++++- engine/common/protocol.h | 41 ++++++++----- engine/server/server.h | 6 +- engine/server/sv_client.c | 21 ++++--- engine/server/sv_custom.c | 8 +-- engine/server/sv_frame.c | 4 +- engine/server/sv_game.c | 116 ++++++++++++++++--------------------- engine/server/sv_main.c | 15 ++++- engine/server/sv_save.c | 18 +++--- 15 files changed, 215 insertions(+), 189 deletions(-) diff --git a/engine/client/cl_game.c b/engine/client/cl_game.c index 10e432c7..d7addec3 100644 --- a/engine/client/cl_game.c +++ b/engine/client/cl_game.c @@ -1003,7 +1003,7 @@ void CL_LinkUserMessage( char *pszName, const int svc_num, int iSize ) if( !pszName || !*pszName ) Host_Error( "CL_LinkUserMessage: bad message name\n" ); - if( svc_num < svc_lastmsg ) + if( svc_num <= svc_lastmsg ) Host_Error( "CL_LinkUserMessage: tried to hook a system message \"%s\"\n", svc_strings[svc_num] ); // see if already hooked diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 27640bfc..ff98b0fa 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -31,8 +31,8 @@ const char *svc_strings[256] = "svc_bad", "svc_nop", "svc_disconnect", + "svc_event", "svc_changing", - "svc_version", "svc_setview", "svc_sound", "svc_time", @@ -45,7 +45,7 @@ const char *svc_strings[256] = "svc_deltatable", "svc_clientdata", "svc_stopsound", - "svc_updatepings", + "svc_pings", "svc_particle", "svc_restoresound", "svc_spawnstatic", @@ -55,14 +55,14 @@ const char *svc_strings[256] = "svc_setpause", "svc_signonnum", "svc_centerprint", - "svc_event", + "svc_modelindex", "svc_soundindex", "svc_ambientsound", "svc_intermission", - "svc_modelindex", - "svc_cdtrack", - "svc_serverinfo", "svc_eventindex", + "svc_cdtrack", + "svc_restore", + "svc_serverinfo", "svc_weaponanim", "svc_bspdecal", "svc_roomtype", @@ -73,25 +73,20 @@ const char *svc_strings[256] = "svc_chokecount", "svc_resourcelist", "svc_deltamovevars", + "svc_resourcerequest", "svc_customization", - "svc_unused46", "svc_crosshairangle", "svc_soundfade", - "svc_unused49", - "svc_unused50", + "svc_filetxferfailed", + "svc_hltv", "svc_director", "svc_studiodecal", - "svc_unused53", + "svc_voicedata", "svc_unused54", "svc_unused55", - "svc_unused56", + "svc_resourcelocation", "svc_querycvarvalue", "svc_querycvarvalue2", - "svc_unused59", - "svc_unused60", - "svc_unused61", - "svc_unused62", - "svc_unused63", }; typedef struct @@ -118,12 +113,12 @@ const char *CL_MsgInfo( int cmd ) Q_strcpy( sz, "???" ); - if( cmd >= 0 && cmd < svc_lastmsg ) + if( cmd >= 0 && cmd <= svc_lastmsg ) { // get engine message name Q_strncpy( sz, svc_strings[cmd], sizeof( sz )); } - else if( cmd >= svc_lastmsg && cmd < ( svc_lastmsg + MAX_USER_MESSAGES )) + else if( cmd > svc_lastmsg && cmd <= ( svc_lastmsg + MAX_USER_MESSAGES )) { int i; @@ -244,7 +239,7 @@ CL_ParseSoundPacket ================== */ -void CL_ParseSoundPacket( sizebuf_t *msg, qboolean is_ambient ) +void CL_ParseSoundPacket( sizebuf_t *msg ) { vec3_t pos; int chan, sound; @@ -252,11 +247,9 @@ void CL_ParseSoundPacket( sizebuf_t *msg, qboolean is_ambient ) int flags, pitch, entnum; sound_t handle = 0; - flags = MSG_ReadWord( msg ); - if( flags & SND_LARGE_INDEX ) - sound = MSG_ReadWord( msg ); - else sound = MSG_ReadByte( msg ); - chan = MSG_ReadByte( msg ); + flags = MSG_ReadUBitLong( msg, MAX_SND_FLAGS_BITS ); + sound = MSG_ReadUBitLong( msg, MAX_SOUND_BITS ); + chan = MSG_ReadUBitLong( msg, MAX_SND_CHAN_BITS ); if( flags & SND_VOLUME ) volume = (float)MSG_ReadByte( msg ) / 255.0f; @@ -271,7 +264,7 @@ void CL_ParseSoundPacket( sizebuf_t *msg, qboolean is_ambient ) else pitch = PITCH_NORM; // entity reletive - entnum = MSG_ReadWord( msg ); + entnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS ); // positioned in space MSG_ReadVec3Coord( msg, pos ); @@ -280,15 +273,21 @@ void CL_ParseSoundPacket( sizebuf_t *msg, qboolean is_ambient ) { char sentenceName[32]; - Q_snprintf( sentenceName, sizeof( sentenceName ), "!%i", sound ); + if( flags & SND_SEQUENCE ) + Q_snprintf( sentenceName, sizeof( sentenceName ), "!#%i", sound ); + else Q_snprintf( sentenceName, sizeof( sentenceName ), "!%i", sound ); + handle = S_RegisterSound( sentenceName ); } else handle = cl.sound_index[sound]; // see precached sound if( !cl.audio_prepped ) + { + MsgDev( D_WARN, "CL_StartSoundPacket: ignore sound message: too early\n" ); return; // too early + } - if( is_ambient ) + if( chan == CHAN_STATIC ) { S_AmbientSound( pos, entnum, handle, volume, attn, pitch, flags ); } @@ -314,11 +313,9 @@ void CL_ParseRestoreSoundPacket( sizebuf_t *msg ) int wordIndex; sound_t handle = 0; - flags = MSG_ReadWord( msg ); - if( flags & SND_LARGE_INDEX ) - sound = MSG_ReadWord( msg ); - else sound = MSG_ReadByte( msg ); - chan = MSG_ReadByte( msg ); + flags = MSG_ReadUBitLong( msg, MAX_SND_FLAGS_BITS ); + sound = MSG_ReadUBitLong( msg, MAX_SOUND_BITS ); + chan = MSG_ReadUBitLong( msg, MAX_SND_CHAN_BITS ); if( flags & SND_VOLUME ) volume = (float)MSG_ReadByte( msg ) / 255.0f; @@ -332,26 +329,36 @@ void CL_ParseRestoreSoundPacket( sizebuf_t *msg ) pitch = MSG_ReadByte( msg ); else pitch = PITCH_NORM; + // entity reletive + entnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS ); + + // positioned in space + MSG_ReadVec3Coord( msg, pos ); + if( flags & SND_SENTENCE ) { char sentenceName[32]; - Q_snprintf( sentenceName, sizeof( sentenceName ), "!%i", sound ); + if( flags & SND_SEQUENCE ) + Q_snprintf( sentenceName, sizeof( sentenceName ), "!#%i", sound ); + else Q_snprintf( sentenceName, sizeof( sentenceName ), "!%i", sound ); + handle = S_RegisterSound( sentenceName ); } else handle = cl.sound_index[sound]; // see precached sound - // entity reletive - entnum = MSG_ReadWord( msg ); - - // positioned in space - MSG_ReadVec3Coord( msg, pos ); wordIndex = MSG_ReadByte( msg ); // 16 bytes here MSG_ReadBytes( msg, &samplePos, sizeof( samplePos )); MSG_ReadBytes( msg, &forcedEnd, sizeof( forcedEnd )); + if( !cl.audio_prepped ) + { + MsgDev( D_WARN, "CL_RestoreSoundPacket: ignore sound message: too early\n" ); + return; // too early + } + S_RestoreSound( pos, entnum, chan, handle, volume, attn, pitch, flags, samplePos, forcedEnd, wordIndex ); } @@ -1081,7 +1088,7 @@ void CL_UpdateUserPings( sizebuf_t *msg ) slot = MSG_ReadUBitLong( msg, MAX_CLIENT_BITS ); if( slot >= MAX_CLIENTS ) - Host_Error( "CL_ParseServerMessage: svc_updatepings > MAX_CLIENTS\n" ); + Host_Error( "CL_ParseServerMessage: svc_pings > MAX_CLIENTS\n" ); player = &cl.players[slot]; player->ping = MSG_ReadUBitLong( msg, 12 ); @@ -1407,7 +1414,7 @@ void CL_ParseUserMessage( sizebuf_t *msg, int svc_num ) byte pbuf[256]; // message can't be larger than 255 bytes // NOTE: any user message is really parse at engine, not in client.dll - if( svc_num < svc_lastmsg || svc_num >= ( MAX_USER_MESSAGES + svc_lastmsg )) + if( svc_num <= svc_lastmsg || svc_num > ( MAX_USER_MESSAGES + svc_lastmsg )) { // out or range Host_Error( "CL_ParseUserMessage: illegible server message %d\n", svc_num ); @@ -1549,7 +1556,8 @@ void CL_ParseServerMessage( sizebuf_t *msg ) cl.refdef.viewentity = MSG_ReadWord( msg ); break; case svc_sound: - CL_ParseSoundPacket( msg, false ); + case svc_ambientsound: + CL_ParseSoundPacket( msg ); cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart; break; case svc_time: @@ -1591,7 +1599,7 @@ void CL_ParseServerMessage( sizebuf_t *msg ) cl.frames[cl.parsecountmod].graphdata.players += playerbytes; cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes; break; - case svc_updatepings: + case svc_pings: CL_UpdateUserPings( msg ); break; case svc_usermessage: @@ -1607,10 +1615,6 @@ void CL_ParseServerMessage( sizebuf_t *msg ) case svc_spawnstatic: CL_ParseStaticEntity( msg ); break; - case svc_ambientsound: - CL_ParseSoundPacket( msg, true ); - cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart; - break; case svc_crosshairangle: CL_ParseCrosshairAngle( msg ); break; diff --git a/engine/common/common.h b/engine/common/common.h index 8b7145d9..be458720 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -275,11 +275,6 @@ typedef struct host_redirect_s void (*flush)( netadr_t adr, rdtype_t target, char *buffer ); } host_redirect_t; -// local flags (never sending acorss the net) -#define SND_LOCALSOUND (1<<9) // not paused, not looped, for internal use -#define SND_STOP_LOOPING (1<<10) // stop all looping sounds on the entity. -#define SND_FILTER_CLIENT (1<<11) // don't send sound from local player if prediction was enabled - typedef struct { char name[64]; diff --git a/engine/common/net_buffer.c b/engine/common/net_buffer.c index 36372e6d..5aeb7557 100644 --- a/engine/common/net_buffer.c +++ b/engine/common/net_buffer.c @@ -18,6 +18,9 @@ GNU General Public License for more details. #include "net_buffer.h" #include "mathlib.h" +//#define DEBUG_NET_MESSAGES_SEND +//#define DEBUG_NET_MESSAGES_READ + // precalculated bit masks for WriteUBitLong. // Using these tables instead of doing the calculations // gives a 33% speedup in WriteUBitLong. @@ -284,25 +287,25 @@ void MSG_WriteBitFloat( sizebuf_t *sb, float val ) void MSG_WriteCmdExt( sizebuf_t *sb, int cmd, netsrc_t type, const char *name ) { -#ifdef DEBUG_NET_MESSAGES +#ifdef DEBUG_NET_MESSAGES_SEND if( name != NULL ) { // get custom name - Msg( "^1sv^7: %s\n", name ); + Msg( "^1sv^7 write: %s\n", name ); } else if( type == NS_SERVER ) { - if( cmd >= 0 && cmd < svc_lastmsg ) + if( cmd >= 0 && cmd <= svc_lastmsg ) { // get engine message name - Msg( "^1sv^7: %s\n", svc_strings[cmd] ); + Msg( "^1sv^7 write: %s\n", svc_strings[cmd] ); } } else if( type == NS_CLIENT ) { - if( cmd >= 0 && cmd < clc_lastmsg ) + if( cmd >= 0 && cmd <= clc_lastmsg ) { - Msg( "^1cl^7: %s\n", clc_strings[cmd] ); + Msg( "^1cl^7 write: %s\n", clc_strings[cmd] ); } } #endif @@ -530,14 +533,14 @@ int MSG_ReadCmd( sizebuf_t *sb, netsrc_t type ) { int cmd = MSG_ReadUBitLong( sb, sizeof( byte ) << 3 ); -#ifdef DEBUG_NET_MESSAGES +#ifdef DEBUG_NET_MESSAGES_READ if( type == NS_SERVER ) { - Msg( "^1cl^7: %s\n", CL_MsgInfo( cmd )); + Msg( "^1cl^7 read: %s\n", CL_MsgInfo( cmd )); } - else if( cmd >= 0 && cmd < clc_lastmsg ) + else if( cmd >= 0 && cmd <= clc_lastmsg ) { - Msg( "^1sv^7: %s\n", clc_strings[cmd] ); + Msg( "^1sv^7 read: %s\n", clc_strings[cmd] ); } #endif return cmd; diff --git a/engine/common/net_buffer.h b/engine/common/net_buffer.h index 94dbedcd..2760bd5d 100644 --- a/engine/common/net_buffer.h +++ b/engine/common/net_buffer.h @@ -18,8 +18,6 @@ GNU General Public License for more details. #include "features.h" -// #define DEBUG_NET_MESSAGES - /* ============================================================================== diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index 39a4dc23..8f19e6d2 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -548,8 +548,8 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg ) { fragbuf_t *buf; int chunksize; - int send, pos; int remaining; + int bits, pos; int bufferid = 1; fragbufwaiting_t *wait, *p; @@ -562,23 +562,32 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg ) wait = (fragbufwaiting_t *)Mem_Alloc( net_mempool, sizeof( fragbufwaiting_t )); - remaining = MSG_GetNumBytesWritten( msg ); - pos = 0; + remaining = MSG_GetNumBitsWritten( msg ); + chunksize <<= 3; // convert bytes to bits + pos = 0; // current position in bits while( remaining > 0 ) { - send = Q_min( remaining, chunksize ); - remaining -= send; + byte buffer[MAX_MSGLEN]; + sizebuf_t temp; + + bits = Q_min( remaining, chunksize ); + remaining -= bits; buf = Netchan_AllocFragbuf(); buf->bufferid = bufferid++; // Copy in data MSG_Clear( &buf->frag_message ); - MSG_WriteBits( &buf->frag_message, msg->pData + pos, send << 3 ); - pos += send; + + MSG_StartReading( &temp, MSG_GetData( msg ), MSG_GetMaxBytes( msg ), MSG_GetNumBitsWritten( msg ), -1 ); + MSG_SeekToBit( &temp, pos ); + MSG_ReadBits( &temp, buffer, bits ); + + MSG_WriteBits( &buf->frag_message, buffer, bits ); Netchan_AddFragbufToTail( wait, buf ); + pos += bits; } // now add waiting list item to end of buffer queue @@ -1236,7 +1245,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data ) // if the reliable buffer has gotten too big, queue it at the end of everything and clear out buffer if( MSG_GetNumBytesWritten( &chan->message ) > MAX_RELIABLE_PAYLOAD ) { - Netchan_CreateFragments( chan, &chan->message ); + Netchan_CreateFragments_( chan, &chan->message ); MSG_Clear( &chan->message ); } } @@ -1621,12 +1630,12 @@ qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg ) MSG_Clear( &pbuf->frag_message ); MSG_StartReading( &temp, msg->pData, MSG_GetMaxBytes( msg ), MSG_GetNumBitsRead( msg ) + frag_offset[i], -1 ); - MSG_ReadBits( msg, buffer, bits ); + MSG_ReadBits( &temp, buffer, bits ); MSG_WriteBits( &pbuf->frag_message, buffer, bits ); } else { - MsgDev( D_ERROR, "Netchan_Process: Couldn't allocate or find buffer %i\n", inbufferid ); + MsgDev( D_ERROR, "Netchan_Process: Couldn't find buffer %i\n", inbufferid ); } // count # of incoming bufs we've queued? are we done? diff --git a/engine/common/net_encode.c b/engine/common/net_encode.c index 03fb5787..de757d01 100644 --- a/engine/common/net_encode.c +++ b/engine/common/net_encode.c @@ -1501,7 +1501,8 @@ void MSG_WriteClientData( sizebuf_t *msg, clientdata_t *from, clientdata_t *to, { delta_t *pField; delta_info_t *dt; - int i; + int i, startBit; + int numChanges = 0; dt = Delta_FindStruct( "clientdata_t" ); Assert( dt && dt->bInitialized ); @@ -1509,14 +1510,24 @@ void MSG_WriteClientData( sizebuf_t *msg, clientdata_t *from, clientdata_t *to, pField = dt->pFields; Assert( pField != NULL ); + startBit = msg->iCurBit; + + MSG_WriteOneBit( msg, 1 ); // have clientdata + // activate fields and call custom encode func Delta_CustomEncode( dt, from, to ); // process fields for( i = 0; i < dt->numFields; i++, pField++ ) { - Delta_WriteField( msg, pField, from, to, timebase ); + if( Delta_WriteField( msg, pField, from, to, timebase )) + numChanges++; } + + if( numChanges ) return; // we have updates + + MSG_SeekToBit( msg, startBit ); + MSG_WriteOneBit( msg, 0 ); // no changes } /* @@ -1540,6 +1551,9 @@ void MSG_ReadClientData( sizebuf_t *msg, clientdata_t *from, clientdata_t *to, f *to = *from; + if( !MSG_ReadOneBit( msg )) + return; // we have no changes + // process fields for( i = 0; i < dt->numFields; i++, pField++ ) { diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 2e7103fe..1dd7ad03 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -22,8 +22,8 @@ GNU General Public License for more details. #define svc_bad 0 // immediately crash client when received #define svc_nop 1 // does nothing #define svc_disconnect 2 // kick client from server -#define svc_changing 3 // changelevel by server request -#define svc_version 4 // [long] server version +#define svc_event 3 // playback event queue +#define svc_changing 4 // changelevel by server request #define svc_setview 5 // [short] entity number #define svc_sound 6 // #define svc_time 7 // [float] server time @@ -36,7 +36,7 @@ GNU General Public License for more details. #define svc_deltatable 14 // [table header][...] #define svc_clientdata 15 // [...] #define svc_stopsound 16 // -#define svc_updatepings 17 // [bit][idx][ping][packet_loss] +#define svc_pings 17 // [bit][idx][ping][packet_loss] #define svc_particle 18 // [float*3][char*3][byte][byte] #define svc_restoresound 19 // #define svc_spawnstatic 20 // creates a static client entity @@ -46,14 +46,14 @@ GNU General Public License for more details. #define svc_setpause 24 // [byte] 0 = unpaused, 1 = paused #define svc_signonnum 25 // [byte] used for the signon sequence #define svc_centerprint 26 // [string] to put in center of the screen -#define svc_event 27 // playback event queue +#define svc_modelindex 27 // [index][modelpath] #define svc_soundindex 28 // [index][soundpath] #define svc_ambientsound 29 // #define svc_intermission 30 // empty message (event) -#define svc_modelindex 31 // [index][modelpath] +#define svc_eventindex 31 // [index][eventname] #define svc_cdtrack 32 // [string] trackname -#define svc_serverinfo 33 // [string] key [string] value -#define svc_eventindex 34 // [index][eventname] +#define svc_restore 33 // [string] savename +#define svc_serverinfo 34 // [string] key [string] value #define svc_weaponanim 35 // [byte]iAnim [byte]body #define svc_bspdecal 36 // [float*3][short][short][short] #define svc_roomtype 37 // [short] room type @@ -64,17 +64,21 @@ GNU General Public License for more details. #define svc_chokecount 42 // [byte] #define svc_resourcelist 43 // [short][...] #define svc_deltamovevars 44 // [movevars_t] -#define svc_customization 45 // - +#define svc_resourcerequest 45 // +#define svc_customization 46 #define svc_crosshairangle 47 // [byte][byte] #define svc_soundfade 48 // [float*4] sound fade parms - +#define svc_filetxferfailed 49 // [string] +#define svc_hltv 50 #define svc_director 51 // #define svc_studiodecal 52 // [float*3][float*3][short][short][byte] - +#define svc_voicedata 53 // [byte][short][...] +// reserved +// reserved +#define svc_resourcelocation 56 // [string] #define svc_querycvarvalue 57 // [string] #define svc_querycvarvalue2 58 // [string][long] (context) -#define svc_lastmsg 64 // start user messages at this point +#define svc_lastmsg 58 // start user messages at this point // client to server #define clc_bad 0 // immediately drop client when received @@ -88,7 +92,7 @@ GNU General Public License for more details. #define clc_voicedata 8 #define clc_requestcvarvalue 9 #define clc_requestcvarvalue2 10 -#define clc_lastmsg 11 // end client messages +#define clc_lastmsg 10 // end client messages #define MAX_VISIBLE_PACKET 1024 // 1024 visible entities per frame (hl1 has 256) @@ -112,22 +116,29 @@ GNU General Public License for more details. #define MAX_EDICTS (1< from client (server downloading) + customization_t customdata; // player customization linked list + resource_t resourcesonhand; + resource_t resourcesneeded; // from client (server downloading) usercmd_t lastcmd; // for filling in big drops diff --git a/engine/server/sv_client.c b/engine/server/sv_client.c index aa13eb1f..bf27b3d1 100644 --- a/engine/server/sv_client.c +++ b/engine/server/sv_client.c @@ -1076,6 +1076,7 @@ void SV_PutClientInServer( sv_client_t *cl ) else ent->v.flags = 0; ent->v.netname = MAKE_STRING( cl->name ); + ent->v.colormap = NUM_FOR_EDICT( ent ); // ??? // fisrt entering svgame.globals->time = sv.time; @@ -1135,7 +1136,9 @@ void SV_PutClientInServer( sv_client_t *cl ) sv_client_t *cur; int i, viewEnt; - MSG_WriteBits( &cl->netchan.message, MSG_GetData( &sv.signon ), MSG_GetNumBitsWritten( &sv.signon )); + // time to send signon buffer + Netchan_CreateFragments( &cl->netchan, &sv.signon ); + Netchan_FragSend( &cl->netchan ); if( cl->pViewEntity ) viewEnt = NUM_FOR_EDICT( cl->pViewEntity ); @@ -1379,7 +1382,7 @@ void SV_WriteModels_f( sv_client_t *cl ) start = Q_atoi( Cmd_Argv( 2 )); // write a packet full of data - while( MSG_GetNumBytesWritten( &cl->netchan.message ) < ( NET_MAX_PAYLOAD / 2 ) && start < MAX_MODELS ) + while(( MSG_GetNumBytesLeft( &cl->netchan.message ) > MAX_UDP_PACKET ) && start < MAX_MODELS ) { if( sv.model_precache[start][0] ) { @@ -1425,7 +1428,7 @@ void SV_WriteSounds_f( sv_client_t *cl ) start = Q_atoi( Cmd_Argv( 2 )); // write a packet full of data - while( MSG_GetNumBytesWritten( &cl->netchan.message ) < ( NET_MAX_PAYLOAD / 2 ) && start < MAX_SOUNDS ) + while(( MSG_GetNumBytesLeft( &cl->netchan.message ) > MAX_UDP_PACKET ) && start < MAX_SOUNDS ) { if( sv.sound_precache[start][0] ) { @@ -1471,7 +1474,7 @@ void SV_WriteEvents_f( sv_client_t *cl ) start = Q_atoi( Cmd_Argv( 2 )); // write a packet full of data - while( MSG_GetNumBytesWritten( &cl->netchan.message ) < ( NET_MAX_PAYLOAD / 2 ) && start < MAX_EVENTS ) + while(( MSG_GetNumBytesLeft( &cl->netchan.message ) > MAX_UDP_PACKET ) && start < MAX_EVENTS ) { if( sv.event_precache[start][0] ) { @@ -1517,7 +1520,7 @@ void SV_WriteLightstyles_f( sv_client_t *cl ) start = Q_atoi( Cmd_Argv( 2 )); // write a packet full of data - while( MSG_GetNumBytesWritten( &cl->netchan.message ) < ( NET_MAX_PAYLOAD / 2 ) && start < MAX_LIGHTSTYLES ) + while(( MSG_GetNumBytesLeft( &cl->netchan.message ) > MAX_UDP_PACKET ) && start < MAX_LIGHTSTYLES ) { if( sv.lightstyles[start].pattern[0] ) { @@ -1565,7 +1568,7 @@ void SV_UserMessages_f( sv_client_t *cl ) start = Q_atoi( Cmd_Argv( 2 )); // write a packet full of data - while( MSG_GetNumBytesWritten( &cl->netchan.message ) < ( NET_MAX_PAYLOAD / 2 ) && start < MAX_USER_MESSAGES ) + while(( MSG_GetNumBytesLeft( &cl->netchan.message ) > MAX_UDP_PACKET ) && start < MAX_USER_MESSAGES ) { message = &svgame.msg[start]; if( message->name[0] ) @@ -1616,7 +1619,7 @@ void SV_DeltaInfo_f( sv_client_t *cl ) fieldIndex = Q_atoi( Cmd_Argv( 3 )); // write a packet full of data - while( MSG_GetNumBytesWritten( &cl->netchan.message ) < ( NET_MAX_PAYLOAD / 2 ) && tableIndex < Delta_NumTables( )) + while(( MSG_GetNumBytesLeft( &cl->netchan.message ) > MAX_UDP_PACKET ) && tableIndex < Delta_NumTables( )) { dt = Delta_FindStructByIndex( tableIndex ); @@ -1680,7 +1683,7 @@ void SV_Baselines_f( sv_client_t *cl ) memset( &nullstate, 0, sizeof( nullstate )); // write a packet full of data - while( MSG_GetNumBytesWritten( &cl->netchan.message ) < ( NET_MAX_PAYLOAD / 2 ) && start < svgame.numEntities ) + while(( MSG_GetNumBytesLeft( &cl->netchan.message ) > MAX_UDP_PACKET ) && start < svgame.numEntities ) { base = &svs.baselines[start]; if(( !start || base->number ) && ( base->modelindex || base->effects != EF_NODRAW )) @@ -1722,7 +1725,7 @@ void SV_Begin_f( sv_client_t *cl ) SV_PutClientInServer( cl ); - // if we are paused, tell the client + // if we are paused, tell the clients if( sv.paused ) { MSG_BeginServerCmd( &sv.reliable_datagram, svc_setpause ); diff --git a/engine/server/sv_custom.c b/engine/server/sv_custom.c index a7b8cb77..c6d64091 100644 --- a/engine/server/sv_custom.c +++ b/engine/server/sv_custom.c @@ -150,13 +150,13 @@ void SV_CreateCustomizationList( sv_client_t *cl ) customization_t *pCust, *pNewCust; int duplicated, lump_count; - cl->customization.pNext = NULL; + cl->customdata.pNext = NULL; - for( pRes = cl->resource1.pNext; pRes != &cl->resource1; pRes = pRes->pNext ) + for( pRes = cl->resourcesonhand.pNext; pRes != &cl->resourcesonhand; pRes = pRes->pNext ) { duplicated = false; - for( pCust = cl->customization.pNext; pCust != NULL; pCust = pCust->pNext ) + for( pCust = cl->customdata.pNext; pCust != NULL; pCust = pCust->pNext ) { if( !memcmp( pCust->resource.rgucMD5_hash, pRes->rgucMD5_hash, 16 )) { @@ -174,7 +174,7 @@ void SV_CreateCustomizationList( sv_client_t *cl ) // create it. lump_count = 0; - if( !SV_CreateCustomization( &cl->customization, pRes, -1, 3, &pNewCust, &lump_count )) + if( !SV_CreateCustomization( &cl->customdata, pRes, -1, 3, &pNewCust, &lump_count )) { MsgDev( D_WARN, "CreateCustomizationList: ignoring custom decal.\n" ); continue; diff --git a/engine/server/sv_frame.c b/engine/server/sv_frame.c index 45f2d197..a0dcb3a1 100644 --- a/engine/server/sv_frame.c +++ b/engine/server/sv_frame.c @@ -413,7 +413,7 @@ void SV_EmitPings( sizebuf_t *msg ) int packet_loss; int i, ping; - MSG_BeginServerCmd( msg, svc_updatepings ); + MSG_BeginServerCmd( msg, svc_pings ); for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ ) { @@ -819,7 +819,7 @@ void SV_SendClientMessages( void ) // If we haven't gotten a message in sv_failuretime seconds, then stop sending messages to this client // until we get another packet in from the client. This prevents crash/drop and reconnect where they are // being hosed with "sequenced packet without connection" packets. - if(( host.realtime - cl->netchan.last_received ) > sv_failuretime->value ) + if( sv_failuretime->value < ( host.realtime - cl->netchan.last_received )) ClearBits( cl->flags, FCL_SEND_NET_MESSAGE ); } diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index 3956c442..736b3400 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -403,7 +403,7 @@ void SV_CreateDecal( sizebuf_t *msg, const float *origin, int decalIndex, int en return; // this can happens if serialized map contain 4096 static decals... - if( MSG_GetNumBytesLeft( msg ) >= 20 ) + if( MSG_GetNumBytesLeft( msg ) < 20 ) return; // static decals are posters, it's always reliable @@ -437,7 +437,7 @@ void SV_CreateStudioDecal( sizebuf_t *msg, const float *origin, const float *sta ASSERT( start ); // this can happens if serialized map contain 4096 static decals... - if( MSG_GetNumBytesLeft( msg ) >= 30 ) + if( MSG_GetNumBytesLeft( msg ) < 32 ) return; // static decals are posters, it's always reliable @@ -474,7 +474,7 @@ void SV_CreateStaticEntity( sizebuf_t *msg, sv_static_entity_t *ent ) int index, i; // this can happens if serialized map contain too many static entities... - if( MSG_GetNumBytesLeft( msg ) >= 64 ) + if( MSG_GetNumBytesLeft( msg ) < 64 ) return; index = SV_ModelIndex( ent->model ); @@ -1767,7 +1767,7 @@ SV_BuildSoundMsg ================= */ -int SV_BuildSoundMsg( edict_t *ent, int chan, const char *samp, int vol, float attn, int flags, int pitch, const vec3_t pos ) +int SV_BuildSoundMsg( edict_t *ent, int chan, const char *sample, int vol, float attn, int flags, int pitch, const vec3_t pos ) { int sound_idx; int entityIndex; @@ -1780,13 +1780,13 @@ int SV_BuildSoundMsg( edict_t *ent, int chan, const char *samp, int vol, float a if( attn < 0.0f || attn > 4.0f ) { - MsgDev( D_ERROR, "SV_StartSound: attenuation = %g\n", attn ); + MsgDev( D_ERROR, "SV_StartSound: attenuation %g must be in range 0-4\n", attn ); return 0; } if( chan < 0 || chan > 7 ) { - MsgDev( D_ERROR, "SV_StartSound: channel = %i\n", chan ); + MsgDev( D_ERROR, "SV_StartSound: channel must be in range 0-7\n" ); return 0; } @@ -1796,36 +1796,30 @@ int SV_BuildSoundMsg( edict_t *ent, int chan, const char *samp, int vol, float a return 0; } - if( !samp || !*samp ) + if( !sample || !*sample ) { MsgDev( D_ERROR, "SV_StartSound: passed NULL sample\n" ); return 0; } - if( samp[0] == '!' && Q_isdigit( samp + 1 )) + if( sample[0] == '!' && Q_isdigit( sample + 1 )) { flags |= SND_SENTENCE; - sound_idx = Q_atoi( samp + 1 ); - - if( sound_idx >= 1536 ) - { - MsgDev( D_ERROR, "SV_StartSound: invalid sentence number %s.\n", samp ); - return 0; - } + sound_idx = Q_atoi( sample + 1 ); } - else if( samp[0] == '#' && Q_isdigit( samp + 1 )) + else if( sample[0] == '#' && Q_isdigit( sample + 1 )) { - flags |= SND_SENTENCE; - sound_idx = Q_atoi( samp + 1 ) + 1536; + flags |= SND_SENTENCE|SND_SEQUENCE; + sound_idx = Q_atoi( sample + 1 ); } else { // precache_sound can be used twice: cache sounds when loading // and return sound index when server is active - sound_idx = SV_SoundIndex( samp ); + sound_idx = SV_SoundIndex( sample ); } - if( !ent->v.modelindex || !ent->v.model ) + if( !ent || !ent->v.modelindex || !ent->v.model ) entityIndex = 0; else if( SV_IsValidEdict( ent->v.aiment )) entityIndex = NUM_FOR_EDICT( ent->v.aiment ); @@ -1835,23 +1829,19 @@ int SV_BuildSoundMsg( edict_t *ent, int chan, const char *samp, int vol, float a if( attn != ATTN_NONE ) flags |= SND_ATTENUATION; if( pitch != PITCH_NORM ) flags |= SND_PITCH; - if( sound_idx > 255 ) flags |= SND_LARGE_INDEX; - // not sending (because this is out of range) flags &= ~SND_SPAWNING; MSG_BeginServerCmd( &sv.multicast, svc_sound ); - MSG_WriteWord( &sv.multicast, flags ); - if( flags & SND_LARGE_INDEX ) - MSG_WriteWord( &sv.multicast, sound_idx ); - else MSG_WriteByte( &sv.multicast, sound_idx ); - MSG_WriteByte( &sv.multicast, chan ); + MSG_WriteUBitLong( &sv.multicast, flags, MAX_SND_FLAGS_BITS ); + MSG_WriteUBitLong( &sv.multicast, sound_idx, MAX_SOUND_BITS ); + MSG_WriteUBitLong( &sv.multicast, chan, MAX_SND_CHAN_BITS ); if( flags & SND_VOLUME ) MSG_WriteByte( &sv.multicast, vol ); if( flags & SND_ATTENUATION ) MSG_WriteByte( &sv.multicast, attn * 64 ); if( flags & SND_PITCH ) MSG_WriteByte( &sv.multicast, pitch ); - MSG_WriteWord( &sv.multicast, entityIndex ); + MSG_WriteUBitLong( &sv.multicast, entityIndex, MAX_ENTITY_BITS ); MSG_WriteVec3Coord( &sv.multicast, pos ); return 1; @@ -1915,8 +1905,8 @@ void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float } else if( sample[0] == '#' && Q_isdigit( sample + 1 )) { - flags |= SND_SENTENCE; - sound_idx = Q_atoi( sample + 1 ) + 1536; + flags |= SND_SENTENCE|SND_SEQUENCE; + sound_idx = Q_atoi( sample + 1 ); } else { @@ -1929,24 +1919,20 @@ void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float entityIndex = NUM_FOR_EDICT( ent->v.aiment ); else entityIndex = NUM_FOR_EDICT( ent ); - if( sound_idx > 255 ) flags |= SND_LARGE_INDEX; - // not sending (because this is out of range) flags &= ~SND_FILTER_CLIENT; flags &= ~SND_SPAWNING; MSG_BeginServerCmd( &sv.multicast, svc_sound ); - MSG_WriteWord( &sv.multicast, flags ); - if( flags & SND_LARGE_INDEX ) - MSG_WriteWord( &sv.multicast, sound_idx ); - else MSG_WriteByte( &sv.multicast, sound_idx ); - MSG_WriteByte( &sv.multicast, chan ); + MSG_WriteUBitLong( &sv.multicast, flags, MAX_SND_FLAGS_BITS ); + MSG_WriteUBitLong( &sv.multicast, sound_idx, MAX_SOUND_BITS ); + MSG_WriteUBitLong( &sv.multicast, chan, MAX_SND_CHAN_BITS ); if( flags & SND_VOLUME ) MSG_WriteByte( &sv.multicast, vol * 255 ); if( flags & SND_ATTENUATION ) MSG_WriteByte( &sv.multicast, attn * 64 ); if( flags & SND_PITCH ) MSG_WriteByte( &sv.multicast, pitch ); - MSG_WriteWord( &sv.multicast, entityIndex ); + MSG_WriteUBitLong( &sv.multicast, entityIndex, MAX_ENTITY_BITS ); MSG_WriteVec3Coord( &sv.multicast, origin ); SV_Multicast( msg_dest, origin, NULL, false, filter ); @@ -1960,7 +1946,7 @@ pfnEmitAmbientSound */ void pfnEmitAmbientSound( edict_t *ent, float *pos, const char *sample, float vol, float attn, int flags, int pitch ) { - int number = 0, sound_idx; + int entityIndex = 0, sound_idx; int msg_dest = MSG_PAS_R; if( !sample ) return; @@ -1987,7 +1973,7 @@ void pfnEmitAmbientSound( edict_t *ent, float *pos, const char *sample, float vo else msg_dest = MSG_ALL; if( SV_IsValidEdict( ent )) - number = NUM_FOR_EDICT( ent ); + entityIndex = NUM_FOR_EDICT( ent ); // always sending stop sound command if( flags & SND_STOP ) msg_dest = MSG_ALL; @@ -1999,8 +1985,8 @@ void pfnEmitAmbientSound( edict_t *ent, float *pos, const char *sample, float vo } else if( sample[0] == '#' && Q_isdigit( sample + 1 )) { - flags |= SND_SENTENCE; - sound_idx = Q_atoi( sample + 1 ) + 1536; + flags |= SND_SENTENCE|SND_SEQUENCE; + sound_idx = Q_atoi( sample + 1 ); } else { @@ -2009,24 +1995,20 @@ void pfnEmitAmbientSound( edict_t *ent, float *pos, const char *sample, float vo sound_idx = SV_SoundIndex( sample ); } - if( sound_idx > 255 ) flags |= SND_LARGE_INDEX; - // not sending (because this is out of range) flags &= ~SND_SPAWNING; MSG_BeginServerCmd( &sv.multicast, svc_ambientsound ); - MSG_WriteWord( &sv.multicast, flags ); - if( flags & SND_LARGE_INDEX ) - MSG_WriteWord( &sv.multicast, sound_idx ); - else MSG_WriteByte( &sv.multicast, sound_idx ); - MSG_WriteByte( &sv.multicast, CHAN_STATIC ); + MSG_WriteUBitLong( &sv.multicast, flags, MAX_SND_FLAGS_BITS ); + MSG_WriteUBitLong( &sv.multicast, sound_idx, MAX_SOUND_BITS ); + MSG_WriteUBitLong( &sv.multicast, CHAN_STATIC, MAX_SND_CHAN_BITS ); if( flags & SND_VOLUME ) MSG_WriteByte( &sv.multicast, vol * 255 ); if( flags & SND_ATTENUATION ) MSG_WriteByte( &sv.multicast, attn * 64 ); if( flags & SND_PITCH ) MSG_WriteByte( &sv.multicast, pitch ); // plays from fixed position - MSG_WriteWord( &sv.multicast, number ); + MSG_WriteUBitLong( &sv.multicast, entityIndex, MAX_ENTITY_BITS ); MSG_WriteVec3Coord( &sv.multicast, pos ); SV_Multicast( msg_dest, pos, NULL, false, false ); @@ -2343,20 +2325,20 @@ void pfnParticleEffect( const float *org, const float *dir, float color, float c return; } - if( MSG_GetNumBytesLeft( &sv.datagram ) >= 16 ) - { - MSG_BeginServerCmd( &sv.multicast, svc_particle ); - MSG_WriteVec3Coord( &sv.multicast, org ); - v = bound( -128, dir[0] * 16.0f, 127 ); - MSG_WriteChar( &sv.multicast, v ); - v = bound( -128, dir[1] * 16.0f, 127 ); - MSG_WriteChar( &sv.multicast, v ); - v = bound( -128, dir[2] * 16.0f, 127 ); - MSG_WriteChar( &sv.multicast, v ); - MSG_WriteByte( &sv.multicast, count ); - MSG_WriteByte( &sv.multicast, color ); - MSG_WriteByte( &sv.multicast, 0 ); - } + if( MSG_GetNumBytesLeft( &sv.datagram ) < 16 ) + return; + + MSG_BeginServerCmd( &sv.multicast, svc_particle ); + MSG_WriteVec3Coord( &sv.multicast, org ); + v = bound( -128, dir[0] * 16.0f, 127 ); + MSG_WriteChar( &sv.multicast, v ); + v = bound( -128, dir[1] * 16.0f, 127 ); + MSG_WriteChar( &sv.multicast, v ); + v = bound( -128, dir[2] * 16.0f, 127 ); + MSG_WriteChar( &sv.multicast, v ); + MSG_WriteByte( &sv.multicast, count ); + MSG_WriteByte( &sv.multicast, color ); + MSG_WriteByte( &sv.multicast, 0 ); } /* @@ -2429,7 +2411,7 @@ void pfnMessageBegin( int msg_dest, int msg_num, const float *pOrigin, edict_t * // check range msg_num = bound( svc_bad, msg_num, 255 ); - if( msg_num < svc_lastmsg ) + if( msg_num <= svc_lastmsg ) { svgame.msg_index = -msg_num; // this is a system message svgame.msg_name = svc_strings[msg_num]; @@ -2441,7 +2423,7 @@ void pfnMessageBegin( int msg_dest, int msg_num, const float *pOrigin, edict_t * else { // check for existing - for( i = 0; i < MAX_USER_MESSAGES && svgame.msg[i].name[0]; i++ ) + for( i = 1; i < MAX_USER_MESSAGES && svgame.msg[i].name[0]; i++ ) { if( svgame.msg[i].number == msg_num ) break; // found @@ -3060,7 +3042,7 @@ int pfnRegUserMsg( const char *pszName, int iSize ) iSize = bound( -1, iSize, 255 ); // message 0 is reserved for svc_bad - for( i = 0; i < MAX_USER_MESSAGES && svgame.msg[i].name[0]; i++ ) + for( i = 1; i < MAX_USER_MESSAGES && svgame.msg[i].name[0]; i++ ) { // see if already registered if( !Q_strcmp( svgame.msg[i].name, pszName )) diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 18a3684b..98289a4f 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -310,7 +310,7 @@ void SV_ReadPackets( void ) if( Netchan_Process( &cl->netchan, &net_message )) { - if(( sv_maxclients->integer == 1 && !FBitSet( host.features, ENGINE_FIXED_FRAMERATE )) || cl->state != cs_spawned ) + if( sv_maxclients->integer == 1 || cl->state != cs_spawned ) SetBits( cl->flags, FCL_SEND_NET_MESSAGE ); // reply at end of frame // this is a valid, sequenced packet, so process it @@ -329,7 +329,18 @@ void SV_ReadPackets( void ) if( Netchan_CopyNormalFragments( &cl->netchan, &net_message, &curSize )) { MSG_Init( &net_message, "ClientPacket", net_message_buffer, curSize ); - SV_ExecuteClientMessage( cl, &net_message ); + + if( sv_maxclients->integer == 1 || cl->state != cs_spawned ) + SetBits( cl->flags, FCL_SEND_NET_MESSAGE ); // reply at end of frame + + // this is a valid, sequenced packet, so process it + if( cl->state != cs_zombie ) + { + cl->lastmessage = host.realtime; // don't timeout + SV_ExecuteClientMessage( cl, &net_message ); + svgame.globals->frametime = sv.frametime; + svgame.globals->time = sv.time; + } } if( Netchan_CopyFileFragments( &cl->netchan, &net_message )) diff --git a/engine/server/sv_save.c b/engine/server/sv_save.c index 2a22b170..77118137 100644 --- a/engine/server/sv_save.c +++ b/engine/server/sv_save.c @@ -505,7 +505,7 @@ void RestoreSound( soundlist_t *entry ) edict_t *ent; // this can happens if serialized map contain 4096 static decals... - if( MSG_GetNumBytesLeft( &sv.signon ) >= 20 ) + if( MSG_GetNumBytesLeft( &sv.signon ) < 36 ) return; if( entry->name[0] == '!' && Q_isdigit( entry->name + 1 )) @@ -515,8 +515,8 @@ void RestoreSound( soundlist_t *entry ) } else if( entry->name[0] == '#' && Q_isdigit( entry->name + 1 )) { - flags |= SND_SENTENCE; - soundIndex = Q_atoi( entry->name + 1 ) + 1536; + flags |= SND_SENTENCE|SND_SEQUENCE; + soundIndex = Q_atoi( entry->name + 1 ); } else { @@ -550,20 +550,16 @@ void RestoreSound( soundlist_t *entry ) if( entry->pitch != PITCH_NORM ) flags |= SND_PITCH; if( !entry->looping ) flags |= SND_STOP_LOOPING; // just in case - if( soundIndex > 255 ) flags |= SND_LARGE_INDEX; - MSG_BeginServerCmd( &sv.signon, svc_restoresound ); - MSG_WriteWord( &sv.signon, flags ); - if( flags & SND_LARGE_INDEX ) - MSG_WriteWord( &sv.signon, soundIndex ); - else MSG_WriteByte( &sv.signon, soundIndex ); - MSG_WriteByte( &sv.signon, entry->channel ); + MSG_WriteUBitLong( &sv.signon, flags, MAX_SND_FLAGS_BITS ); + MSG_WriteUBitLong( &sv.signon, soundIndex, MAX_SOUND_BITS ); + MSG_WriteUBitLong( &sv.signon, entry->channel, MAX_SND_CHAN_BITS ); if( flags & SND_VOLUME ) MSG_WriteByte( &sv.signon, entry->volume * 255 ); if( flags & SND_ATTENUATION ) MSG_WriteByte( &sv.signon, entry->attenuation * 64 ); if( flags & SND_PITCH ) MSG_WriteByte( &sv.signon, entry->pitch ); - MSG_WriteWord( &sv.signon, entry->entnum ); + MSG_WriteUBitLong( &sv.signon, entry->entnum, MAX_ENTITY_BITS ); MSG_WriteVec3Coord( &sv.signon, entry->origin ); MSG_WriteByte( &sv.signon, entry->wordIndex );