12 Mar 2018

This commit is contained in:
g-cont 2018-03-12 00:00:00 +03:00 committed by Alibek Omarov
parent e96b555d6b
commit 556275f912
29 changed files with 505 additions and 313 deletions

View File

@ -33,7 +33,7 @@ cvar_t weaponstay = {"mp_weaponstay","0", FCVAR_SERVER };
cvar_t forcerespawn= {"mp_forcerespawn","1", FCVAR_SERVER };
cvar_t flashlight = {"mp_flashlight","0", FCVAR_SERVER };
cvar_t aimcrosshair= {"mp_autocrosshair","1", FCVAR_SERVER };
cvar_t decalfrequency = {"decalfrequency","30", FCVAR_SERVER };
cvar_t decalfrequency = {"decalfrequency","30", FCVAR_SERVER|FCVAR_ARCHIVE };
cvar_t teamlist = {"mp_teamlist","hgrunt;scientist", FCVAR_SERVER };
cvar_t teamoverride = {"mp_teamoverride","1" };
cvar_t defaultteam = {"mp_defaultteam","0" };

View File

@ -1339,7 +1339,7 @@ void CL_PlayDemo_f( void )
demo.starttime = CL_GetDemoPlaybackClock(); // for determining whether to read another message
Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableValue( "net_qport" ), NULL, NULL );
Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize );
memset( demo.cmds, 0, sizeof( demo.cmds ));
demo.angle_position = 1;

View File

