2022-03-08 05:31:34 +00:00
# include "q3common.h"
2006-02-11 14:51:36 +00:00
# include "shader.h"
2005-08-26 22:50:31 +00:00
2008-11-09 22:29:28 +00:00
2022-03-08 05:31:34 +00:00
# include "glquake.h"
# include "shader.h"
# include "cl_master.h"
# ifndef STATIC_Q3
void Cvar_ForceCheatVars ( qboolean semicheats , qboolean absolutecheats ) { } //locks/unlocks cheat cvars depending on weather we are allowed them.
//int Cvar_ApplyLatches(int latchflag){return 0;}
unsigned int utf8_decode ( int * error , const void * in , char const * * out ) { return 0 ; }
void Con_PrintFlags ( const char * txt , unsigned int setflags , unsigned int clearflags ) { }
void Con_ClearNotify ( void ) { }
unsigned int key_dest_mask ;
float in_sensitivityscale ;
void Sys_Clipboard_PasteText ( clipboardtype_t clipboardtype , void ( * callback ) ( void * cb , const char * utf8 ) , void * ctx ) { } ; //calls the callback once the text is available (maybe instantly). utf8 arg may be NULL if the clipboard was unavailable.
void SCR_SetLoadingStage ( int stage ) { }
void SCR_BeginLoadingPlaque ( void ) { }
void SCR_EndLoadingPlaque ( void ) { }
void Shader_DefaultCinematic ( struct shaderparsestate_s * ps , const char * shortname , const void * args ) { }
shader_t * R_RegisterCustom ( model_t * mod , const char * name , unsigned int usageflags , shader_gen_t * defaultgen , const void * args ) { return NULL ; }
cin_t * R_ShaderGetCinematic ( shader_t * s ) { return NULL ; }
void Media_SetState ( cin_t * cin , cinstates_t newstate ) { }
void R_UnloadShader ( shader_t * shader ) { }
cinstates_t Media_GetState ( cin_t * cin ) { return 0 ; }
void Media_Send_Reset ( cin_t * cin ) { }
char * CL_TryingToConnect ( void ) { return NULL ; }
downloadlist_t * CL_DownloadFailed ( const char * name , qdownload_t * qdl , enum dlfailreason_e failreason ) { return NULL ; }
qboolean DL_Begun ( qdownload_t * dl ) { return 0 ; }
void CL_DownloadFinished ( qdownload_t * dl ) { }
int Sys_EnumerateFiles ( const char * gpath , const char * match , int ( QDECL * func ) ( const char * fname , qofs_t fsize , time_t modtime , void * parm , searchpathfuncs_t * spath ) , void * parm , searchpathfuncs_t * spath ) { return 0 ; }
# endif
2005-08-26 22:50:31 +00:00
//urm, yeah, this is more than just parse.
# ifdef Q3CLIENT
# include "clq3defs.h"
2022-03-08 05:31:34 +00:00
# define SHOWSTRING(s) if(cl_shownet_ptr->value==2)Con_Printf ("%s\n", s);
# define SHOWNET(x) if(cl_shownet_ptr->value==2)Con_Printf ("%3i:%s\n", msg->currentbit-8, x);
# define SHOWNET2(x, y) if(cl_shownet_ptr->value==2)Con_Printf ("%3i:%3i:%s\n", msg->currentbit-8, y, x);
2005-08-26 22:50:31 +00:00
void MSG_WriteBits ( sizebuf_t * msg , int value , int bits ) ;
2022-03-08 05:31:34 +00:00
static qboolean CLQ3_Netchan_Process ( sizebuf_t * msg ) ;
2005-08-26 22:50:31 +00:00
ClientConnectionState_t ccs ;
qboolean CG_FillQ3Snapshot ( int snapnum , snapshot_t * snapshot )
{
int i ;
clientSnap_t * snap ;
if ( snapnum > ccs . serverMessageNum )
{
2022-03-08 05:31:34 +00:00
plugfuncs - > EndGame ( " CG_FillQ3Snapshot: snapshotNumber > cl.snap.serverMessageNum " ) ;
2005-08-26 22:50:31 +00:00
}
if ( ccs . serverMessageNum - snapnum > = Q3UPDATE_BACKUP )
{
return false ; // too old
}
snap = & ccs . snapshots [ snapnum & Q3UPDATE_MASK ] ;
if ( ! snap - > valid | | snap - > serverMessageNum ! = snapnum )
{
return false ; // invalid
}
memcpy ( & snapshot - > ps , & snap - > playerstate , sizeof ( snapshot - > ps ) ) ;
snapshot - > numEntities = snap - > numEntities ;
for ( i = 0 ; i < snapshot - > numEntities ; i + + )
{
2019-02-24 08:32:45 +00:00
memcpy ( & snapshot - > entities [ i ] , & ccs . parseEntities [ ( snap - > firstEntity + i ) & Q3PARSE_ENTITIES_MASK ] , sizeof ( snapshot - > entities [ 0 ] ) ) ;
2005-08-26 22:50:31 +00:00
}
memcpy ( & snapshot - > areamask , snap - > areabits , sizeof ( snapshot - > areamask ) ) ;
snapshot - > snapFlags = snap - > snapFlags ;
snapshot - > ping = snap - > ping ;
snapshot - > serverTime = snap - > serverTime ;
snapshot - > numServerCommands = snap - > serverCommandNum ;
snapshot - > serverCommandSequence = ccs . lastServerCommandNum ;
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
CLQ3_ParseServerCommand
= = = = = = = = = = = = = = = = = = = = =
*/
void CLQ3_ParseServerCommand ( void )
{
int number ;
char * string ;
2022-03-08 05:31:34 +00:00
number = msgfuncs - > ReadLong ( ) ;
// SHOWNET(va("%i", number));
2005-08-26 22:50:31 +00:00
2022-03-08 05:31:34 +00:00
string = msgfuncs - > ReadString ( ) ;
2005-08-26 22:50:31 +00:00
SHOWSTRING ( string ) ;
if ( number < = ccs . lastServerCommandNum )
{
return ; // we have already received this command
}
ccs . lastServerCommandNum + + ;
2019-07-02 04:12:20 +00:00
if ( number > ccs . lastServerCommandNum + Q3TEXTCMD_MASK - 1 )
2005-08-26 22:50:31 +00:00
{
2007-02-23 00:21:33 +00:00
Con_Printf ( " Warning: Lost %i reliable serverCommands \n " ,
2005-08-26 22:50:31 +00:00
number - ccs . lastServerCommandNum ) ;
}
// archive the command to be processed by cgame later
2019-07-02 04:12:20 +00:00
Q_strncpyz ( ccs . serverCommands [ number & Q3TEXTCMD_MASK ] , string , sizeof ( ccs . serverCommands [ 0 ] ) ) ;
2005-08-26 22:50:31 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
CL_DeltaEntity
Parses deltas from the given base and adds the resulting entity
to the current frame
= = = = = = = = = = = = = = = = = =
*/
static void CLQ3_DeltaEntity ( clientSnap_t * frame , int newnum , q3entityState_t * old , qboolean unchanged )
{
q3entityState_t * state ;
2019-02-24 08:32:45 +00:00
state = & ccs . parseEntities [ ccs . firstParseEntity & Q3PARSE_ENTITIES_MASK ] ;
2005-08-26 22:50:31 +00:00
if ( unchanged )
{
memcpy ( state , old , sizeof ( * state ) ) ; // don't read any bits
}
else
{
if ( ! MSG_Q3_ReadDeltaEntity ( old , state , newnum ) ) // the entity present in oldframe is not in the current frame
return ;
}
ccs . firstParseEntity + + ;
frame - > numEntities + + ;
}
/*
= = = = = = = = = = = = = = = = = =
CL_ParsePacketEntities
An svc_packetentities has just been parsed , deal with the
rest of the data stream .
= = = = = = = = = = = = = = = = = =
*/
static void CLQ3_ParsePacketEntities ( clientSnap_t * oldframe , clientSnap_t * newframe )
{
int numentities ;
int oldnum ;
int newnum ;
q3entityState_t * oldstate ;
oldstate = NULL ;
newframe - > firstEntity = ccs . firstParseEntity ;
newframe - > numEntities = 0 ;
// delta from the entities present in oldframe
numentities = 0 ;
if ( ! oldframe )
{
oldnum = 99999 ;
}
else if ( oldframe - > numEntities < = 0 )
{
oldnum = 99999 ;
}
else
{
2019-02-24 08:32:45 +00:00
oldstate = & ccs . parseEntities [ oldframe - > firstEntity & Q3PARSE_ENTITIES_MASK ] ;
2005-08-26 22:50:31 +00:00
oldnum = oldstate - > number ;
}
while ( 1 )
{
2022-03-08 05:31:34 +00:00
newnum = msgfuncs - > ReadBits ( GENTITYNUM_BITS ) ;
if ( newnum < 0 )
plugfuncs - > EndGame ( " CLQ3_ParsePacketEntities: end of message " ) ;
else if ( newnum > = MAX_GENTITIES )
plugfuncs - > EndGame ( " CLQ3_ParsePacketEntities: bad number %i " , newnum ) ;
2005-08-26 22:50:31 +00:00
// end of packetentities
if ( newnum = = ENTITYNUM_NONE )
{
break ;
}
while ( oldnum < newnum )
{
// one or more entities from the old packet are unchanged
SHOWSTRING ( va ( " unchanged: %i " , oldnum ) ) ;
CLQ3_DeltaEntity ( newframe , oldnum , oldstate , true ) ;
numentities + + ;
if ( numentities > = oldframe - > numEntities )
{
oldnum = 99999 ;
}
else
{
2019-02-24 08:32:45 +00:00
oldstate = & ccs . parseEntities [ ( oldframe - > firstEntity + numentities ) & Q3PARSE_ENTITIES_MASK ] ;
2005-08-26 22:50:31 +00:00
oldnum = oldstate - > number ;
2011-05-15 13:23:13 +00:00
}
}
2005-08-26 22:50:31 +00:00
if ( oldnum = = newnum )
{
// delta from previous state
SHOWSTRING ( va ( " delta: %i " , newnum ) ) ;
CLQ3_DeltaEntity ( newframe , newnum , oldstate , false ) ;
numentities + + ;
if ( numentities > = oldframe - > numEntities )
{
oldnum = 99999 ;
}
else
{
2019-02-24 08:32:45 +00:00
oldstate = & ccs . parseEntities [ ( oldframe - > firstEntity + numentities ) & Q3PARSE_ENTITIES_MASK ] ;
2005-08-26 22:50:31 +00:00
oldnum = oldstate - > number ;
}
continue ;
}
if ( oldnum > newnum )
{
// delta from baseline
SHOWSTRING ( va ( " baseline: %i " , newnum ) ) ;
CLQ3_DeltaEntity ( newframe , newnum , & ccs . baselines [ newnum ] , false ) ;
}
}
// any remaining entities in the old frame are copied over
while ( oldnum ! = 99999 )
{
// one or more entities from the old packet are unchanged
SHOWSTRING ( va ( " unchanged: %i " , oldnum ) ) ;
CLQ3_DeltaEntity ( newframe , oldnum , oldstate , true ) ;
numentities + + ;
if ( numentities > = oldframe - > numEntities )
{
oldnum = 99999 ;
}
else
{
2019-02-24 08:32:45 +00:00
oldstate = & ccs . parseEntities [ ( oldframe - > firstEntity + numentities ) & Q3PARSE_ENTITIES_MASK ] ;
2005-08-26 22:50:31 +00:00
oldnum = oldstate - > number ;
}
}
}
void CLQ3_ParseSnapshot ( void )
{
clientSnap_t snap , * oldsnap ;
int delta ;
int len ;
2022-03-08 05:31:34 +00:00
// int i;
// outframe_t *frame;
2005-08-26 22:50:31 +00:00
// usercmd_t *ucmd;
// int commandTime;
memset ( & snap , 0 , sizeof ( snap ) ) ;
snap . serverMessageNum = ccs . serverMessageNum ;
snap . serverCommandNum = ccs . lastServerCommandNum ;
2022-03-08 05:31:34 +00:00
snap . serverTime = msgfuncs - > ReadLong ( ) ;
2014-06-12 23:08:42 +00:00
//so we can delta to it properly.
2022-03-08 05:31:34 +00:00
clientfuncs - > UpdateGameTime ( snap . serverTime / 1000.0f ) ;
2005-08-26 22:50:31 +00:00
// If the frame is delta compressed from data that we
// no longer have available, we must suck up the rest of
2011-05-15 13:23:13 +00:00
// the frame, but not use it, then ask for a non-compressed message
2022-03-08 05:31:34 +00:00
delta = msgfuncs - > ReadByte ( ) ;
2005-08-26 22:50:31 +00:00
if ( delta )
{
snap . deltaFrame = ccs . serverMessageNum - delta ;
oldsnap = & ccs . snapshots [ snap . deltaFrame & Q3UPDATE_MASK ] ;
if ( ! oldsnap - > valid )
{
// should never happen
Con_Printf ( " Delta from invalid frame (not supposed to happen!). \n " ) ;
}
else if ( oldsnap - > serverMessageNum ! = snap . deltaFrame )
{
// The frame that the server did the delta from
// is too old, so we can't reconstruct it properly.
2019-02-24 08:32:45 +00:00
Con_DPrintf ( " Delta frame too old. \n " ) ;
2005-08-26 22:50:31 +00:00
}
else if ( ccs . firstParseEntity - oldsnap - > firstEntity >
2019-02-24 08:32:45 +00:00
Q3MAX_PARSE_ENTITIES - MAX_ENTITIES_IN_SNAPSHOT )
2005-08-26 22:50:31 +00:00
{
2019-02-24 08:32:45 +00:00
Con_DPrintf ( " Delta parse_entities too old. \n " ) ;
2005-08-26 22:50:31 +00:00
}
else
{
snap . valid = true ; // valid delta parse
}
}
else
{
oldsnap = NULL ;
snap . deltaFrame = - 1 ;
snap . valid = true ; // uncompressed frame
}
// read snapFlags
2022-03-08 05:31:34 +00:00
snap . snapFlags = msgfuncs - > ReadByte ( ) ;
2005-08-26 22:50:31 +00:00
// read areabits
2022-03-08 05:31:34 +00:00
len = msgfuncs - > ReadByte ( ) ;
msgfuncs - > ReadData ( snap . areabits , len ) ;
2005-08-26 22:50:31 +00:00
// read playerinfo
SHOWSTRING ( " playerstate " ) ;
MSG_Q3_ReadDeltaPlayerstate ( oldsnap ? & oldsnap - > playerstate : NULL , & snap . playerstate ) ;
// read packet entities
SHOWSTRING ( " packet entities " ) ;
CLQ3_ParsePacketEntities ( oldsnap , & snap ) ;
if ( ! snap . valid )
{
return ;
}
// cl.adjustTimeDelta = true;
// Find last usercmd server has processed and calculate snap.ping
snap . ping = 3 ;
2022-03-08 05:31:34 +00:00
/* for (i=ccs.netchan.outgoing_sequence-1 ; i>ccs.netchan.outgoing_sequence-Q3CMD_BACKUP ; i--)
2005-08-26 22:50:31 +00:00
{
2019-07-02 04:12:20 +00:00
frame = & cl . outframes [ i & Q3CMD_MASK ] ;
2005-08-26 22:50:31 +00:00
if ( frame - > server_message_num = = snap . deltaFrame )
{
2022-03-08 05:31:34 +00:00
snap . ping = plugfuncs - > GetMilliseconds ( ) - frame - > client_time ;
2005-08-26 22:50:31 +00:00
break ;
}
2022-03-08 05:31:34 +00:00
} */
2005-08-26 22:50:31 +00:00
memcpy ( & ccs . snap , & snap , sizeof ( snap ) ) ;
memcpy ( & ccs . snapshots [ ccs . serverMessageNum & Q3UPDATE_MASK ] , & snap , sizeof ( snap ) ) ;
SHOWSTRING ( va ( " snapshot:%i delta:%i ping:%i " , snap . serverMessageNum , snap . deltaFrame , snap . ping ) ) ;
}
2014-06-12 23:08:42 +00:00
# define MAXCHUNKSIZE 65536
2005-08-26 22:50:31 +00:00
void CLQ3_ParseDownload ( void )
{
2022-03-08 05:31:34 +00:00
qdownload_t * dl = ccs . download ;
2005-08-26 22:50:31 +00:00
unsigned int chunknum ;
unsigned int chunksize ;
unsigned char chunkdata [ MAXCHUNKSIZE ] ;
int i ;
char * s ;
2022-03-08 05:31:34 +00:00
chunknum = ( unsigned short ) msgfuncs - > ReadShort ( ) ;
2014-06-12 23:08:42 +00:00
chunknum | = ccs . downloadchunknum & ~ 0xffff ; //add the chunk number, truncated by the network protocol.
2005-08-26 22:50:31 +00:00
if ( ! chunknum )
{
2022-03-08 05:31:34 +00:00
dl - > size = ( unsigned int ) msgfuncs - > ReadLong ( ) ;
cvarfuncs - > SetFloat ( cvarfuncs - > GetNVFDG ( " cl_downloadSize " , " 0 " , 0 , NULL , " Q3 Compat " ) - > name , dl - > size ) ; //so the gamecode knows download progress.
2005-08-26 22:50:31 +00:00
}
2014-06-12 23:08:42 +00:00
if ( dl - > size = = ( unsigned int ) - 1 )
2019-07-29 05:28:20 +00:00
{ //the only downloads we should be getting is pk3s.
//if they're advertised-but-failing then its probably due to permissions rather than file-not-found
2022-03-08 05:31:34 +00:00
s = msgfuncs - > ReadString ( ) ;
2019-07-29 05:28:20 +00:00
CL_DownloadFailed ( dl - > remotename , dl , DLFAIL_SERVERCVAR ) ;
2022-03-08 05:31:34 +00:00
plugfuncs - > EndGame ( " %s " , s ) ;
2005-08-26 22:50:31 +00:00
return ;
}
2022-03-08 05:31:34 +00:00
chunksize = ( unsigned short ) msgfuncs - > ReadShort ( ) ;
2005-08-26 22:50:31 +00:00
if ( chunksize > MAXCHUNKSIZE )
2022-03-08 05:31:34 +00:00
plugfuncs - > EndGame ( " Server sent a download chunk of size %i (it's too damn big!) \n " , chunksize ) ;
2005-08-26 22:50:31 +00:00
for ( i = 0 ; i < chunksize ; i + + )
2022-03-08 05:31:34 +00:00
chunkdata [ i ] = msgfuncs - > ReadByte ( ) ;
2005-08-26 22:50:31 +00:00
if ( ccs . downloadchunknum ! = chunknum ) //the q3 client is rather lame.
{ //ccs.downloadchunknum holds the chunk number.
2005-10-16 12:52:06 +00:00
Con_DPrintf ( " PACKETLOSS WHEN DOWNLOADING!!!! \n " ) ;
2005-08-26 22:50:31 +00:00
return ; //let the server try again some time
}
ccs . downloadchunknum + + ;
2014-06-12 23:08:42 +00:00
if ( ! dl | | dl - > method ! = DL_Q3 )
2005-08-26 22:50:31 +00:00
{
2014-06-12 23:08:42 +00:00
Con_Printf ( " Server sending download, but no download was requested \n " ) ;
CLQ3_SendClientCommand ( " stopdl " ) ;
return ;
}
2005-08-26 22:50:31 +00:00
2014-06-12 23:08:42 +00:00
if ( ! dl - > file )
{
if ( ! DL_Begun ( dl ) )
2005-08-26 22:50:31 +00:00
{
2019-07-29 05:28:20 +00:00
CL_DownloadFailed ( dl - > remotename , dl , DLFAIL_CLIENTFILE ) ;
2005-08-26 22:50:31 +00:00
return ;
}
}
2014-06-12 23:08:42 +00:00
Con_DPrintf ( " dl: chnk %u, size %u, csize %u \n " , ( unsigned int ) chunknum , ( unsigned int ) dl - > size , ( unsigned int ) chunksize ) ;
2005-08-26 22:50:31 +00:00
if ( ! chunksize )
{
2014-06-12 23:08:42 +00:00
CL_DownloadFinished ( dl ) ;
2005-08-26 22:50:31 +00:00
2022-03-08 05:31:34 +00:00
ccs . servercount = - 1 ; //make sure the server resends us that vital gamestate.
2005-08-26 22:50:31 +00:00
ccs . downloadchunknum = - 1 ;
2014-06-12 23:08:42 +00:00
return ;
2005-08-26 22:50:31 +00:00
}
else
{
2014-06-12 23:08:42 +00:00
VFS_WRITE ( dl - > file , chunkdata , chunksize ) ;
dl - > ratebytes + = chunksize ;
chunksize = VFS_TELL ( dl - > file ) ;
2006-01-02 23:01:54 +00:00
// Con_Printf("Recieved %i\n", chunksize);
2005-08-26 22:50:31 +00:00
2014-06-12 23:08:42 +00:00
dl - > percent = ( 100.0 * chunksize ) / dl - > size ;
2005-08-26 22:50:31 +00:00
}
2014-06-12 23:08:42 +00:00
CLQ3_SendClientCommand ( " nextdl %u " , chunknum ) ;
}
static qboolean CLQ3_SendDownloads ( char * rc , char * rn )
{
while ( rn )
{
qdownload_t * dl ;
char localname [ MAX_QPATH ] ;
char tempname [ MAX_QPATH ] ;
2022-03-08 05:31:34 +00:00
char filename [ MAX_QPATH ] ;
2014-06-12 23:08:42 +00:00
char crc [ 64 ] ;
vfsfile_t * f ;
2022-03-08 05:31:34 +00:00
rc = cmdfuncs - > ParseToken ( rc , crc , sizeof ( crc ) , NULL ) ;
rn = cmdfuncs - > ParseToken ( rn , filename , sizeof ( filename ) , NULL ) ;
if ( ! * filename )
2014-06-12 23:08:42 +00:00
break ;
2022-03-08 05:31:34 +00:00
if ( ! strchr ( filename , ' / ' ) ) //don't let some muppet tell us to download quake3.exe
2014-06-12 23:08:42 +00:00
break ;
//as much as I'd like to use COM_FCheckExists, this stuf is relative to root, not the gamedir.
2022-03-08 05:31:34 +00:00
f = fsfuncs - > OpenVFS ( va ( " %s.pk3 " , filename ) , " rb " , FS_ROOT ) ;
2014-06-12 23:08:42 +00:00
if ( f )
{
VFS_CLOSE ( f ) ;
continue ;
}
2022-03-08 05:31:34 +00:00
if ( ! fsfuncs - > GenCachedPakName ( va ( " %s.pk3 " , filename ) , crc , localname , sizeof ( localname ) ) )
2014-06-12 23:08:42 +00:00
continue ;
2022-03-08 05:31:34 +00:00
f = fsfuncs - > OpenVFS ( localname , " rb " , FS_ROOT ) ;
2014-06-12 23:08:42 +00:00
if ( f )
{
VFS_CLOSE ( f ) ;
continue ;
}
2022-03-08 05:31:34 +00:00
if ( ! fsfuncs - > GenCachedPakName ( va ( " %s.tmp " , filename ) , crc , tempname , sizeof ( tempname ) ) )
2014-06-12 23:08:42 +00:00
continue ;
2022-03-08 05:31:34 +00:00
if ( ! cvarfuncs - > GetFloat ( " cl_downloads " ) )
2019-02-24 08:32:45 +00:00
{
2022-03-08 05:31:34 +00:00
Con_Printf ( CON_WARNING " Need to download %s.pk3, but downloads are disabled \n " , filename ) ;
2019-02-24 08:32:45 +00:00
continue ;
}
2014-06-12 23:08:42 +00:00
//fixme: request to download it
2022-03-08 05:31:34 +00:00
Con_Printf ( " Sending request to download %s.pk3 \n " , filename ) ;
CLQ3_SendClientCommand ( " download %s.pk3 " , filename ) ;
2014-06-12 23:08:42 +00:00
ccs . downloadchunknum = 0 ;
dl = Z_Malloc ( sizeof ( * dl ) ) ;
//q3's downloads are relative to root, but they do at least force a pk3 extension.
Q_snprintfz ( dl - > localname , sizeof ( dl - > localname ) , " package/%s " , localname ) ;
Q_snprintfz ( dl - > tempname , sizeof ( dl - > tempname ) , " package/%s " , tempname ) ;
dl - > prefixbytes = 8 ;
dl - > fsroot = FS_ROOT ;
2022-03-08 05:31:34 +00:00
Q_snprintfz ( dl - > remotename , sizeof ( dl - > remotename ) , " %s.pk3 " , filename ) ;
2014-06-12 23:08:42 +00:00
dl - > method = DL_Q3 ;
dl - > percent = 0 ;
2022-03-08 05:31:34 +00:00
ccs . download = dl ;
2014-06-12 23:08:42 +00:00
return true ;
}
return false ;
2005-08-26 22:50:31 +00:00
}
2022-03-08 05:31:34 +00:00
qboolean CLQ3_SystemInfoChanged ( const char * str )
2005-08-26 22:50:31 +00:00
{
qboolean usingpure , usingcheats ;
char * value ;
char * pc , * pn ;
char * rc , * rn ;
2022-03-08 05:31:34 +00:00
Con_Printf ( " Server's sv_pure: \" %s \" \n " , worldfuncs - > GetInfoKey ( str , " sv_pure " ) ) ;
usingpure = atoi ( worldfuncs - > GetInfoKey ( str , " sv_pure " ) ) ;
usingcheats = atoi ( worldfuncs - > GetInfoKey ( str , " sv_cheats " ) ) ;
2005-08-26 22:50:31 +00:00
Cvar_ForceCheatVars ( usingpure | | usingcheats , usingcheats ) ;
2022-03-08 05:31:34 +00:00
// if (atoi(value))
// Host_EndGame("Unable to connect to Q3 Pure Servers\n");
value = worldfuncs - > GetInfoKey ( str , " fs_game " ) ;
2005-08-26 22:50:31 +00:00
2022-03-08 05:31:34 +00:00
if ( ! * value )
2005-08-26 22:50:31 +00:00
{
2022-03-08 05:31:34 +00:00
value = " baseq3 " ;
2005-08-26 22:50:31 +00:00
}
2022-03-08 05:31:34 +00:00
rc = worldfuncs - > GetInfoKey ( str , " sv_referencedPaks " ) ; //the ones that we should download.
rn = worldfuncs - > GetInfoKey ( str , " sv_referencedPakNames " ) ;
2014-06-12 23:08:42 +00:00
if ( CLQ3_SendDownloads ( rc , rn ) )
return false ;
2005-08-26 22:50:31 +00:00
2022-03-08 05:31:34 +00:00
pc = worldfuncs - > GetInfoKey ( str , " sv_paks " ) ; //the ones that we are allowed to use (in order!)
pn = worldfuncs - > GetInfoKey ( str , " sv_pakNames " ) ;
fsfuncs - > PureMode ( value , usingpure ? 2 : 0 , pn , pc , rn , rc , ccs . fs_key ) ;
2005-08-26 22:50:31 +00:00
return true ; //yay, we're in
}
2022-03-08 05:31:34 +00:00
void CLQ3_ParseGameState ( sizebuf_t * msg )
2005-08-26 22:50:31 +00:00
{
int c ;
int index ;
char * configString ;
//
// wipe the client_state_t struct
//
2022-03-08 05:31:34 +00:00
clientfuncs - > ClearClientState ( ) ;
CG_ClearGameState ( ) ;
2014-03-30 08:55:06 +00:00
ccs . firstParseEntity = 0 ;
memset ( ccs . parseEntities , 0 , sizeof ( ccs . parseEntities ) ) ;
memset ( ccs . baselines , 0 , sizeof ( ccs . baselines ) ) ;
2022-03-08 05:31:34 +00:00
ccs . lastServerCommandNum = msgfuncs - > ReadLong ( ) ;
2005-08-26 22:50:31 +00:00
for ( ; ; )
{
2022-03-08 05:31:34 +00:00
c = msgfuncs - > ReadByte ( ) ;
2005-08-26 22:50:31 +00:00
2022-03-08 05:31:34 +00:00
if ( c < 0 )
2005-08-26 22:50:31 +00:00
{
2022-03-08 05:31:34 +00:00
plugfuncs - > EndGame ( " CLQ3_ParseGameState: read past end of server message " ) ;
break ;
2005-08-26 22:50:31 +00:00
}
if ( c = = svcq3_eom )
{
break ;
}
SHOWNET ( va ( " %i " , c ) ) ;
switch ( c )
{
default :
2022-03-08 05:31:34 +00:00
plugfuncs - > EndGame ( " CLQ3_ParseGameState: bad command byte %i " , c ) ;
2005-08-26 22:50:31 +00:00
break ;
case svcq3_configstring :
2022-03-08 05:31:34 +00:00
index = msgfuncs - > ReadBits ( 16 ) ;
2005-08-26 22:50:31 +00:00
if ( index < 0 | | index > = MAX_Q3_CONFIGSTRINGS )
{
2022-03-08 05:31:34 +00:00
plugfuncs - > EndGame ( " CLQ3_ParseGameState: configString index %i out of range " , index ) ;
2005-08-26 22:50:31 +00:00
}
2022-03-08 05:31:34 +00:00
configString = msgfuncs - > ReadString ( ) ;
2005-08-26 22:50:31 +00:00
CG_InsertIntoGameState ( index , configString ) ;
break ;
case svcq3_baseline :
2022-03-08 05:31:34 +00:00
index = msgfuncs - > ReadBits ( GENTITYNUM_BITS ) ;
2005-08-26 22:50:31 +00:00
if ( index < 0 | | index > = MAX_GENTITIES )
{
2022-03-08 05:31:34 +00:00
plugfuncs - > EndGame ( " CLQ3_ParseGameState: baseline index %i out of range " , index ) ;
2005-08-26 22:50:31 +00:00
}
MSG_Q3_ReadDeltaEntity ( NULL , & ccs . baselines [ index ] , index ) ;
break ;
}
}
2022-03-08 05:31:34 +00:00
ccs . playernum = msgfuncs - > ReadLong ( ) ;
ccs . fs_key = msgfuncs - > ReadLong ( ) ;
2005-08-26 22:50:31 +00:00
2008-11-09 22:29:28 +00:00
if ( ! CLQ3_SystemInfoChanged ( CG_GetConfigString ( CFGSTR_SYSINFO ) ) )
2014-06-12 23:08:42 +00:00
{
UI_Restart_f ( ) ;
2005-08-26 22:50:31 +00:00
return ;
2014-06-12 23:08:42 +00:00
}
2005-08-26 22:50:31 +00:00
2022-03-08 05:31:52 +00:00
scenefuncs - > NewMap ( NULL ) ;
2022-03-08 05:31:34 +00:00
CG_Restart ( ) ;
2005-08-26 22:50:31 +00:00
UI_Restart_f ( ) ;
2022-03-08 05:31:34 +00:00
if ( ! ccs . worldmodel )
plugfuncs - > EndGame ( " CGame didn't set a map. \n " ) ;
2006-06-04 16:02:03 +00:00
2005-08-26 22:50:31 +00:00
SCR_EndLoadingPlaque ( ) ;
2022-03-08 05:31:34 +00:00
ccs . state = ca_active ;
2005-08-26 22:50:31 +00:00
{
char buffer [ 2048 ] ;
2022-03-08 05:31:34 +00:00
strcpy ( buffer , va ( " cp %i " , ccs . servercount ) ) ;
fsfuncs - > GenerateClientPacksList ( buffer , sizeof ( buffer ) , ccs . fs_key ) ;
2011-05-15 13:23:13 +00:00
CLQ3_SendClientCommand ( " %s " , buffer ) ; // warning: format not a string literal and no format arguments
2005-08-26 22:50:31 +00:00
}
// load cgame, etc
// CL_ChangeLevel();
2022-03-08 05:31:34 +00:00
cvarfuncs - > ForceSetString ( " cl_paused " , " 0 " ) ;
2005-08-26 22:50:31 +00:00
}
2022-03-08 05:31:34 +00:00
int CLQ3_ParseServerMessage ( sizebuf_t * msg )
2005-08-26 22:50:31 +00:00
{
int cmd ;
2022-03-08 05:31:34 +00:00
if ( ! CLQ3_Netchan_Process ( msg ) )
return ccs . state ; //was a fragment.
2005-08-26 22:50:31 +00:00
2022-03-08 05:31:34 +00:00
if ( cl_shownet_ptr - > value = = 1 )
Con_Printf ( " %i " , msg - > cursize ) ;
else if ( cl_shownet_ptr - > value = = 2 )
2013-11-29 14:36:47 +00:00
Con_Printf ( " ------------------ \n " ) ;
2005-08-26 22:50:31 +00:00
2022-03-08 05:31:34 +00:00
msgfuncs - > BeginReading ( msg , msg_nullnetprim ) ;
ccs . serverMessageNum = msgfuncs - > ReadLong ( ) ;
msg - > packing = SZ_HUFFMAN ; //the rest is huffman compressed.
2005-08-26 22:50:31 +00:00
// read last client command number server received
2022-03-08 05:31:34 +00:00
ccs . lastClientCommandNum = msgfuncs - > ReadLong ( ) ;
2019-07-02 04:12:20 +00:00
if ( ccs . lastClientCommandNum < = ccs . numClientCommands - Q3TEXTCMD_BACKUP )
2005-08-26 22:50:31 +00:00
{
2019-07-02 04:12:20 +00:00
ccs . lastClientCommandNum = ccs . numClientCommands - Q3TEXTCMD_BACKUP + 1 ;
2005-08-26 22:50:31 +00:00
}
else if ( ccs . lastClientCommandNum > ccs . numClientCommands )
{
ccs . lastClientCommandNum = ccs . numClientCommands ;
}
//
// parse the message
//
for ( ; ; )
{
2022-03-08 05:31:34 +00:00
cmd = msgfuncs - > ReadByte ( ) ;
2005-08-26 22:50:31 +00:00
2022-03-08 05:31:34 +00:00
if ( cmd < 0 ) //hm, we have an eom, so only stop when the message is bad.
2005-08-26 22:50:31 +00:00
{
2022-03-08 05:31:34 +00:00
plugfuncs - > EndGame ( " CLQ3_ParseServerMessage: read past end of server message " ) ;
2005-08-26 22:50:31 +00:00
break ;
}
if ( cmd = = svcq3_eom )
{
SHOWNET2 ( " END OF MESSAGE " , 2 ) ;
break ;
}
SHOWNET ( va ( " %i " , cmd ) ) ;
2011-05-15 13:23:13 +00:00
2005-08-26 22:50:31 +00:00
// other commands
switch ( cmd )
{
default :
2022-03-08 05:31:34 +00:00
plugfuncs - > EndGame ( " CLQ3_ParseServerMessage: Illegible server message " ) ;
2005-08-26 22:50:31 +00:00
break ;
case svcq3_nop :
break ;
case svcq3_gamestate :
2022-03-08 05:31:34 +00:00
CLQ3_ParseGameState ( msg ) ;
2005-08-26 22:50:31 +00:00
break ;
case svcq3_serverCommand :
CLQ3_ParseServerCommand ( ) ;
break ;
case svcq3_download :
CLQ3_ParseDownload ( ) ;
break ;
case svcq3_snapshot :
CLQ3_ParseSnapshot ( ) ;
break ;
}
}
2022-03-08 05:31:34 +00:00
return ccs . state ;
2005-08-26 22:50:31 +00:00
}
2022-03-08 05:31:34 +00:00
static qboolean CLQ3_Netchan_Process ( sizebuf_t * msg )
2005-08-26 22:50:31 +00:00
{
2022-03-08 05:31:34 +00:00
if ( Netchan_ProcessQ3 ( & ccs . netchan , msg ) )
2005-08-26 22:50:31 +00:00
{
2020-03-07 09:00:40 +00:00
# ifndef Q3_NOENCRYPT
2022-03-08 05:31:34 +00:00
int sequence ;
int lastClientCommandNum ;
qbyte bitmask ;
qbyte c ;
int i , j ;
char * string ;
int readcount ;
msgfuncs - > BeginReading ( msg , msg_nullnetprim ) ;
sequence = msgfuncs - > ReadLong ( ) ;
msg - > packing = SZ_HUFFMAN ;
readcount = msg - > currentbit > > 3 ;
lastClientCommandNum = msgfuncs - > ReadLong ( ) ;
// calculate bitmask
bitmask = ( sequence ^ ccs . challenge ) & 0xff ;
string = ccs . clientCommands [ lastClientCommandNum & Q3TEXTCMD_MASK ] ;
// decrypt the packet
for ( i = readcount + 4 , j = 0 ; i < msg - > cursize ; i + + , j + + )
2005-08-26 22:50:31 +00:00
{
2022-03-08 05:31:34 +00:00
if ( ! string [ j ] )
j = 0 ; // another way around
c = string [ j ] ;
if ( c > 127 | | c = = ' % ' )
c = ' . ' ;
bitmask ^ = c < < ( ( i - readcount ) & 1 ) ;
msg - > data [ i ] ^ = bitmask ;
2005-08-26 22:50:31 +00:00
}
2022-03-08 05:31:34 +00:00
msg - > packing = SZ_RAWBITS ; //first bit was plain...
2007-02-23 00:21:33 +00:00
# endif
2022-03-08 05:31:34 +00:00
return true ; //all good
}
return false ; //its bad dude, bad.
2005-08-26 22:50:31 +00:00
}
2022-03-08 05:31:34 +00:00
void CL_Netchan_Transmit ( struct ftenet_connections_s * socket , int length , const qbyte * data )
2005-08-26 22:50:31 +00:00
{
2020-03-07 09:00:40 +00:00
# ifndef Q3_NOENCRYPT
2022-03-08 05:31:34 +00:00
sizebuf_t msg ;
char msgdata [ MAX_OVERALLMSGLEN ] ;
2005-08-26 22:50:31 +00:00
int serverid ;
int lastSequence ;
int lastServerCommandNum ;
qbyte bitmask ;
qbyte c ;
int i , j ;
char * string ;
2022-03-08 05:31:34 +00:00
msgfuncs - > BeginWriting ( & msg , msg_nullnetprim , msgdata , sizeof ( msgdata ) ) ;
msgfuncs - > WriteData ( & msg , data , length ) ;
if ( msg . overflowed )
2005-08-26 22:50:31 +00:00
{
2022-03-08 05:31:34 +00:00
plugfuncs - > EndGame ( " Client message overflowed " ) ;
2005-08-26 22:50:31 +00:00
}
2022-03-08 05:31:34 +00:00
msgfuncs - > BeginReading ( & msg , msg_nullnetprim ) ;
2005-08-26 22:50:31 +00:00
msg . packing = SZ_HUFFMAN ;
2022-03-08 05:31:34 +00:00
serverid = msgfuncs - > ReadLong ( ) ;
lastSequence = msgfuncs - > ReadLong ( ) ;
lastServerCommandNum = msgfuncs - > ReadLong ( ) ;
2005-08-26 22:50:31 +00:00
// calculate bitmask
2022-03-08 05:31:34 +00:00
bitmask = ( lastSequence ^ serverid ^ ccs . challenge ) & 0xff ;
2019-07-02 04:12:20 +00:00
string = ccs . serverCommands [ lastServerCommandNum & Q3TEXTCMD_MASK ] ;
2005-08-26 22:50:31 +00:00
// encrypt the packet
2022-03-08 05:31:34 +00:00
for ( i = 12 , j = 0 ; i < msg . cursize ; i + + , j + + )
2005-08-26 22:50:31 +00:00
{
2022-03-08 05:31:34 +00:00
if ( ! string [ j ] )
2005-08-26 22:50:31 +00:00
{
j = 0 ; // another way around
}
c = string [ j ] ;
2022-03-08 05:31:34 +00:00
if ( c > 127 | | c = = ' % ' )
2005-08-26 22:50:31 +00:00
{
c = ' . ' ;
}
bitmask ^ = c < < ( i & 1 ) ;
msg . data [ i ] ^ = bitmask ;
}
2022-03-08 05:31:34 +00:00
data = msg . data ;
length = msg . cursize ;
2007-02-23 00:21:33 +00:00
# endif
2022-03-08 05:31:34 +00:00
Netchan_TransmitQ3 ( socket , & ccs . netchan , length , data ) ;
2005-08-26 22:50:31 +00:00
}
static void MSG_WriteDeltaKey ( sizebuf_t * msg , int key , int from , int to , int bits )
{
if ( from = = to )
{
2022-03-08 05:31:34 +00:00
msgfuncs - > WriteBits ( msg , 0 , 1 ) ;
2005-08-26 22:50:31 +00:00
return ; // unchanged
}
2011-05-15 13:23:13 +00:00
2022-03-08 05:31:34 +00:00
msgfuncs - > WriteBits ( msg , 1 , 1 ) ;
msgfuncs - > WriteBits ( msg , to ^ key , bits ) ;
2005-08-26 22:50:31 +00:00
}
void MSG_Q3_WriteDeltaUsercmd ( sizebuf_t * msg , int key , const usercmd_t * from , const usercmd_t * to )
{
// figure out how to pack serverTime
if ( to - > servertime - from - > servertime < 255 )
{
2022-03-08 05:31:34 +00:00
msgfuncs - > WriteBits ( msg , 1 , 1 ) ;
msgfuncs - > WriteBits ( msg , to - > servertime - from - > servertime , 8 ) ;
2005-08-26 22:50:31 +00:00
}
else
{
2022-03-08 05:31:34 +00:00
msgfuncs - > WriteBits ( msg , 0 , 1 ) ;
msgfuncs - > WriteBits ( msg , to - > servertime , 32 ) ;
2005-08-26 22:50:31 +00:00
}
if ( ! memcmp ( ( qbyte * ) from + 4 , ( qbyte * ) to + 4 , sizeof ( usercmd_t ) - 4 ) )
{
2022-03-08 05:31:34 +00:00
msgfuncs - > WriteBits ( msg , 0 , 1 ) ;
2005-08-26 22:50:31 +00:00
return ; // nothing changed
}
key ^ = to - > servertime ;
2022-03-08 05:31:34 +00:00
msgfuncs - > WriteBits ( msg , 1 , 1 ) ;
2005-08-26 22:50:31 +00:00
MSG_WriteDeltaKey ( msg , key , from - > angles [ 0 ] , to - > angles [ 0 ] , 16 ) ;
MSG_WriteDeltaKey ( msg , key , from - > angles [ 1 ] , to - > angles [ 1 ] , 16 ) ;
MSG_WriteDeltaKey ( msg , key , from - > angles [ 2 ] , to - > angles [ 2 ] , 16 ) ;
MSG_WriteDeltaKey ( msg , key , from - > forwardmove , to - > forwardmove , 8 ) ;
2022-03-08 05:31:34 +00:00
MSG_WriteDeltaKey ( msg , key , from - > sidemove , to - > sidemove , 8 ) ;
2005-08-26 22:50:31 +00:00
MSG_WriteDeltaKey ( msg , key , from - > upmove , to - > upmove , 8 ) ;
MSG_WriteDeltaKey ( msg , key , from - > buttons , to - > buttons , 16 ) ;
MSG_WriteDeltaKey ( msg , key , from - > weapon , to - > weapon , 8 ) ;
}
void VARGS CLQ3_SendClientCommand ( const char * fmt , . . . )
{
va_list argptr ;
char command [ MAX_STRING_CHARS ] ;
va_start ( argptr , fmt ) ;
2011-07-22 15:11:35 +00:00
vsnprintf ( command , sizeof ( command ) , fmt , argptr ) ;
2005-08-26 22:50:31 +00:00
va_end ( argptr ) ;
// create new clientCommand
ccs . numClientCommands + + ;
// check if server will lose some of our clientCommands
2019-07-02 04:12:20 +00:00
if ( ccs . numClientCommands - ccs . lastClientCommandNum > = Q3TEXTCMD_BACKUP )
2022-03-08 05:31:34 +00:00
plugfuncs - > EndGame ( " Client command overflow " ) ;
2005-08-26 22:50:31 +00:00
2019-07-02 04:12:20 +00:00
Q_strncpyz ( ccs . clientCommands [ ccs . numClientCommands & Q3TEXTCMD_MASK ] , command , sizeof ( ccs . clientCommands [ 0 ] ) ) ;
2005-08-26 22:50:31 +00:00
Con_DPrintf ( " Sending %s \n " , command ) ;
}
2022-03-08 05:31:34 +00:00
void CLQ3_SendCmd ( struct ftenet_connections_s * socket , usercmd_t * cmd , unsigned int movesequence , double gametime )
2005-08-26 22:50:31 +00:00
{
char * string ;
int i ;
char data [ MAX_OVERALLMSGLEN ] ;
sizebuf_t msg ;
2022-03-08 05:31:34 +00:00
// outframe_t *frame;
unsigned int oldsequence ;
2005-08-26 22:50:31 +00:00
int cmdcount , key ;
2022-03-08 05:31:34 +00:00
const usercmd_t * to , * from ;
static usercmd_t nullcmd ;
2005-08-26 22:50:31 +00:00
//reuse the q1 array
2022-03-08 05:31:34 +00:00
cmd - > servertime = gametime * 1000 ;
2005-08-26 22:50:31 +00:00
cmd - > weapon = ccs . selected_weapon ;
2022-03-08 05:31:34 +00:00
2005-08-26 22:50:31 +00:00
cmd - > forwardmove * = 127 / 400.0f ;
cmd - > sidemove * = 127 / 400.0f ;
cmd - > upmove * = 127 / 400.0f ;
2014-02-11 17:51:29 +00:00
if ( cmd - > forwardmove > 127 )
cmd - > forwardmove = 127 ;
if ( cmd - > forwardmove < - 127 )
cmd - > forwardmove = - 127 ;
if ( cmd - > sidemove > 127 )
cmd - > sidemove = 127 ;
if ( cmd - > sidemove < - 127 )
cmd - > sidemove = - 127 ;
if ( cmd - > upmove > 127 )
cmd - > upmove = 127 ;
if ( cmd - > upmove < - 127 )
cmd - > upmove = - 127 ;
2005-08-26 22:50:31 +00:00
2005-09-08 22:52:46 +00:00
if ( cmd - > buttons & 2 ) //jump
{
cmd - > upmove = 100 ;
cmd - > buttons & = ~ 2 ;
}
2019-09-04 07:59:40 +00:00
if ( Key_Dest_Has ( ~ kdm_game ) )
2005-09-08 22:52:46 +00:00
cmd - > buttons | = 2 ; //add in the 'at console' button
2019-02-24 08:32:45 +00:00
//FIXME: q3 generates a new command every video frame, but a new packet at a more limited rate.
//FIXME: we should return here if its not yet time for a network frame.
2005-08-26 22:50:31 +00:00
2022-03-08 05:31:34 +00:00
/* frame = &cl.outframes[ccs.netchan.outgoing_sequence & Q3CMD_MASK];
frame - > cmd_sequence = movesequence ;
2005-08-26 22:50:31 +00:00
frame - > server_message_num = ccs . serverMessageNum ;
2022-03-08 05:31:34 +00:00
frame - > server_time = gametime ;
frame - > client_time = plugfuncs - > GetMilliseconds ( ) ;
*/
2005-08-26 22:50:31 +00:00
memset ( & msg , 0 , sizeof ( msg ) ) ;
msg . maxsize = sizeof ( data ) ;
msg . data = data ;
msg . packing = SZ_HUFFMAN ;
2022-03-08 05:31:34 +00:00
msgfuncs - > WriteBits ( & msg , ccs . servercount , 32 ) ;
msgfuncs - > WriteBits ( & msg , ccs . serverMessageNum , 32 ) ;
msgfuncs - > WriteBits ( & msg , ccs . lastServerCommandNum , 32 ) ;
2005-08-26 22:50:31 +00:00
// write clientCommands not acknowledged by server yet
for ( i = ccs . lastClientCommandNum + 1 ; i < = ccs . numClientCommands ; i + + )
{
2022-03-08 05:31:34 +00:00
msgfuncs - > WriteBits ( & msg , clcq3_clientCommand , 8 ) ;
msgfuncs - > WriteBits ( & msg , i , 32 ) ;
2019-07-02 04:12:20 +00:00
string = ccs . clientCommands [ i & Q3TEXTCMD_MASK ] ;
2005-08-26 22:50:31 +00:00
while ( * string )
2022-03-08 05:31:34 +00:00
msgfuncs - > WriteBits ( & msg , * string + + , 8 ) ;
msgfuncs - > WriteBits ( & msg , 0 , 8 ) ;
2005-08-26 22:50:31 +00:00
}
2022-03-08 05:31:34 +00:00
i = ccs . netchan . outgoing_sequence ;
i - = bound ( 0 , cl_c2sdupe_ptr - > ival , 5 ) ; //extra age, if desired
2019-02-24 08:32:45 +00:00
i - - ;
2022-03-08 05:31:34 +00:00
if ( i < ccs . netchan . outgoing_sequence - Q3CMD_MASK )
i = ccs . netchan . outgoing_sequence - Q3CMD_MASK ;
oldsequence = movesequence - 1 ; //cl.outframes[i & Q3CMD_MASK].cmd_sequence;
cmdcount = movesequence - oldsequence ;
2019-07-02 04:12:20 +00:00
if ( cmdcount > Q3CMD_MASK )
cmdcount = Q3CMD_MASK ;
2019-02-24 08:32:45 +00:00
2005-08-26 22:50:31 +00:00
// begin a client move command, if any
2019-02-24 08:32:45 +00:00
if ( cmdcount )
2005-08-26 22:50:31 +00:00
{
2022-03-08 05:31:34 +00:00
if ( cl_nodelta_ptr - > value | | ! ccs . snap . valid | | ccs . snap . serverMessageNum ! = ccs . serverMessageNum )
msgfuncs - > WriteBits ( & msg , clcq3_nodeltaMove , 8 ) ; // no compression
2005-08-26 22:50:31 +00:00
else
2022-03-08 05:31:34 +00:00
msgfuncs - > WriteBits ( & msg , clcq3_move , 8 ) ;
2005-08-26 22:50:31 +00:00
// write cmdcount
2022-03-08 05:31:34 +00:00
msgfuncs - > WriteBits ( & msg , cmdcount , 8 ) ;
2005-08-26 22:50:31 +00:00
// calculate key
2019-07-02 04:12:20 +00:00
string = ccs . serverCommands [ ccs . lastServerCommandNum & Q3TEXTCMD_MASK ] ;
2005-08-26 22:50:31 +00:00
key = ccs . fs_key ^ ccs . serverMessageNum ^ StringKey ( string , 32 ) ;
2019-02-24 08:32:45 +00:00
//note that q3 uses timestamps so sequences are not important
//we can also send dupes without issue.
2005-08-26 22:50:31 +00:00
from = & nullcmd ;
2022-03-08 05:31:34 +00:00
for ( i = movesequence - cmdcount ; i < movesequence ; i + + )
2005-08-26 22:50:31 +00:00
{
2022-03-08 05:31:34 +00:00
to = inputfuncs - > GetMoveEntry ( i ) ;
if ( ! to )
to = from ;
2005-08-26 22:50:31 +00:00
MSG_Q3_WriteDeltaUsercmd ( & msg , key , from , to ) ;
from = to ;
}
}
2022-03-08 05:31:34 +00:00
msgfuncs - > WriteBits ( & msg , clcq3_eom , 8 ) ;
2005-08-26 22:50:31 +00:00
2022-03-08 05:31:34 +00:00
CL_Netchan_Transmit ( socket , msg . cursize , msg . data ) ;
while ( ccs . netchan . reliable_length )
Netchan_TransmitNextFragment ( socket , & ccs . netchan ) ;
2005-08-26 22:50:31 +00:00
}
2022-03-08 05:31:34 +00:00
void CLQ3_SendAuthPacket ( struct ftenet_connections_s * socket , netadr_t * gameserver )
2005-08-26 22:50:31 +00:00
{
2019-08-03 01:58:03 +00:00
# ifdef HAVE_PACKET
2005-08-26 22:50:31 +00:00
char data [ 2048 ] ;
sizebuf_t msg ;
//send the auth packet
//this should be the right code, but it doesn't work.
2013-05-03 04:28:08 +00:00
if ( gameserver - > type = = NA_IP )
2005-08-26 22:50:31 +00:00
{
2022-03-08 05:31:34 +00:00
char * key = cvarfuncs - > GetNVFDG ( " cl_cdkey " , " " , CVAR_ARCHIVE , " Quake3 auth " , " Q3 Compat " ) - > string ;
2005-08-26 22:50:31 +00:00
netadr_t authaddr ;
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
# define Q3_AUTHORIZE_SERVER_NAME "authorize.quake3arena.com:27952"
2005-08-26 22:50:31 +00:00
if ( * key )
{
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
Con_Printf ( " Resolving %s \n " , Q3_AUTHORIZE_SERVER_NAME ) ;
2022-03-08 05:31:34 +00:00
if ( masterfuncs - > StringToAdr ( Q3_AUTHORIZE_SERVER_NAME , 0 , & authaddr , 1 , NULL ) )
2005-08-26 22:50:31 +00:00
{
2022-03-08 05:31:34 +00:00
msgfuncs - > BeginWriting ( & msg , msg_nullnetprim , data , sizeof ( data ) ) ;
msgfuncs - > WriteLong ( & msg , - 1 ) ;
msgfuncs - > WriteString ( & msg , " getKeyAuthorize 0 " ) ;
2005-08-26 22:50:31 +00:00
msg . cursize - - ;
while ( * key )
{
if ( ( * key > = ' a ' & & * key < = ' z ' ) | | ( * key > = ' A ' & & * key < = ' Z ' ) | | ( * key > = ' 0 ' & & * key < = ' 9 ' ) )
2022-03-08 05:31:34 +00:00
msgfuncs - > WriteByte ( & msg , * key ) ;
2005-08-26 22:50:31 +00:00
key + + ;
}
2022-03-08 05:31:34 +00:00
msgfuncs - > WriteByte ( & msg , 0 ) ;
2005-08-26 22:50:31 +00:00
2022-03-08 05:31:34 +00:00
msgfuncs - > SendPacket ( socket , msg . cursize , msg . data , & authaddr ) ;
2005-08-26 22:50:31 +00:00
}
else
Con_Printf ( " failed \n " ) ;
}
}
2019-08-03 01:58:03 +00:00
# endif
2005-08-26 22:50:31 +00:00
}
2022-03-08 05:31:34 +00:00
void CLQ3_SendConnectPacket ( struct ftenet_connections_s * socket , netadr_t * to , int challenge , int qport , infobuf_t * userinfo )
2005-08-26 22:50:31 +00:00
{
2018-07-05 16:21:44 +00:00
char infostr [ 1024 ] ;
2005-08-26 22:50:31 +00:00
char data [ 2048 ] ;
sizebuf_t msg ;
2022-03-08 05:31:34 +00:00
static const char * priorityq3 [ ] = { " * " , " name " , NULL } ;
2018-07-05 16:21:44 +00:00
static const char * nonq3 [ ] = { " challenge " , " qport " , " protocol " , " ip " , " chat " , NULL } ;
2022-03-08 05:31:34 +00:00
int protocol = cvarfuncs - > GetFloat ( " com_protocolversion " ) ;
2005-08-26 22:50:31 +00:00
memset ( & ccs , 0 , sizeof ( ccs ) ) ;
2022-03-08 05:31:34 +00:00
ccs . servercount = - 1 ;
ccs . challenge = challenge ;
Netchan_SetupQ3 ( NS_CLIENT , & ccs . netchan , to , qport ) ;
2005-08-26 22:50:31 +00:00
2022-03-08 05:31:34 +00:00
worldfuncs - > IBufToInfo ( userinfo , infostr , sizeof ( infostr ) , priorityq3 , nonq3 , NULL , NULL , /*&cls.userinfosync,*/ userinfo ) ;
2018-07-05 16:21:44 +00:00
2022-03-08 05:31:34 +00:00
msgfuncs - > BeginWriting ( & msg , msg_nullnetprim , data , sizeof ( data ) ) ;
msgfuncs - > WriteLong ( & msg , - 1 ) ;
msgfuncs - > WriteString ( & msg , va ( " connect \" \\ challenge \\ %i \\ qport \\ %i \\ protocol \\ %i%s \" " , challenge , qport , protocol , infostr ) ) ;
2014-05-10 13:42:13 +00:00
# ifdef HUFFNETWORK
2022-03-08 05:31:34 +00:00
if ( msgfuncs - > Huff_EncryptPacket )
msgfuncs - > Huff_EncryptPacket ( & msg , 12 ) ;
if ( ! msgfuncs - > Huff_CompressionCRC | | ! msgfuncs - > Huff_CompressionCRC ( HUFFCRC_QUAKE3 ) )
2014-05-10 13:42:13 +00:00
{
Con_Printf ( " Huffman compression error \n " ) ;
return ;
}
# endif
2022-03-08 05:31:34 +00:00
msgfuncs - > SendPacket ( socket , msg . cursize , msg . data , to ) ;
}
void CLQ3_Established ( void )
{
ccs . state = ca_connected ;
}
void CLQ3_Disconnect ( struct ftenet_connections_s * socket )
{
ccs . state = ca_disconnected ;
2005-08-26 22:50:31 +00:00
}
2006-02-17 19:54:47 +00:00
# endif