12 Mar 2018
This commit is contained in:
parent
e96b555d6b
commit
556275f912
|
@ -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" };
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -850,6 +850,7 @@ void Host_FreeCommon( void )
|
|||
Image_Shutdown();
|
||||
Sound_Shutdown();
|
||||
Netchan_Shutdown();
|
||||
HPAK_FlushHostQueue();
|
||||
FS_Shutdown();
|
||||
|
||||
Mem_FreePool( &host.mempool );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++ )
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ));
|
||||
|
|
|
@ -73,7 +73,7 @@ void SV_BroadcastPrintf( sv_client_t *ignore, char *fmt, ... )
|
|||
}
|
||||
|
||||
// echo to console
|
||||
Con_Printf( string );
|
||||
Con_DPrintf( string );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Reference in New Issue