@ -25,6 +25,8 @@ GNU General Public License for more details.
#define MAX_TOTAL_CMDS 32
#define MAX_CMD_BUFFER 8000
#define CONNECTION_PROBLEM_TIME 15.0 // 15 seconds
#define CL_CONNECTION_RETRIES 10
#define CL_TEST_RETRIES 5
CVAR_DEFINE_AUTO( mp_decals, "300", FCVAR_ARCHIVE, "decals limit in multiplayer" );
CVAR_DEFINE_AUTO( dev_overview, "0", 0, "draw level in overview-mode" );
@ -186,6 +188,14 @@ void CL_CheckClientState( void )
}
}
int CL_GetFragmentSize( void *unused )
{
if( Netchan_IsLocal( &cls.netchan ))
return FRAGMENT_LOCAL_SIZE;
return FRAGMENT_MAX_SIZE;
}
/*
=====================
CL_SignonReply
@ -702,7 +712,7 @@ void CL_WritePacket( void )
if( cl.maxclients == 1 || ( NET_IsLocalAddress( cls.netchan.remote_address ) && !host_limitlocal->value ))
send_command = true;
if(( host.realtime >= cls.nextcmdtime ) && Netchan_CanPacket( &cls.netchan ))
if(( host.realtime >= cls.nextcmdtime ) && Netchan_CanPacket( &cls.netchan, true ))
send_command = true;
if( cl.send_reply )
@ -1064,16 +1074,40 @@ void CL_CheckForResend( void )
if( !NET_StringToAdr( cls.servername, &adr ))
{
MsgDev( D_ERROR, "CL_CheckForResend: bad server address\n" );
cls.state = ca_disconnected;
cls.signon = 0;
CL_Disconnect();
return;
}
// only retry so many times before failure.
if( cls.connect_retry >= CL_CONNECTION_RETRIES )
{
MsgDev( D_ERROR, "CL_CheckForResend: couldn't connected\n" );
CL_Disconnect();
return;
}
if( adr.port == 0 ) adr.port = MSG_BigShort( PORT_SERVER );
if( cls.connect_retry == CL_TEST_RETRIES )
{
// too many fails use default connection method
Netchan_OutOfBandPrint( NS_CLIENT, adr, "getchallenge\n" );
Cvar_SetValue( "cl_dlmax", FRAGMENT_MAX_SIZE );
cls.connect_time = host.realtime;
cls.connect_retry++;
return;
}
cls.max_fragment_size = Q_max( FRAGMENT_MAX_SIZE, cls.max_fragment_size >> Q_min( 1, cls.connect_retry ));
cls.connect_time = host.realtime; // for retransmit requests
cls.connect_retry++;
Con_Printf( "Connecting to %s...\n", cls.servername );
#if 0
Netchan_OutOfBandPrint( NS_CLIENT, adr, "getchallenge\n" );
#else
Netchan_OutOfBandPrint( NS_CLIENT, adr, "bandwidth %i %i\n", PROTOCOL_VERSION, cls.max_fragment_size );
#endif
}
resource_t *CL_AddResource( resourcetype_t type, const char *name, int size, qboolean bFatalIfMissing, int index )
@ -1157,6 +1191,8 @@ void CL_Connect_f( void )
cls.state = ca_connecting;
Q_strncpy( cls.servername, server, sizeof( cls.servername ));
cls.connect_time = MAX_HEARTBEAT; // CL_CheckForResend() will fire immediately
cls.max_fragment_size = FRAGMENT_MAX_SIZE; // guess a we can establish connection with maximum fragment size
cls.connect_retry = 0;
cls.spectator = false;
cls.signon = 0;
}
@ -1229,16 +1265,17 @@ void CL_ClearState( void )
{
int i;
CL_ClearResourceLists();
for( i = 0; i < MAX_CLIENTS; i++ )
COM_ClearCustomizationList( &cl.players[i].customdata, false );
S_StopAllSounds ( true );
CL_ClearEffects ();
CL_FreeEdicts ();
CL_ClearPhysEnts ();
NetAPI_CancelAllRequests();
CL_ClearResourceLists();
for( i = 0; i < MAX_CLIENTS; i++ )
COM_ClearCustomizationList( &cl.players[i].customdata, false );
// wipe the entire cl structure
memset( &cl, 0, sizeof( cl ));
@ -1284,9 +1321,9 @@ void CL_SendDisconnectMessage( void )
cls.netchan.remote_address.type = NA_LOOPBACK;
// make sure message will be delivered
Netchan_Transmit( &cls.netchan, MSG_GetNumBytesWritten( &buf ), MSG_GetData( &buf ));
Netchan_Transmit( &cls.netchan, MSG_GetNumBytesWritten( &buf ), MSG_GetData( &buf ));
Netchan_Transmit( &cls.netchan, MSG_GetNumBytesWritten( &buf ), MSG_GetData( &buf ));
Netchan_TransmitBits( &cls.netchan, MSG_GetNumBitsWritten( &buf ), MSG_GetData( &buf ));
Netchan_TransmitBits( &cls.netchan, MSG_GetNumBitsWritten( &buf ), MSG_GetData( &buf ));
Netchan_TransmitBits( &cls.netchan, MSG_GetNumBitsWritten( &buf ), MSG_GetData( &buf ));
}
/*
@ -1300,7 +1337,7 @@ void CL_Reconnect( qboolean setup_netchan )
{
if( setup_netchan )
{
Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableValue( "net_qport" ), NULL, NULL );
Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize );
}
else
{
@ -1340,6 +1377,7 @@ void CL_Disconnect( void )
cls.connect_time = 0;
cls.changedemo = false;
cls.max_fragment_size = FRAGMENT_MAX_SIZE; // reset fragment size
CL_Stop_f();
// send a disconnect message to the server
@ -1353,6 +1391,7 @@ void CL_Disconnect( void )
Netchan_Clear( &cls.netchan );
cls.state = ca_disconnected;
cls.connect_retry = 0;
cls.signon = 0;
// back to menu in non-developer mode
@ -1741,6 +1780,60 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
// print command from somewhere
Con_Printf( "%s", MSG_ReadString( msg ));
}
else if( !Q_strcmp( c, "testpacket" ))
{
byte recv_buf[NET_MAX_FRAGMENT];
dword crcValue = MSG_ReadLong( msg );
int realsize = MSG_GetMaxBytes( msg ) - MSG_GetNumBytesRead( msg );
dword crcValue2 = 0;
if( cls.max_fragment_size != MSG_GetMaxBytes( msg ))
{
if( cls.connect_retry >= CL_TEST_RETRIES )
{
// too many fails use default connection method
Netchan_OutOfBandPrint( NS_CLIENT, from, "getchallenge\n" );
Cvar_SetValue( "cl_dlmax", FRAGMENT_MAX_SIZE );
cls.connect_time = host.realtime;
return;
}
// if we waiting more than cl_timeout or packet was trashed
Msg( "got testpacket, size mismatched %d should be %d\n", MSG_GetMaxBytes( msg ), cls.max_fragment_size );
cls.connect_time = MAX_HEARTBEAT;
return; // just wait for a next responce
}
// reading test buffer
MSG_ReadBytes( msg, recv_buf, realsize );
// procssing the CRC
CRC32_ProcessBuffer( &crcValue2, recv_buf, realsize );
if( crcValue == crcValue2 )
{
// packet was sucessfully delivered, adjust the fragment size and get challenge
Msg( "CRC %p is matched, get challenge, fragment size %d\n", crcValue, cls.max_fragment_size );
Netchan_OutOfBandPrint( NS_CLIENT, from, "getchallenge\n" );
Cvar_SetValue( "cl_dlmax", cls.max_fragment_size );
cls.connect_time = host.realtime;
}
else
{
if( cls.connect_retry >= CL_TEST_RETRIES )
{
// too many fails use default connection method
Netchan_OutOfBandPrint( NS_CLIENT, from, "getchallenge\n" );
Cvar_SetValue( "cl_dlmax", FRAGMENT_MAX_SIZE );
cls.connect_time = host.realtime;
return;
}
Msg( "got testpacket, CRC mismatched %p should be %p, trying next fragment size %d\n", crcValue2, crcValue, cls.max_fragment_size >> 1 );
// trying the next size of packet
cls.connect_time = MAX_HEARTBEAT;
}
}
else if( !Q_strcmp( c, "ping" ))
{
// ping from somewhere

View File

@ -865,17 +865,17 @@ void CL_RemoveCustomization( int nPlayerNum, customization_t *pRemove )
if( pList->bInUse && pList->pInfo )
{
if ( pList->resource.type == t_decal )
if( pList->resource.type == t_decal )
{
if( cls.state == ca_active )
R_DecalRemoveAll( ~nPlayerNum );
R_DecalRemoveAll( pList->nUserData1 );
FS_FreeImage( pList->pInfo );
}
}
cl.players[nPlayerNum].customdata.pNext = pNext;
Mem_Free( pRemove );
Mem_Free( pList );
break;
}
}
@ -888,64 +888,66 @@ CL_ParseCustomization
void CL_ParseCustomization( sizebuf_t *msg )
{
customization_t *pExistingCustomization;
resource_t *resource;
customization_t *pList;
qboolean bFound;
resource_t *pRes;
int i;
i = MSG_ReadByte( msg );
if( i >= MAX_CLIENTS )
Host_Error( "Bogus player index during customization parsing.\n" );
resource = Mem_Alloc( cls.mempool, sizeof( resource_t ));
resource->type = MSG_ReadByte( msg );
pRes = Mem_Alloc( cls.mempool, sizeof( resource_t ));
pRes->type = MSG_ReadByte( msg );
Q_strncpy( resource->szFileName, MSG_ReadString( msg ), sizeof( resource->szFileName ));
resource->nIndex = MSG_ReadShort( msg );
resource->nDownloadSize = MSG_ReadLong( msg );
resource->ucFlags = MSG_ReadByte( msg ) & ~RES_WASMISSING;
resource->pNext = resource->pPrev = NULL;
Q_strncpy( pRes->szFileName, MSG_ReadString( msg ), sizeof( pRes->szFileName ));
pRes->nIndex = MSG_ReadShort( msg );
pRes->nDownloadSize = MSG_ReadLong( msg );
pRes->ucFlags = MSG_ReadByte( msg ) & ~RES_WASMISSING;
pRes->pNext = pRes->pPrev = NULL;
if( FBitSet( resource->ucFlags, RES_CUSTOM ))
MSG_ReadBytes( msg, resource->rgucMD5_hash, 16 );
resource->playernum = i;
if( FBitSet( pRes->ucFlags, RES_CUSTOM ))
MSG_ReadBytes( msg, pRes->rgucMD5_hash, 16 );
pRes->playernum = i;
if( !cl_allow_download.value )
{
Con_DPrintf( "Refusing new resource, cl_allow_download set to 0\n" );
Mem_Free( resource );
Mem_Free( pRes );
return;
}
if( cls.state == ca_active && !cl_download_ingame.value )
{
Con_DPrintf( "Refusing new resource, cl_download_ingame set to 0\n" );
Mem_Free( resource );
Mem_Free( pRes );
return;
}
pExistingCustomization = CL_PlayerHasCustomization( i, resource->type );
pExistingCustomization = CL_PlayerHasCustomization( i, pRes->type );
if( pExistingCustomization )
CL_RemoveCustomization( i, pExistingCustomization );
bFound = false;
for( pList = cl.players[resource->playernum].customdata.pNext; pList; pList = pList->pNext )
for( pList = cl.players[pRes->playernum].customdata.pNext; pList; pList = pList->pNext )
{
if( !memcmp( pList->resource.rgucMD5_hash, resource->rgucMD5_hash, 16 ) )
if( !memcmp( pList->resource.rgucMD5_hash, pRes->rgucMD5_hash, 16 ))
{
bFound = true;
break;
}
}
if( HPAK_GetDataPointer( CUSTOM_RES_PATH, resource, NULL, NULL ))
if( HPAK_GetDataPointer( CUSTOM_RES_PATH, pRes, NULL, NULL ))
{
qboolean bError = false;
if( !bFound )
{
if( !COM_CreateCustomization( &cl.players[resource->playernum].customdata, resource, resource->playernum, RES_FATALIFMISSING, NULL, NULL ))
pList = &cl.players[pRes->playernum].customdata;
if( !COM_CreateCustomization( pList, pRes, pRes->playernum, FCUST_FROMHPAK, NULL, NULL ))
bError = true;
}
else
@ -954,13 +956,13 @@ void CL_ParseCustomization( sizebuf_t *msg )
}
if( bError ) Con_DPrintf( "Error loading customization\n" );
Mem_Free( resource );
Mem_Free( pRes );
}
else
{
resource->ucFlags |= RES_WASMISSING;
CL_AddToResourceList( resource, &cl.resourcesneeded );
Con_Printf( "Requesting %s from server\n", resource );
SetBits( pRes->ucFlags, RES_WASMISSING );
CL_AddToResourceList( pRes, &cl.resourcesneeded );
Con_Printf( "Requesting %s from server\n", pRes->szFileName );
CL_StartResourceDownloading( "Custom resource propagation...\n", true );
}
}
@ -1016,6 +1018,31 @@ void CL_ParseResourceRequest( sizebuf_t *msg )
}
}
/*
==================
CL_CreateCustomizationList
loading custom decal for self
==================
*/
void CL_CreateCustomizationList( void )
{
resource_t *pResource;
player_info_t *pPlayer;
int i;
pPlayer = &cl.players[cl.playernum];
pPlayer->customdata.pNext = NULL;
for( i = 0; i < cl.num_resources; i++ )
{
pResource = &cl.resourcelist[i];
if( !COM_CreateCustomization( &pPlayer->customdata, pResource, cl.playernum, 0, NULL, NULL ))
Con_Printf( "problem with client customization %i, ignoring...", pResource );
}
}
/*
==================
CL_ParseFileTransferFailed
@ -1157,6 +1184,10 @@ void CL_ParseServerData( sizebuf_t *msg )
cls.scrshot_request = scrshot_plaque; // request levelshot even if exist (check filetime)
}
for( i = 0; i < MAX_CLIENTS; i++ )
COM_ClearCustomizationList( &cl.players[i].customdata, true );
CL_CreateCustomizationList();
// request resources from server
CL_ServerCommand( true, "sendres %i\n", cl.servercount );

View File

@ -116,7 +116,16 @@ add client-side resource to list
*/
void CL_AddClientResource( const char *filename, int type )
{
resource_t *pResource;
resource_t *p, *pResource;
for( p = cl.resourcesneeded.pNext; p != &cl.resourcesneeded; p = p->pNext )
{
if( !Q_stricmp( p->szFileName, filename ))
break;
}
if( p == &cl.resourcesneeded )
return; // already existed ?
pResource = Mem_Alloc( cls.mempool, sizeof( resource_t ));
@ -2392,13 +2401,13 @@ void CL_ParseTempEntity( sizebuf_t *msg )
R_RicochetSound( pos );
break;
case TE_PLAYERDECAL:
color = MSG_ReadByte( &buf ); // playernum
color = MSG_ReadByte( &buf ) - 1; // playernum
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
entityIndex = MSG_ReadShort( &buf );
decalIndex = MSG_ReadByte( &buf );
CL_PlayerDecal( CL_DecalIndex( decalIndex ), entityIndex, pos );
CL_PlayerDecal( color, decalIndex, entityIndex, pos );
break;
case TE_BUBBLES:
case TE_BUBBLETRAIL:
@ -2973,9 +2982,28 @@ CL_PlayerDecal
spray custom colored decal (clan logo etc)
===============
*/
void CL_PlayerDecal( int textureIndex, int entityIndex, float *pos )
void CL_PlayerDecal( int playernum, int customIndex, int entityIndex, float *pos )
{
R_DecalShoot( textureIndex, entityIndex, 0, pos, 0, 1.0f );
int textureIndex = 0;
customization_t *pCust = NULL;
if( playernum < MAX_CLIENTS )
pCust = cl.players[playernum].customdata.pNext;
if( pCust != NULL && pCust->pBuffer != NULL && pCust->pInfo != NULL )
{
if( FBitSet( pCust->resource.ucFlags, RES_CUSTOM ) && pCust->resource.type == t_decal && pCust->bTranslated )
{
if( !pCust->nUserData1 && pCust->pInfo != NULL )
{
const char *decalname = va( "player%dlogo%d", playernum, customIndex );
pCust->nUserData1 = GL_LoadTextureInternal( decalname, pCust->pInfo, TF_DECAL, false );
}
textureIndex = pCust->nUserData1;
}
}
R_DecalShoot( textureIndex, entityIndex, 0, pos, FDECAL_CUSTOM, 1.0f );
}
/*

View File

@ -568,6 +568,8 @@ typedef struct
// connection information
char servername[MAX_QPATH]; // name of server from original connect
double connect_time; // for connection retransmits
int max_fragment_size; // we needs to test a real network bandwidth
int connect_retry; // how many times we send a connect packet to the server
qboolean spectator; // not a real player, just spectator
local_state_t spectator_state; // init as client startup
@ -737,6 +739,7 @@ void CL_SendCommand( void );
void CL_Disconnect_f( void );
void CL_ProcessFile( qboolean successfully_received, const char *filename );
void CL_WriteUsercmd( sizebuf_t *msg, int from, int to );
int CL_GetFragmentSize( void *unused );
qboolean CL_PrecacheResources( void );
void CL_SetupOverviewParams( void );
void CL_UpdateFrameLerp( void );
@ -935,8 +938,9 @@ void CL_TestLights( void );
void CL_DrawParticlesExternal( const ref_viewpass_t *rvp, qboolean trans_pass, float frametime );
void CL_FireCustomDecal( int textureIndex, int entityIndex, int modelIndex, float *pos, int flags, float scale );
void CL_DecalShoot( int textureIndex, int entityIndex, int modelIndex, float *pos, int flags );
void CL_PlayerDecal( int textureIndex, int entityIndex, float *pos );
void CL_PlayerDecal( int playerIndex, int textureIndex, int entityIndex, float *pos );
void R_FreeDeadParticles( struct particle_s **ppparticles );
void CL_AddClientResource( const char *filename, int type );
void CL_AddClientResources( void );
int CL_FxBlend( cl_entity_t *e );
void CL_InitParticles( void );

View File

@ -1079,7 +1079,7 @@ void GL_DrawAliasFrame( aliashdr_t *paliashdr )
}
else
{
pglTexCoord2f (((float *)order)[0], ((float *)order)[1]);
pglTexCoord2f( ((float *)order)[0], ((float *)order)[1] );
}
order += 2;

View File

@ -146,7 +146,7 @@ static void R_GetDecalDimensions( int texture, int *width, int *height )
//-----------------------------------------------------------------------------
// compute the decal basis based on surface normal
//-----------------------------------------------------------------------------
void R_DecalComputeBasis( msurface_t *surf, vec3_t textureSpaceBasis[3] )
void R_DecalComputeBasis( msurface_t *surf, int flags, vec3_t textureSpaceBasis[3] )
{
vec3_t surfaceNormal;
@ -155,9 +155,31 @@ void R_DecalComputeBasis( msurface_t *surf, vec3_t textureSpaceBasis[3] )
VectorNegate( surf->plane->normal, surfaceNormal );
else VectorCopy( surf->plane->normal, surfaceNormal );
VectorNormalize2( surfaceNormal, textureSpaceBasis[2] );
#if 0
if( FBitSet( flags, FDECAL_CUSTOM ))
{
vec3_t pSAxis = { 1, 0, 0 };
// T = S cross N
CrossProduct( pSAxis, textureSpaceBasis[2], textureSpaceBasis[1] );
// Name sure they aren't parallel or antiparallel
// In that case, fall back to the normal algorithm.
if( DotProduct( textureSpaceBasis[1], textureSpaceBasis[1] ) > 1e-6 )
{
// S = N cross T
CrossProduct( textureSpaceBasis[2], textureSpaceBasis[1], textureSpaceBasis[0] );
VectorNormalizeFast( textureSpaceBasis[0] );
VectorNormalizeFast( textureSpaceBasis[1] );
return;
}
// Fall through to the standard algorithm for parallel or antiparallel
}
#endif
VectorNormalize2( surf->texinfo->vecs[0], textureSpaceBasis[0] );
VectorNormalize2( surf->texinfo->vecs[1], textureSpaceBasis[1] );
VectorNormalize2( surfaceNormal, textureSpaceBasis[2] );
}
void R_SetupDecalTextureSpaceBasis( decal_t *pDecal, msurface_t *surf, int texture, vec3_t textureSpaceBasis[3], float decalWorldScale[2] )
@ -165,7 +187,7 @@ void R_SetupDecalTextureSpaceBasis( decal_t *pDecal, msurface_t *surf, int textu
int width, height;
// Compute the non-scaled decal basis
R_DecalComputeBasis( surf, textureSpaceBasis );
R_DecalComputeBasis( surf, pDecal->flags, textureSpaceBasis );
R_GetDecalDimensions( texture, &width, &height );
// world width of decal = ptexture->width / pDecal->scale
@ -427,7 +449,7 @@ static decal_t *R_DecalIntersect( decalinfo_t *decalinfo, msurface_t *surf, int
// Don't steal bigger decals and replace them with smaller decals
// Don't steal permanent decals
if(!( pDecal->flags & FDECAL_PERMANENT ))
if( !FBitSet( pDecal->flags, FDECAL_PERMANENT ))
{
vec3_t testBasis[3];
vec3_t testPosition[2];
@ -624,7 +646,7 @@ void R_DecalSurface( msurface_t *surf, decalinfo_t *decalinfo )
// Determine the decal basis (measured in world space)
// Note that the decal basis vectors 0 and 1 will always lie in the same
// plane as the texture space basis vectorstextureVecsTexelsPerWorldUnits.
R_DecalComputeBasis( surf, decalinfo->m_Basis );
R_DecalComputeBasis( surf, decalinfo->m_Flags, decalinfo->m_Basis );
// Compute an effective width and height (axis aligned) in the parent texture space
// How does this work? decalBasis[0] represents the u-direction (width)
@ -1151,7 +1173,7 @@ int R_CreateDecalList( decallist_t *pList )
decal_t *pdecals;
// decal is in use and is not a custom decal
if( decal->psurface == NULL || FBitSet( decal->flags, FDECAL_DONTSAVE ))
if( decal->psurface == NULL || ( decal->flags & FDECAL_DONTSAVE ))
continue;
// compute depth

View File

@ -946,7 +946,7 @@ void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fv
VOX_LoadSound( target_chan, S_SkipSoundChar( sfx->name ));
Q_strncpy( target_chan->name, sfx->name, sizeof( target_chan->name ));
sfx = target_chan->sfx;
pSource = sfx->cache;
if( sfx ) pSource = sfx->cache;
}
else
{
@ -1092,7 +1092,7 @@ void S_RestoreSound( const vec3_t pos, int ent, int chan, sound_t handle, float
else
{
sfx = target_chan->sfx;
pSource = sfx->cache;
if( sfx ) pSource = sfx->cache;
}
}
else
@ -1183,7 +1183,7 @@ void S_AmbientSound( const vec3_t pos, int ent, sound_t handle, float fvol, floa
VOX_LoadSound( ch, S_SkipSoundChar( sfx->name ));
Q_strncpy( ch->name, sfx->name, sizeof( ch->name ));
sfx = ch->sfx;
pSource = sfx->cache;
if( sfx ) pSource = sfx->cache;
fvox = 1;
}
else

View File

@ -32,24 +32,24 @@ qboolean CustomDecal_Validate( void *raw, int nFileSize )
void COM_ClearCustomizationList( customization_t *pHead, qboolean bCleanDecals )
{
customization_t *pNext, *pCurrent;
customization_t *pCurrent;
customization_t *pNext;
for( pCurrent = pHead->pNext; pCurrent; pCurrent = pNext )
for( pCurrent = pHead->pNext; pCurrent != NULL; pCurrent = pNext )
{
pNext = pCurrent->pNext;
if( pCurrent->bInUse && pCurrent->pBuffer )
{
Mem_Free( pCurrent->pBuffer );
}
if( pCurrent->bInUse && pCurrent->pInfo )
{
if( pCurrent->resource.type == t_decal )
{
if( bCleanDecals && CL_Active( ))
R_DecalRemoveAll( ~pCurrent->resource.playernum );
R_DecalRemoveAll( pCurrent->nUserData1 );
}
FS_FreeImage( pCurrent->pInfo );
}
Mem_Free( pCurrent );
@ -60,9 +60,9 @@ void COM_ClearCustomizationList( customization_t *pHead, qboolean bCleanDecals )
qboolean COM_CreateCustomization( customization_t *pListHead, resource_t *pResource, int playernumber, int flags, customization_t **pOut, int *nLumps )
{
customization_t *pCust;
qboolean bError = false;
void *pNewBuffer = NULL;
int checksize = 0;
customization_t *pCust;
if( pOut ) *pOut = NULL;
@ -81,9 +81,10 @@ qboolean COM_CreateCustomization( customization_t *pListHead, resource_t *pResou
}
else
{
int checksize = 0;
pCust->pBuffer = COM_LoadFile( pResource->szFileName, 5, &checksize );
Msg( "loading %s, check %d, downoad %d\n", pResource->szFileName, checksize, pCust->resource.nDownloadSize );
pCust->pBuffer = FS_LoadFile( pResource->szFileName, &checksize, true );
if( checksize != pCust->resource.nDownloadSize )
bError = true;
}
if( bError )
@ -99,6 +100,10 @@ qboolean COM_CreateCustomization( customization_t *pListHead, resource_t *pResou
{
if( pResource->nDownloadSize >= (1 * 1024) && pResource->nDownloadSize <= ( 16 * 1024 ))
{
pCust->bTranslated = true;
pCust->nUserData1 = 0;
pCust->nUserData2 = 1;
if( !FBitSet( flags, FCUST_WIPEDATA ))
pCust->pInfo = FS_LoadImage( "#logo.bmp", pCust->pBuffer, pCust->resource.nDownloadSize );
else pCust->pInfo = NULL;

View File

@ -850,6 +850,7 @@ void Host_FreeCommon( void )
Image_Shutdown();
Sound_Shutdown();
Netchan_Shutdown();
HPAK_FlushHostQueue();
FS_Shutdown();
Mem_FreePool( &host.mempool );

View File

@ -71,8 +71,9 @@ void HPAK_FlushHostQueue( void )
{
hash_pack_queue_t *p;
for( p = gp_hpak_queue; p != NULL; p = p->next )
for( p = gp_hpak_queue; p != NULL; p = gp_hpak_queue )
{
gp_hpak_queue = p->next;
HPAK_AddLump( false, p->name, &p->resource, p->data, NULL );
freestring( p->name );
Mem_Free( p->data );
@ -193,9 +194,9 @@ static qboolean HPAK_FindResource( hpak_info_t *hpk, byte *hash, resource_t *pRe
void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource, byte *pData, file_t *pFile )
{
int i, j, position, length;
hpak_lump_t *pCurrentEntry = NULL;
string srcname, dstname;
hpak_info_t srcpak, dstpak;
hpak_lump_t *pCurrentEntry;
file_t *file_src;
file_t *file_dst;
char md5[16];
@ -318,7 +319,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
for( i = 0; i < srcpak.count; i++ )
{
if( memcmp( md5, srcpak.entries[i].resource.rgucMD5_hash, 16 ) < 0 )
if( memcmp( md5, srcpak.entries[i].resource.rgucMD5_hash, 16 ))
{
pCurrentEntry = &dstpak.entries[i];
@ -516,7 +517,7 @@ qboolean HPAK_ResourceForHash( const char *filename, byte *hash, resource_t *pRe
file_t *f;
hash_pack_queue_t *p;
if( !filename || !filename[0] )
if( !COM_CheckString( filename ))
return false;
for( p = gp_hpak_queue; p != NULL; p = p->next )
@ -639,7 +640,7 @@ qboolean HPAK_GetDataPointer( const char *filename, resource_t *pResource, byte
file_t *f;
int i;
if( !filename || !filename[0] )
if( !COM_CheckString( filename ))
return false;
if( buffer ) *buffer = NULL;

View File

@ -88,7 +88,7 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, size_t filesize )
return false;
// special hack for loading qfont
if( !Q_strncmp( "#XASH_SYSTEMFONT_001", name, 20 ))
if( !Q_strncmp( name, "#XASH_SYSTEMFONT_001", 20 ))
{
// NOTE: same as system font we can use 4-bit bmps only
// step1: move main layer into alpha-channel (give grayscale from RED channel)
@ -112,6 +112,14 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, size_t filesize )
memcpy( palette, buf_p, cbPalBytes );
// setup gradient alpha for player decal
if( !Q_strncmp( name, "#logo", 5 ))
{
for( i = 0; i < bhdr.colors; i++ )
palette[i][3] = i;
image.flags |= IMAGE_HAS_ALPHA;
}
if( host.overview_loading && bhdr.bitsPerPixel == 8 )
{
// convert green background into alpha-layer, make opacity for all other entries
@ -129,8 +137,7 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, size_t filesize )
if( Image_CheckFlag( IL_KEEP_8BIT ) && bhdr.bitsPerPixel == 8 )
{
pixbuf = image.palette = Mem_Alloc( host.imagepool, 1024 );
image.flags |= IMAGE_HAS_COLOR;
// bmp have a reversed palette colors
for( i = 0; i < bhdr.colors; i++ )
{

View File

@ -106,9 +106,29 @@ qboolean MSG_CheckOverflow( sizebuf_t *sb )
return MSG_Overflow( sb, 0 );
}
void MSG_SeekToBit( sizebuf_t *sb, int bitPos )
int MSG_SeekToBit( sizebuf_t *sb, int bitPos, int whence )
{
// compute the file offset
switch( whence )
{
case SEEK_CUR:
bitPos += sb->iCurBit;
break;
case SEEK_SET:
break;
case SEEK_END:
bitPos += sb->nDataBits;
break;
default:
return -1;
}
if( bitPos < 0 || bitPos > sb->nDataBits )
return -1;
sb->iCurBit = bitPos;
return 0;
}
void MSG_SeekToByte( sizebuf_t *sb, int bytePos )
@ -656,13 +676,13 @@ void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove )
sizebuf_t temp;
MSG_StartWriting( &temp, sb->pData, MSG_GetMaxBytes( sb ), startbit, -1 );
MSG_SeekToBit( sb, endbit );
MSG_SeekToBit( sb, endbit, SEEK_SET );
for( i = 0; i < remaining_to_end; i++ )
{
MSG_WriteOneBit( &temp, MSG_ReadOneBit( sb ));
}
MSG_SeekToBit( sb, startbit );
MSG_SeekToBit( sb, startbit, SEEK_SET );
sb->nDataBits -= bitstoremove;
}

View File

@ -58,10 +58,10 @@ typedef struct sizebuf_s
// common functions
void MSG_InitExt( sizebuf_t *sb, const char *pDebugName, void *pData, int nBytes, int nMaxBits );
void MSG_InitMasks( void ); // called once at startup engine
void MSG_SeekToBit( sizebuf_t *sb, int bitPos );
void MSG_SeekToByte( sizebuf_t *sb, int bytePos );
int MSG_SeekToBit( sizebuf_t *sb, int bitPos, int whence );
void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove );
_inline int MSG_TellBit( sizebuf_t *sb ) { return sb->iCurBit; }
_inline const char *MSG_GetName( sizebuf_t *sb ) { return sb->pDebugName; }
qboolean MSG_CheckOverflow( sizebuf_t *sb );
short MSG_BigShort( short swap );

View File

@ -27,11 +27,7 @@ GNU General Public License for more details.
#define FLOW_AVG ( 2.0 / 3.0 ) // how fast to converge flow estimates
#define FLOW_INTERVAL 0.1 // don't compute more often than this
#define MAX_RELIABLE_PAYLOAD 32768 // biggest packet that has frag and or reliable data
#define MAX_RELIABLE_PAYLOAD_BITS (MAX_RELIABLE_PAYLOAD<<3)
#define MAX_RESEND_PAYLOAD 36000
#define MAX_RESEND_PAYLOAD_BITS (MAX_RESEND_PAYLOAD<<3)
#define MAX_RELIABLE_PAYLOAD 1400 // biggest packet that has frag and or reliable data
// forward declarations
void Netchan_FlushIncoming( netchan_t *chan, int stream );
@ -98,7 +94,7 @@ int net_drop;
netadr_t net_from;
sizebuf_t net_message;
byte *net_mempool;
byte net_message_buffer[MAX_INIT_MSG];
byte net_message_buffer[NET_MAX_MESSAGE];
const char *ns_strings[NS_COUNT] =
{
@ -126,7 +122,7 @@ void Netchan_Init( void )
net_mempool = Mem_AllocPool( "Network Pool" );
MSG_InitMasks (); // initialize bit-masks
MSG_InitMasks(); // initialize bit-masks
}
void Netchan_Shutdown( void )
@ -159,10 +155,8 @@ detect a loopback message
*/
qboolean Netchan_IsLocal( netchan_t *chan )
{
#if 0 // FIXME
if( !NET_IsActive() || NET_IsLocalAddress( chan->remote_address ))
return true;
#endif
return false;
}
@ -219,10 +213,10 @@ Netchan_CanPacket
Returns true if the bandwidth choke isn't active
================
*/
qboolean Netchan_CanPacket( netchan_t *chan )
qboolean Netchan_CanPacket( netchan_t *chan, qboolean choke )
{
// never choke loopback packets.
if( !net_chokeloopback->value && NET_IsLocalAddress( chan->remote_address ))
if( !choke || !net_chokeloopback->value && NET_IsLocalAddress( chan->remote_address ))
{
chan->cleartime = host.realtime;
return true;
@ -241,11 +235,7 @@ void Netchan_UnlinkFragment( fragbuf_t *buf, fragbuf_t **list )
{
fragbuf_t *search;
if( !list )
{
MsgDev( D_ERROR, "Netchan_UnlinkFragment: Asked to unlink fragment from empty list, ignored\n" );
return;
}
if( !list ) return;
// at head of list
if( buf == *list )
@ -271,9 +261,8 @@ void Netchan_UnlinkFragment( fragbuf_t *buf, fragbuf_t **list )
}
search = search->next;
}
MsgDev( D_ERROR, "Netchan_UnlinkFragment: Couldn't find fragment\n" );
}
/*
==============================
Netchan_ClearFragbufs
@ -372,8 +361,8 @@ Sends an out-of-band datagram
*/
void Netchan_OutOfBand( int net_socket, netadr_t adr, int length, byte *data )
{
byte send_buf[MAX_PRINT_MSG];
sizebuf_t send;
byte send_buf[NET_MAX_PAYLOAD];
// write the packet header
MSG_Init( &send, "SequencePacket", send_buf, sizeof( send_buf ));
@ -397,8 +386,8 @@ Sends a text message in an out-of-band datagram
*/
void Netchan_OutOfBandPrint( int net_socket, netadr_t adr, char *format, ... )
{
static char string[MAX_PRINT_MSG];
va_list argptr;
char string[MAX_PRINT_MSG];
va_list argptr;
va_start( argptr, format );
Q_vsnprintf( string, sizeof( string ) - 1, format, argptr );
@ -578,7 +567,7 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg )
fragbuf_t *buf;
int chunksize;
int remaining;
int bits, pos;
int bytes, pos;
int bufferid = 1;
fragbufwaiting_t *wait, *p;
@ -587,38 +576,27 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg )
if( chan->pfnBlockSize != NULL )
chunksize = chan->pfnBlockSize( chan->client );
else chunksize = FRAGMENT_SV2CL_MAX_SIZE;
chunksize = 8192;
else chunksize = FRAGMENT_MAX_SIZE; // fallback
wait = (fragbufwaiting_t *)Mem_Alloc( net_mempool, sizeof( fragbufwaiting_t ));
remaining = MSG_GetNumBitsWritten( msg );
chunksize <<= 3; // convert bytes to bits
pos = 0; // current position in bits
remaining = MSG_GetNumBytesWritten( msg );
pos = 0; // current position in bytes
while( remaining > 0 )
{
byte buffer[NET_MAX_PAYLOAD];
sizebuf_t temp;
bits = Q_min( remaining, chunksize );
remaining -= bits;
bytes = Q_min( remaining, chunksize );
remaining -= bytes;
buf = Netchan_AllocFragbuf();
buf->bufferid = bufferid++;
// Copy in data
MSG_Clear( &buf->frag_message );
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 );
MSG_WriteBits( &buf->frag_message, &msg->pData[pos], bytes << 3 );
Netchan_AddFragbufToTail( wait, buf );
pos += bits;
pos += bytes;
}
// now add waiting list item to end of buffer queue
@ -747,10 +725,9 @@ void Netchan_CreateFileFragmentsFromBuffer( netchan_t *chan, char *filename, byt
if( chan->pfnBlockSize != NULL )
chunksize = chan->pfnBlockSize( chan->client );
else chunksize = FRAGMENT_SV2CL_MAX_SIZE;
wait = ( fragbufwaiting_t * )Mem_Alloc( net_mempool, sizeof( fragbufwaiting_t ));
else chunksize = FRAGMENT_MAX_SIZE; // fallback
wait = (fragbufwaiting_t *)Mem_Alloc( net_mempool, sizeof( fragbufwaiting_t ));
remaining = size;
pos = 0;
@ -766,13 +743,13 @@ void Netchan_CreateFileFragmentsFromBuffer( netchan_t *chan, char *filename, byt
if( firstfragment )
{
firstfragment = false;
// write filename
MSG_WriteString( &buf->frag_message, filename );
// send a bit less on first package
send -= MSG_GetNumBytesWritten( &buf->frag_message );
firstfragment = false;
}
buf->isbuffer = true;
@ -782,8 +759,8 @@ void Netchan_CreateFileFragmentsFromBuffer( netchan_t *chan, char *filename, byt
MSG_WriteBits( &buf->frag_message, pbuf + pos, send << 3 );
pos += send;
remaining -= send;
pos += send;
Netchan_AddFragbufToTail( wait, buf );
}
@ -798,9 +775,7 @@ void Netchan_CreateFileFragmentsFromBuffer( netchan_t *chan, char *filename, byt
p = chan->waitlist[FRAG_FILE_STREAM];
while( p->next )
{
p = p->next;
}
p->next = wait;
}
}
@ -822,17 +797,16 @@ int Netchan_CreateFileFragments( netchan_t *chan, const char *filename )
fragbufwaiting_t *wait, *p;
fragbuf_t *buf;
if( chan->pfnBlockSize != NULL )
chunksize = chan->pfnBlockSize( chan->client );
else chunksize = FRAGMENT_SV2CL_MAX_SIZE;
filesize = FS_FileSize( filename, false );
chunksize = 32768;
if( filesize <= 0 )
if(( filesize = FS_FileSize( filename, false )) <= 0 )
{
MsgDev( D_WARN, "Unable to open %s for transfer\n", filename );
Con_Printf( S_WARN "Unable to open %s for transfer\n", filename );
return 0;
}
if( chan->pfnBlockSize != NULL )
chunksize = chan->pfnBlockSize( chan->client );
else chunksize = FRAGMENT_MAX_SIZE; // fallback
wait = (fragbufwaiting_t *)Mem_Alloc( net_mempool, sizeof( fragbufwaiting_t ));
remaining = filesize;
pos = 0;
@ -849,13 +823,13 @@ chunksize = 32768;
if( firstfragment )
{
firstfragment = false;
// Write filename
MSG_WriteString( &buf->frag_message, filename );
// Send a bit less on first package
send -= MSG_GetNumBytesWritten( &buf->frag_message );
firstfragment = false;
}
buf->isfile = true;
@ -878,10 +852,7 @@ chunksize = 32768;
{
p = chan->waitlist[FRAG_FILE_STREAM];
while( p->next )
{
p = p->next;
}
p->next = wait;
}
@ -896,11 +867,12 @@ Netchan_FlushIncoming
*/
void Netchan_FlushIncoming( netchan_t *chan, int stream )
{
fragbuf_t *p, *n;
fragbuf_t *p, *n;
MSG_Clear( &net_message );
p = chan->incomingbufs[ stream ];
while( p )
{
n = p->next;
@ -919,7 +891,7 @@ Netchan_CopyNormalFragments
*/
qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *length )
{
size_t frag_num_bits = 0;
size_t size = 0;
fragbuf_t *p, *n;
if( !chan->incomingready[FRAG_NORMAL_STREAM] )
@ -927,7 +899,6 @@ qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *l
if( !chan->incomingbufs[FRAG_NORMAL_STREAM] )
{
MsgDev( D_ERROR, "Netchan_CopyNormalFragments: Called with no fragments readied\n" );
chan->incomingready[FRAG_NORMAL_STREAM] = false;
return false;
}
@ -941,8 +912,8 @@ qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *l
n = p->next;
// copy it in
MSG_WriteBits( msg, MSG_GetData( &p->frag_message ), MSG_GetNumBitsWritten( &p->frag_message ));
frag_num_bits += MSG_GetNumBitsWritten( &p->frag_message );
MSG_WriteBytes( msg, MSG_GetData( &p->frag_message ), MSG_GetNumBytesWritten( &p->frag_message ));
size += MSG_GetNumBytesWritten( &p->frag_message );
Mem_Free( p );
p = n;
@ -954,7 +925,7 @@ qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *l
chan->incomingready[FRAG_NORMAL_STREAM] = false;
// tell about message size
if( length ) *length = BitByte( frag_num_bits );
if( length ) *length = size;
return true;
}
@ -967,18 +938,16 @@ Netchan_CopyFileFragments
*/
qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
{
fragbuf_t *p, *n;
char filename[MAX_QPATH];
int nsize;
char filename[MAX_OSPATH];
int nsize, pos;
byte *buffer;
int pos;
fragbuf_t *p, *n;
if( !chan->incomingready[FRAG_FILE_STREAM] )
return false;
if( !chan->incomingbufs[FRAG_FILE_STREAM] )
{
MsgDev( D_WARN, "Netchan_CopyFileFragments: Called with no fragments readied\n" );
chan->incomingready[FRAG_FILE_STREAM] = false;
return false;
}
@ -988,42 +957,20 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
MSG_Init( msg, "NetMessage", net_message_buffer, sizeof( net_message_buffer ));
// copy in first chunk so we can get filename out
MSG_WriteBits( msg, MSG_GetData( &p->frag_message ), MSG_GetNumBitsWritten( &p->frag_message ));
MSG_SeekToBit( msg, 0 ); // rewind buffer
MSG_WriteBytes( msg, MSG_GetData( &p->frag_message ), MSG_GetNumBytesWritten( &p->frag_message ));
MSG_Clear( msg );
Q_strncpy( filename, MSG_ReadString( msg ), sizeof( filename ));
if( Q_strlen( filename ) <= 0 )
if( !COM_CheckString( filename ))
{
MsgDev( D_ERROR, "File fragment received with no filename\nFlushing input queue\n" );
// clear out bufs
Con_Printf( S_ERROR "file fragment received with no filename\nFlushing input queue\n" );
Netchan_FlushIncoming( chan, FRAG_FILE_STREAM );
return false;
}
else if( Q_strstr( filename, ".." ))
else if( filename[0] != '!' && !COM_IsSafeFileToDownload( filename ))
{
MsgDev( D_ERROR, "File fragment received with relative path, ignoring\n" );
// clear out bufs
Netchan_FlushIncoming( chan, FRAG_FILE_STREAM );
return false;
}
if( filename[0] != '!' && !COM_IsSafeFileToDownload( filename ))
{
Con_Printf( "File fragment received with bad path, ignoring\n" );
// Clear out bufs
Netchan_FlushIncoming( chan, FRAG_FILE_STREAM );
return false;
}
if( host.type == HOST_DEDICATED && filename[0] != '!' )
{
Con_Printf( "File fragment received with bad path, ignoring (2)\n" );
// Clear out bufs
Con_Printf( S_ERROR "file fragment received with bad path, ignoring\n" );
Netchan_FlushIncoming( chan, FRAG_FILE_STREAM );
return false;
}
@ -1032,9 +979,7 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
if( filename[0] != '!' && FS_FileExists( filename, false ))
{
MsgDev( D_ERROR, "Can't download %s, already exists\n", filename );
// clear out bufs
Con_Printf( S_ERROR "can't download %s, already exists\n", filename );
Netchan_FlushIncoming( chan, FRAG_FILE_STREAM );
return true;
}
@ -1045,14 +990,12 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
{
nsize += MSG_GetNumBytesWritten( &p->frag_message ); // Size will include a bit of slop, oh well
if( p == chan->incomingbufs[FRAG_FILE_STREAM] )
{
nsize -= MSG_GetNumBytesRead( msg );
}
p = p->next;
}
buffer = Mem_Alloc( net_mempool, nsize + 1 );
p = chan->incomingbufs[ FRAG_FILE_STREAM ];
p = chan->incomingbufs[FRAG_FILE_STREAM];
pos = 0;
while( p )
@ -1077,19 +1020,15 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
}
pos += cursize;
Mem_Free( p );
p = n;
}
// customization files goes int tempbuffer
if( filename[0] == '!' )
{
if( chan->tempbuffer )
{
Con_DPrintf( "Netchan_CopyFragments: Freeing holdover tempbuffer\n" );
Mem_Free( chan->tempbuffer );
}
chan->tempbuffer = buffer;
chan->tempbuffersize = nsize;
}
@ -1104,8 +1043,6 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
MSG_Clear( msg );
chan->incomingbufs[FRAG_FILE_STREAM] = NULL;
// reset flag
chan->incomingready[FRAG_FILE_STREAM] = false;
return true;
@ -1116,8 +1053,6 @@ qboolean Netchan_Validate( netchan_t *chan, sizebuf_t *sb, qboolean *frag_messag
int i, buffer, offset;
int count, length;
return true;
for( i = 0; i < MAX_STREAMS; i++ )
{
if( !frag_message[i] )
@ -1128,16 +1063,16 @@ return true;
offset = BitByte( frag_offset[i] );
length = BitByte( frag_length[i] );
if( buffer < 0 || buffer > 25000 )
if( buffer < 0 || buffer > NET_MAX_BUFFER_ID )
return false;
if( count < 0 || count > 25000 )
if( count < 0 || count > NET_MAX_BUFFERS_COUNT )
return false;
if( length < 0 || length > 2048 )
if( length < 0 || length > ( FRAGMENT_MAX_SIZE << 3 ))
return false;
if( offset < 0 || offset > 16384 )
if( offset < 0 || offset > ( FRAGMENT_MAX_SIZE << 3 ))
return false;
}
@ -1242,20 +1177,18 @@ A 0 length will still generate a packet and deal with the reliable messages.
*/
void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
{
sizebuf_t send;
int max_send_size, statId;
byte send_buf[NET_MAX_MESSAGE];
qboolean send_reliable_fragment;
qboolean send_resending = false;
uint w1, w2, statId;
qboolean send_reliable;
uint w1, w2;
sizebuf_t send;
int i, j;
float fRate;
// check for message overflow
if( MSG_CheckOverflow( &chan->message ))
{
MsgDev( D_ERROR, "%s:outgoing message overflow\n", NET_AdrToString( chan->remote_address ));
Con_Printf( S_ERROR "%s:outgoing message overflow\n", NET_AdrToString( chan->remote_address ));
return;
}
@ -1263,10 +1196,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
send_reliable = false;
if( chan->incoming_acknowledged > chan->last_reliable_sequence && chan->incoming_reliable_acknowledged != chan->reliable_sequence )
{
send_reliable = true;
send_resending = true;
}
// A packet can have "reliable payload + frag payload + unreliable payload
// frag payload can be a file chunk, if so, it needs to be parsed on the receiving end and reliable payload + unreliable payload need
@ -1281,7 +1211,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
// will be true if we are active and should let chan->message get some bandwidth
int send_from_frag[MAX_STREAMS] = { 0, 0 };
int send_from_regular = false;
int send_from_regular = 0;
// if we have data in the waiting list(s) and we have cleared the current queue(s), then
// push the waitlist(s) into the current queue(s)
@ -1303,7 +1233,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
send_from_regular = false;
// if the reliable buffer has gotten too big, queue it at the end of everything and clear out buffer
if( MSG_GetNumBitsWritten( &chan->message ) > MAX_RELIABLE_PAYLOAD_BITS )
if( MSG_GetNumBytesWritten( &chan->message ) > MAX_RELIABLE_PAYLOAD )
{
Netchan_CreateFragments_( chan, &chan->message );
MSG_Clear( &chan->message );
@ -1345,6 +1275,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
for( i = 0; i < MAX_STREAMS; i++ )
{
int newpayloadsize;
int fragment_size;
// is there someting in the fragbuf?
@ -1353,7 +1284,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
if( pbuf )
{
fragment_size = MSG_GetNumBitsWritten( &pbuf->frag_message );
fragment_size = MSG_GetNumBytesWritten( &pbuf->frag_message );
// files set size a bit differently.
if( pbuf->isfile && !pbuf->isbuffer )
@ -1362,8 +1293,10 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
}
}
newpayloadsize = (( chan->reliable_length + ( fragment_size << 3 )) + 7 ) >> 3;
// make sure we have enought space left
if( send_from_frag[i] && pbuf && (( chan->reliable_length + fragment_size ) < MAX_RELIABLE_PAYLOAD_BITS ))
if( send_from_frag[i] && pbuf && newpayloadsize < NET_MAX_FRAGMENT )
{
sizebuf_t temp;
@ -1373,7 +1306,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
// if it's not in-memory, then we'll need to copy it in frame the file handle.
if( pbuf->isfile && !pbuf->isbuffer )
{
byte filebuffer[NET_MAX_PAYLOAD];
byte filebuffer[NET_MAX_FRAGMENT];
file_t *file;
file = FS_Open( pbuf->filename, "rb", false );
@ -1430,7 +1363,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
// send the qport if we are a client
if( chan->sock == NS_CLIENT )
{
MSG_WriteWord( &send, Cvar_VariableValue( "net_qport" ));
MSG_WriteWord( &send, Cvar_VariableInteger( "net_qport" ));
}
if( send_reliable && send_reliable_fragment )
@ -1458,14 +1391,9 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
chan->last_reliable_sequence = chan->outgoing_sequence - 1;
}
// is there room for the unreliable payload?
max_send_size = MAX_RESEND_PAYLOAD_BITS;
if( !send_resending )
max_send_size = MSG_GetMaxBits( &send );
if(( max_send_size - MSG_GetNumBitsWritten( &send )) >= length )
if( MSG_GetNumBitsLeft( &send ) >= length )
MSG_WriteBits( &send, data, length );
else MsgDev( D_WARN, "Netchan_Transmit: unreliable message overflow\n" );
else Con_Printf( S_WARN "Netchan_Transmit: unreliable message overflow\n" );
// deal with packets that are too small for some networks
if( MSG_GetNumBytesWritten( &send ) < 16 && !NET_IsLocalAddress( chan->remote_address )) // packet too small for some networks
@ -1477,6 +1405,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
MSG_BeginClientCmd( &send, clc_nop );
else if( chan->sock == NS_SERVER )
MSG_BeginServerCmd( &send, svc_nop );
else break;
}
}
@ -1496,24 +1425,22 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
NET_SendPacket( chan->sock, MSG_GetNumBytesWritten( &send ), MSG_GetData( &send ), chan->remote_address );
}
fRate = 1.0f / chan->rate;
if( SV_Active() && sv_lan.value && sv_lan_rate.value > 1000.0 )
fRate = 1.0f / sv_lan_rate.value;
else fRate = 1.0f / chan->rate;
if( chan->cleartime < host.realtime )
chan->cleartime = host.realtime;
chan->cleartime += ( MSG_GetNumBytesWritten( &send ) + UDP_HEADER_SIZE ) * fRate;
if( net_showpackets->value == 1.0f )
if( net_showpackets->value && net_showpackets->value != 2.0f )
{
char c;
c = ( chan->sock == NS_CLIENT ) ? 'c' : 's';
Con_Printf( " %c --> sz=%i seq=%i ack=%i rel=%i tm=%f\n"
, c
Con_Printf( " %s --> sz=%i seq=%i ack=%i rel=%i tm=%f\n"
, ns_strings[chan->sock]
, MSG_GetNumBytesWritten( &send )
, ( chan->outgoing_sequence - 1 )
, chan->incoming_sequence
, ( chan->outgoing_sequence - 1 ) & 63
, chan->incoming_sequence & 63
, send_reliable ? 1 : 0
, (float)host.realtime );
}
@ -1556,8 +1483,6 @@ qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg )
if( !CL_IsPlaybackDemo() && !NET_CompareAdr( net_from, chan->remote_address ))
return false;
chan->last_received = host.realtime;
// get sequence numbers
MSG_Clear( msg );
sequence = MSG_ReadLong( msg );
@ -1594,17 +1519,13 @@ qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg )
sequence_ack &= ~BIT( 30 );
sequence_ack &= ~BIT( 31 );
if( net_showpackets->value == 2.0f )
if( net_showpackets->value && net_showpackets->value != 3.0f )
{
char c;
c = ( chan->sock == NS_CLIENT ) ? 'c' : 's';
Con_Printf( " %c <-- sz=%i seq=%i ack=%i rel=%i tm=%f\n"
, c
Con_Printf( " %s <-- sz=%i seq=%i ack=%i rel=%i tm=%f\n"
, ns_strings[chan->sock]
, MSG_GetMaxBytes( msg )
, sequence
, sequence_ack
, sequence & 63
, sequence_ack & 63
, reliable_message
, host.realtime );
}
@ -1626,7 +1547,7 @@ qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg )
// dropped packets don't keep the message from being used
net_drop = sequence - ( chan->incoming_sequence + 1 );
if( net_drop > 0 && net_showdrop->value )
Con_Printf( "%s:Dropped %i packets at %i\n", NET_AdrToString( chan->remote_address ), sequence - (chan->incoming_sequence + 1), sequence );
Con_Printf( "%s:dropped %i packets at %i\n", NET_AdrToString( chan->remote_address ), net_drop, sequence );
// if the current outgoing reliable message has been acknowledged
// clear the buffer to make way for the next
@ -1648,6 +1569,8 @@ qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg )
chan->incoming_reliable_sequence ^= 1;
}
chan->last_received = host.realtime;
// Update data flow stats
statId = chan->flow[FLOW_INCOMING].current & MASK_LATENT;
chan->flow[FLOW_INCOMING].stats[statId].size = MSG_GetMaxBytes( msg ) + UDP_HEADER_SIZE;
@ -1663,11 +1586,11 @@ qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg )
{
for( i = 0; i < MAX_STREAMS; i++ )
{
fragbuf_t *pbuf;
int j, inbufferid;
int intotalbuffers;
int oldpos, curbit;
int numbitstoremove;
fragbuf_t *pbuf;
if( !frag_message[i] )
continue;
@ -1681,23 +1604,20 @@ qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg )
if( pbuf )
{
byte buffer[NET_MAX_PAYLOAD];
byte buffer[NET_MAX_FRAGMENT];
int bits, size;
sizebuf_t temp;
int bits;
size = MSG_GetNumBitsRead( msg ) + frag_offset[i];
bits = frag_length[i];
// copy in data
MSG_Clear( &pbuf->frag_message );
MSG_StartReading( &temp, msg->pData, MSG_GetMaxBytes( msg ), MSG_GetNumBitsRead( msg ) + frag_offset[i], -1 );
MSG_StartReading( &temp, msg->pData, MSG_GetMaxBytes( msg ), size, -1 );
MSG_ReadBits( &temp, buffer, bits );
MSG_WriteBits( &pbuf->frag_message, buffer, bits );
}
else
{
MsgDev( D_ERROR, "Netchan_Process: Couldn't find buffer %i\n", inbufferid );
}
// count # of incoming bufs we've queued? are we done?
Netchan_CheckForCompletion( chan, i, intotalbuffers );
@ -1709,12 +1629,10 @@ qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg )
numbitstoremove = frag_length[i];
MSG_ExciseBits( msg, curbit, numbitstoremove );
MSG_SeekToBit( msg, oldpos );
MSG_SeekToBit( msg, oldpos, SEEK_SET );
for( j = i + 1; j < MAX_STREAMS; j++ )
{
frag_offset[j] -= frag_length[i];
}
}
// is there anything left to process?

View File

@ -1512,7 +1512,7 @@ qboolean MSG_WriteDeltaMovevars( sizebuf_t *msg, movevars_t *from, movevars_t *t
// if we have no changes - kill the message
if( !numChanges )
{
MSG_SeekToBit( msg, startBit );
MSG_SeekToBit( msg, startBit, SEEK_SET );
return false;
}
return true;
@ -1583,7 +1583,7 @@ void MSG_WriteClientData( sizebuf_t *msg, clientdata_t *from, clientdata_t *to,
if( numChanges ) return; // we have updates
MSG_SeekToBit( msg, startBit );
MSG_SeekToBit( msg, startBit, SEEK_SET );
MSG_WriteOneBit( msg, 0 ); // no changes
}
@ -1662,7 +1662,7 @@ void MSG_WriteWeaponData( sizebuf_t *msg, weapon_data_t *from, weapon_data_t *to
}
// if we have no changes - kill the message
if( !numChanges ) MSG_SeekToBit( msg, startBit );
if( !numChanges ) MSG_SeekToBit( msg, startBit, SEEK_SET );
}
/*
@ -1790,7 +1790,7 @@ void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *
}
// if we have no changes - kill the message
if( !numChanges && !force ) MSG_SeekToBit( msg, startBit );
if( !numChanges && !force ) MSG_SeekToBit( msg, startBit, SEEK_SET );
}
/*

View File

@ -89,7 +89,7 @@ dll_info_t winsock_dll = { "wsock32.dll", winsock_funcs, false };
typedef struct
{
byte data[MAX_INIT_MSG];
byte data[NET_MAX_MESSAGE];
int datalen;
} net_loopmsg_t;

View File

@ -24,7 +24,7 @@ typedef enum
} netsrc_t;
// Max length of unreliable message
#define MAX_DATAGRAM 4000
#define MAX_DATAGRAM 16384
// Max length of a multicast message
#define MAX_MULTICAST 8192 // some mods spamming for rain effect

View File

@ -40,6 +40,15 @@ GNU General Public License for more details.
// This is the packet payload without any header bytes (which are attached for actual sending)
#define NET_MAX_PAYLOAD MAX_INIT_MSG
// Theoretically maximum size of UDP-packet without header and hardware-specific data
#define NET_MAX_FRAGMENT 65536
// because encoded as highpart of uint32
#define NET_MAX_BUFFER_ID 32767
// because encoded as lowpart of uint32
#define NET_MAX_BUFFERS_COUNT 32767
// This is the payload plus any header info (excluding UDP header)
// Packet header is:
@ -105,16 +114,13 @@ typedef struct
int totalbytes;
} flow_t;
#define FRAGMENT_SV2CL_MIN_SIZE 256
#define FRAGMENT_SV2CL_MAX_SIZE 1024
// generic fragment structure
typedef struct fragbuf_s
{
struct fragbuf_s *next; // next buffer in chain
int bufferid; // id of this buffer
sizebuf_t frag_message; // message buffer where raw data is stored
byte frag_message_buf[NET_MAX_MESSAGE]; // the actual data sits here
byte frag_message_buf[NET_MAX_FRAGMENT]; // the actual data sits here
qboolean isfile; // is this a file buffer?
qboolean isbuffer; // is this file buffer from memory ( custom decal, etc. ).
char filename[MAX_OSPATH]; // name of the file to save out on remote host
@ -197,8 +203,10 @@ typedef struct netchan_s
extern netadr_t net_from;
extern netadr_t net_local;
extern sizebuf_t net_message;
extern byte net_message_buffer[MAX_INIT_MSG];
extern byte net_message_buffer[NET_MAX_MESSAGE];
extern convar_t *net_speeds;
extern convar_t sv_lan;
extern convar_t sv_lan_rate;
extern int net_drop;
void Netchan_Init( void );
@ -216,7 +224,8 @@ void Netchan_OutOfBandPrint( int net_socket, netadr_t adr, char *format, ... );
qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg );
void Netchan_UpdateProgress( netchan_t *chan );
qboolean Netchan_IncomingReady( netchan_t *chan );
qboolean Netchan_CanPacket( netchan_t *chan );
qboolean Netchan_CanPacket( netchan_t *chan, qboolean choke );
qboolean Netchan_IsLocal( netchan_t *chan );
void Netchan_ReportFlow( netchan_t *chan );
void Netchan_FragSend( netchan_t *chan );
void Netchan_Clear( netchan_t *chan );

View File

@ -154,10 +154,10 @@ GNU General Public License for more details.
// decal flags
#define FDECAL_PERMANENT 0x01 // This decal should not be removed in favor of any new decals
#define FDECAL_USE_LANDMARK 0x02 // This is a decal applied on a bmodel without origin-brush so we done in absoulute pos
#define FDECAL_DONTSAVE 0x04 // Decal was loaded from adjacent level, don't save it for this level
// reserved 0x08
// reserved 0x10
// reserved 0x20
#define FDECAL_CUSTOM 0x04 // This is a custom clan logo and should not be saved/restored
// reserved
// reserved
#define FDECAL_DONTSAVE 0x20 // Decal was loaded from adjacent level, don't save it for this level
#define FDECAL_STUDIO 0x40 // Indicates a studio decal
#define FDECAL_LOCAL_SPACE 0x80 // decal is in local space (any decal after serialization)
@ -174,6 +174,10 @@ GNU General Public License for more details.
#define MAX_RESOURCES (MAX_MODELS+MAX_SOUNDS+MAX_CUSTOM+MAX_EVENTS)
#define MAX_RESOURCE_BITS 13 // 13 bits 8192 resource (4096 models + 2048 sounds + 1024 events + 1024 files)
#define FRAGMENT_MIN_SIZE 1200 // default MTU
#define FRAGMENT_MAX_SIZE 64000 // minimal acceptable value without testing network bandwith
#define FRAGMENT_LOCAL_SIZE FRAGMENT_MAX_SIZE // local connection
extern const char *svc_strings[svc_lastmsg+1];
extern const char *clc_strings[clc_lastmsg+1];

View File

@ -410,8 +410,6 @@ extern server_t sv; // local server
extern svgame_static_t svgame; // persistant game info
extern areanode_t sv_areanodes[]; // AABB dynamic tree
extern convar_t sv_lan;
extern convar_t sv_lan_rate;
extern convar_t mp_logecho;
extern convar_t mp_logfile;
extern convar_t sv_unlag;

View File

@ -89,24 +89,15 @@ void SV_GetChallenge( netadr_t from )
int SV_GetFragmentSize( sv_client_t *cl )
{
int size = FRAGMENT_SV2CL_MAX_SIZE;
int cl_size;
int cl_frag_size;
if( cl->state == cs_spawned )
{
cl_size = Q_atoi( Info_ValueForKey( cl->userinfo, "cl_dlmax" ));
if( Netchan_IsLocal( &cl->netchan ))
return FRAGMENT_LOCAL_SIZE;
if( cl_size != 0 )
{
size = bound( FRAGMENT_SV2CL_MIN_SIZE, cl_size, FRAGMENT_SV2CL_MAX_SIZE );
}
else
{
size = FRAGMENT_SV2CL_MIN_SIZE;
}
}
cl_frag_size = Q_atoi( Info_ValueForKey( cl->userinfo, "cl_dlmax" ));
cl_frag_size = bound( FRAGMENT_MIN_SIZE, cl_frag_size, FRAGMENT_MAX_SIZE );
return size;
return cl_frag_size;
}
/*
@ -689,6 +680,58 @@ const char *SV_GetClientIDString( sv_client_t *cl )
return result;
}
/*
================
SV_TestBandWidth
================
*/
void SV_TestBandWidth( netadr_t from )
{
int version = Q_atoi( Cmd_Argv( 1 ));
int packetsize = Q_atoi( Cmd_Argv( 2 ));
byte send_buf[FRAGMENT_MAX_SIZE];
dword crcValue = 0;
byte *filepos;
int crcpos;
file_t *test;
sizebuf_t send;
// don't waste time of protocol mismatched
if( version != PROTOCOL_VERSION )
{
SV_RejectConnection( from, "unsupported protocol (%i should be %i)\n", version, PROTOCOL_VERSION );
return;
}
test = FS_Open( "gfx.wad", "rb", false );
if( FS_FileLength( test ) < sizeof( send_buf ))
{
// skip the test and just get challenge
SV_GetChallenge( from );
return;
}
// write the packet header
MSG_Init( &send, "BandWidthPacket", send_buf, sizeof( send_buf ));
MSG_WriteLong( &send, -1 ); // -1 sequence means out of band
MSG_WriteString( &send, "testpacket" );
crcpos = MSG_GetNumBytesWritten( &send );
MSG_WriteLong( &send, 0 ); // reserve space for crc
filepos = send.pData + MSG_GetNumBytesWritten( &send );
packetsize = packetsize - MSG_GetNumBytesWritten( &send ); // adjust the packet size
FS_Read( test, filepos, packetsize );
FS_Close( test );
CRC32_ProcessBuffer( &crcValue, filepos, packetsize ); // calc CRC
MSG_SeekToBit( &send, packetsize << 3, SEEK_CUR );
*(uint *)&send.pData[crcpos] = crcValue;
// send the datagram
NET_SendPacket( NS_SERVER, MSG_GetNumBytesWritten( &send ), MSG_GetData( &send ), from );
}
/*
================
SV_Ack
@ -1817,15 +1860,15 @@ static qboolean SV_DownloadFile_f( sv_client_t *cl )
{
if( sv_send_resources.value )
{
// also check the model textures
if( !Q_stricmp( COM_FileExtension( name ), "mdl" ))
{
if( FS_FileExists( Mod_StudioTexName( name ), false ) > 0 )
Netchan_CreateFileFragments( &cl->netchan, Mod_StudioTexName( name ));
}
if( Netchan_CreateFileFragments( &cl->netchan, name ))
{
// also check the model textures
if( !Q_stricmp( COM_FileExtension( name ), "mdl" ))
{
if( FS_FileExists( Mod_StudioTexName( name ), false ) > 0 )
Netchan_CreateFileFragments( &cl->netchan, Mod_StudioTexName( name ));
}
Netchan_FragSend( &cl->netchan );
return true;
}
@ -2064,6 +2107,7 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
if( !Q_strcmp( pcmd, "ping" )) SV_Ping( from );
else if( !Q_strcmp( pcmd, "ack" )) SV_Ack( from );
else if( !Q_strcmp( pcmd, "info" )) SV_Info( from );
else if( !Q_strcmp( pcmd, "bandwidth" )) SV_TestBandWidth( from );
else if( !Q_strcmp( pcmd, "getchallenge" )) SV_GetChallenge( from );
else if( !Q_strcmp( pcmd, "connect" )) SV_ConnectClient( from );
else if( !Q_strcmp( pcmd, "rcon" )) SV_RemoteCommand( from, msg );
@ -2231,7 +2275,7 @@ void SV_ParseResourceList( sv_client_t *cl, sizebuf_t *msg )
SV_ClearResourceList( &cl->resourcesneeded );
SV_ClearResourceList( &cl->resourcesonhand );
for ( i = 0; i < total; i++ )
for( i = 0; i < total; i++ )
{
resource = Z_Malloc( sizeof( resource_t ) );
Q_strncpy( resource->szFileName, MSG_ReadString( msg ), sizeof( resource->szFileName ));

View File

@ -73,7 +73,7 @@ void SV_BroadcastPrintf( sv_client_t *ignore, char *fmt, ... )
}
// echo to console
Con_Printf( string );
Con_DPrintf( string );
}
/*

View File

@ -56,7 +56,7 @@ void SV_CreateCustomizationList( sv_client_t *cl )
}
else
{
MsgDev( D_REPORT, "SV_CreateCustomization list, ignoring dup. resource for player %s\n", cl->name );
Con_Printf( S_WARN "SV_CreateCustomization list, ignoring dup. resource for player %s\n", cl->name );
}
}
}
@ -335,10 +335,10 @@ void SV_AddToResourceList( resource_t *pResource, resource_t *pList )
pList->pPrev = pResource;
}
void SV_SendCustomization( sv_client_t *cl, resource_t *pResource )
void SV_SendCustomization( sv_client_t *cl, int playernum, resource_t *pResource )
{
MSG_BeginServerCmd( &cl->netchan.message, svc_customization );
MSG_WriteByte( &cl->netchan.message, ( cl - svs.clients )); // playernum
MSG_WriteByte( &cl->netchan.message, playernum ); // playernum
MSG_WriteByte( &cl->netchan.message, pResource->type );
MSG_WriteString( &cl->netchan.message, pResource->szFileName );
MSG_WriteShort( &cl->netchan.message, pResource->nIndex );
@ -391,11 +391,11 @@ int SV_EstimateNeededResources( sv_client_t *cl )
if( p->type != t_decal )
continue;
if( HPAK_ResourceForHash( CUSTOM_RES_PATH, p->rgucMD5_hash, NULL ))
if( !HPAK_ResourceForHash( CUSTOM_RES_PATH, p->rgucMD5_hash, NULL ))
{
if( p->nDownloadSize != 0 )
{
p->ucFlags |= RES_WASMISSING;
SetBits( p->ucFlags, RES_WASMISSING );
size += p->nDownloadSize;
}
else
@ -420,7 +420,7 @@ void SV_Customization( sv_client_t *pClient, resource_t *pResource, qboolean bSk
for( i = 0, cl = svs.clients; i < svs.maxclients; i++, cl++ )
{
if( !cl->state != cs_spawned )
if( cl->state != cs_spawned )
continue;
if( FBitSet( cl->flags, FCL_FAKECLIENT ))
@ -429,7 +429,7 @@ void SV_Customization( sv_client_t *pClient, resource_t *pResource, qboolean bSk
if( cl == pClient && bSkipPlayer )
continue;
SV_SendCustomization( cl, pResource );
SV_SendCustomization( cl, nPlayerNumber, pResource );
}
}
@ -442,7 +442,7 @@ void SV_PropagateCustomizations( sv_client_t *pHost )
for( i = 0, cl = svs.clients; i < svs.maxclients; i++, cl++ )
{
if( !cl->state != cs_spawned )
if( cl->state != cs_spawned )
continue;
if( FBitSet( cl->flags, FCL_FAKECLIENT ))
@ -452,7 +452,7 @@ void SV_PropagateCustomizations( sv_client_t *pHost )
{
if( !pCust->bInUse ) continue;
pResource = &pCust->resource;
SV_SendCustomization( pHost, pResource );
SV_SendCustomization( pHost, i, pResource );
}
}
}
@ -517,7 +517,7 @@ void SV_BatchUploadRequest( sv_client_t *cl )
{
if( FBitSet( p->ucFlags, RES_CUSTOM ))
{
Q_snprintf( filename, sizeof( filename ) - 4, "!MD5%s", MD5_Print( p->rgucMD5_hash ));
Q_snprintf( filename, sizeof( filename ), "!MD5%s", MD5_Print( p->rgucMD5_hash ));
if( SV_CheckFile( &cl->netchan.message, filename ))
SV_MoveToOnHandList( cl, p );

View File

@ -649,8 +649,9 @@ SV_SendClientDatagram
*/
void SV_SendClientDatagram( sv_client_t *cl )
{
static byte msg_buf[MAX_INIT_MSG];
sizebuf_t msg;
static int message_peak = 0;
byte msg_buf[MAX_DATAGRAM];
sizebuf_t msg;
// if we running server with fixed fps so no reason
// to send updates too fast: time just not changed
@ -674,7 +675,7 @@ void SV_SendClientDatagram( sv_client_t *cl )
// for this client out to the message
if( MSG_CheckOverflow( &cl->datagram ))
{
MsgDev( D_WARN, "datagram overflowed for %s\n", cl->name );
Con_Printf( S_WARN "%s overflowed for %s\n", MSG_GetName( &cl->datagram ), cl->name );
}
else
{
@ -685,10 +686,16 @@ void SV_SendClientDatagram( sv_client_t *cl )
MSG_Clear( &cl->datagram );
if( MSG_GetNumBytesWritten( &msg ) > message_peak )
{
Msg( "max bytes %d for datagram\n", MSG_GetNumBytesWritten( &msg ));
message_peak = MSG_GetNumBytesWritten( &msg );
}
if( MSG_CheckOverflow( &msg ))
{
// must have room left for the packet header
MsgDev( D_WARN, "msg overflowed for %s\n", cl->name );
Con_Printf( S_ERROR, "%s overflowed for %s\n", MSG_GetName( &msg ), cl->name );
MSG_Clear( &msg );
}
@ -862,7 +869,7 @@ void SV_SendClientMessages( void )
if( FBitSet( cl->flags, FCL_SEND_NET_MESSAGE ))
{
// bandwidth choke active?
if( !Netchan_CanPacket( &cl->netchan ))
if( !Netchan_CanPacket( &cl->netchan, cl->state == cs_spawned ))
{
cl->chokecount++;
continue;
@ -875,7 +882,7 @@ void SV_SendClientMessages( void )
// NOTE: we should send frame even if server is not simulated to prevent overflow
if( cl->state == cs_spawned )
SV_SendClientDatagram( cl );
else Netchan_Transmit( &cl->netchan, 0, NULL ); // just update reliable
else Netchan_TransmitBits( &cl->netchan, 0, NULL ); // just update reliable
}
}

View File

@ -271,7 +271,7 @@ void SV_ProcessFile( sv_client_t *cl, const char *filename )
qboolean bFound;
qboolean bError;
if( filename[0] == '!' )
if( filename[0] != '!' )
{
Con_Printf( "Ignoring non-customization file upload of %s\n", filename );
return;
@ -971,6 +971,7 @@ void SV_Shutdown( const char *finalmsg )
SV_FreeClients();
svs.maxclients = 0;
HPAK_FlushHostQueue();
Log_Printf( "Server shutdown\n" );
Log_Close();

View File

@ -1758,7 +1758,7 @@ static void SV_Physics_Entity( edict_t *ent )
// g-cont. don't alow free entities during loading because
// this produce a corrupted baselines
if( sv.state == ss_active && ent->v.flags & FL_KILLME )
if( sv.state == ss_active && FBitSet( ent->v.flags, FL_KILLME ))
SV_FreeEdict( ent );
}

View File

@ -461,8 +461,6 @@ void ReapplyDecal( SAVERESTOREDATA *pSaveData, decallist_t *entry, qboolean adja
// these entities might not exist over transitions,
// so we'll use the saved plane and do a traceline instead
flags |= FDECAL_DONTSAVE;
MsgDev( D_ERROR, "couldn't restore entity index %i, do trace for decal\n", entityIndex );
VectorCopy( entry->position, testspot );
@ -2254,7 +2252,8 @@ void SV_SaveGame( const char *pName )
SV_BuildSaveComment( comment, sizeof( comment ));
SV_SaveGameSlot( savename, comment );
CL_HudMessage( "GAMESAVED" ); // defined in titles.txt
if( !FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
CL_HudMessage( "GAMESAVED" ); // defined in titles.txt
}
/*