05 Dec 2015

This commit is contained in:
g-cont 2015-12-05 00:00:00 +03:00 committed by Alibek Omarov
parent fa6c196a72
commit dc90b26c99
23 changed files with 299 additions and 155 deletions

View File

@ -2265,11 +2265,64 @@ physent_t *pfnGetPhysent( int idx )
=============
pfnSetUpPlayerPrediction
FIXME: finalize
=============
*/
void pfnSetUpPlayerPrediction( int dopred, int bIncludeLocalClient )
{
// TODO: implement
entity_state_t *playerstate = cl.frames[cl.parsecountmod].playerstate;
predicted_player_t *player = cls.predicted_players;
cl_entity_t *clent;
int j, v12;
for( j = 0; j < MAX_CLIENTS; j++, player++, playerstate++ )
{
player->active = false;
if( playerstate->messagenum != cl.parsecount )
continue; // not present this frame
if( !playerstate->modelindex )
continue;
// special for EF_NODRAW and local client?
if(( playerstate->effects & EF_NODRAW ) && !bIncludeLocalClient )
{
// don't include local player?
if( cl.playernum != j )
{
player->active = true;
player->movetype = playerstate->movetype;
player->solid = playerstate->solid;
player->usehull = playerstate->usehull;
clent = CL_EDICT_NUM( j + 1 );
// CL_ComputePlayerOrigin( v9 );
VectorCopy( clent->origin, player->origin );
VectorCopy( clent->angles, player->angles );
}
else continue;
}
else
{
if( cl.playernum == j )
continue;
player->active = true;
player->movetype = playerstate->movetype;
player->solid = playerstate->solid;
player->usehull = playerstate->usehull;
v12 = 17080 * cl.parsecountmod + 340 * j;
player->origin[0] = cl.frames[0].playerstate[0].origin[0] + v12;
player->origin[1] = cl.frames[0].playerstate[0].origin[1] + v12;
player->origin[2] = cl.frames[0].playerstate[0].origin[2] + v12;
player->angles[0] = cl.frames[0].playerstate[0].angles[0] + v12;
player->angles[1] = cl.frames[0].playerstate[0].angles[1] + v12;
player->angles[2] = cl.frames[0].playerstate[0].angles[2] + v12;
}
}
}
/*

View File

@ -284,6 +284,7 @@ void CL_CreateCmd( void )
// build list of all solid entities per next frame (exclude clients)
CL_SetSolidEntities ();
CL_SetSolidPlayers ( cl.playernum );
VectorCopy( cl.refdef.cl_viewangles, angles );
VectorCopy( cl.frame.local.client.origin, cl.data.origin );
@ -673,14 +674,16 @@ CL_Connect_f
*/
void CL_Connect_f( void )
{
char *server;
string server;
if( Cmd_Argc() != 2 )
{
Msg( "Usage: connect <server>\n" );
return;
}
Q_strncpy( server, Cmd_Argv( 1 ), sizeof( cls.servername ));
if( Host_ServerState())
{
// if running a local server, kill it and reissue
@ -688,9 +691,8 @@ void CL_Connect_f( void )
SV_Shutdown( false );
}
server = Cmd_Argv( 1 );
NET_Config( true ); // allow remote
Msg( "server %s\n", server );
CL_Disconnect();
@ -907,9 +909,7 @@ CL_InternetServers_f
void CL_InternetServers_f( void )
{
netadr_t adr;
char part1query[12];
char part2query[128];
string fullquery;
char fullquery[512] = "\x31\xFF" "0.0.0.0:0\0" "\\gamedir\\";
MsgDev( D_INFO, "Scanning for servers on the internet area...\n" );
NET_Config( true ); // allow remote
@ -917,13 +917,9 @@ void CL_InternetServers_f( void )
if( !NET_StringToAdr( MASTERSERVER_ADR, &adr ) )
MsgDev( D_INFO, "Can't resolve adr: %s\n", MASTERSERVER_ADR );
Q_snprintf( part1query, sizeof( part1query ), "%c%c0.0.0.0:0", 0x31, 0xFF );
Q_snprintf( part2query, sizeof( part2query ), "\\gamedir\\%s_xash\\nap\\%d", GI->gamedir, 70 );
Q_strcpy( &fullquery[21], GI->gamedir );
Q_memcpy( fullquery, part1query, sizeof( part1query ));
Q_memcpy( fullquery + sizeof( part1query ), part2query, Q_strlen( part2query ));
NET_SendPacket( NS_CLIENT, sizeof( part1query ) + Q_strlen( part2query ) + 1, fullquery, adr );
NET_SendPacket( NS_CLIENT, Q_strlen( GI->gamedir ) + 22, fullquery, adr );
}
/*
@ -1331,8 +1327,7 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
else if( !Q_strcmp( c, "print" ))
{
// print command from somewhere
args = BF_ReadString( msg );
Msg( args );
Msg( "remote: %s\n", BF_ReadString( msg ));
}
else if( !Q_strcmp( c, "ping" ))
{
@ -1357,11 +1352,6 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
// dropped the connection but it is still getting packets from us
CL_Disconnect();
}
else if( clgame.dllFuncs.pfnConnectionlessPacket( &from, args, buf, &len ))
{
// user out of band message (must be handled in CL_ConnectionlessPacket)
if( len > 0 ) Netchan_OutOfBand( NS_SERVER, from, len, buf );
}
else if( msg->pData[0] == 0xFF && msg->pData[1] == 0xFF && msg->pData[2] == 0xFF && msg->pData[3] == 0xFF && msg->pData[4] == 0x66 && msg->pData[5] == 0x0A )
{
dataoffset = 6;
@ -1369,11 +1359,7 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
while( 1 )
{
servadr.type = NA_IP;
servadr.ip[0] = msg->pData[dataoffset + 0];
servadr.ip[1] = msg->pData[dataoffset + 1];
servadr.ip[2] = msg->pData[dataoffset + 2];
servadr.ip[3] = msg->pData[dataoffset + 3];
Q_memcpy( servadr.ip, &msg->pData[dataoffset], sizeof(servadr.ip));
servadr.port = *(word *)&msg->pData[dataoffset + 4];
if( !servadr.port )
@ -1388,6 +1374,11 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
dataoffset += 6;
}
}
else if( clgame.dllFuncs.pfnConnectionlessPacket( &from, args, buf, &len ))
{
// user out of band message (must be handled in CL_ConnectionlessPacket)
if( len > 0 ) Netchan_OutOfBand( NS_SERVER, from, len, buf );
}
else MsgDev( D_ERROR, "bad connectionless packet from %s:\n%s\n", NET_AdrToString( from ), args );
}
@ -1516,16 +1507,21 @@ A file has been received via the fragmentation/reassembly layer, put it in the r
see if we have finished downloading files.
====================
*/
void CL_ProcessFile( BOOL successfully_received, const char *filename )
void CL_ProcessFile( qboolean successfully_received, const char *filename )
{
MsgDev( D_INFO, "Received %s, but file processing is not hooked up!!!\n", filename );
if( successfully_received )
MsgDev( D_INFO, "received %s\n", filename );
else MsgDev( D_WARN, "failed to download %s", filename );
if( cls.downloadfileid == cls.downloadcount - 1 )
{
MsgDev( D_INFO, "All Files downloaded\n" );
MsgDev( D_INFO, "Download completed, resuming connection\n" );
FS_Rescan();
BF_WriteByte( &cls.netchan.message, clc_stringcmd );
BF_WriteString( &cls.netchan.message, "continueloading" );
cls.downloadfileid = 0;
cls.downloadcount = 0;
return;
}
cls.downloadfileid++;
@ -1607,7 +1603,7 @@ void CL_InitLocal( void )
cls.state = ca_disconnected;
// register our variables
cl_predict = Cvar_Get( "cl_predict", "0", CVAR_ARCHIVE, "disables client movement prediction" );
cl_predict = Cvar_Get( "cl_predict", "0", CVAR_ARCHIVE, "enable client movement prediction" );
cl_crosshair = Cvar_Get( "crosshair", "1", CVAR_ARCHIVE, "show weapon chrosshair" );
cl_nodelta = Cvar_Get ("cl_nodelta", "0", 0, "disable delta-compression for usercommnds" );
cl_idealpitchscale = Cvar_Get( "cl_idealpitchscale", "0.8", 0, "how much to look up/down slopes and stairs when not using freelook" );
@ -1621,7 +1617,7 @@ void CL_InitLocal( void )
// userinfo
Cvar_Get( "password", "", CVAR_USERINFO, "player password" );
name = Cvar_Get( "name", Sys_GetCurrentUser(), CVAR_USERINFO|CVAR_ARCHIVE|CVAR_PRINTABLEONLY, "player name" );
model = Cvar_Get( "model", "player", CVAR_USERINFO|CVAR_ARCHIVE, "player model ('player' it's a single player model)" );
model = Cvar_Get( "model", "player", CVAR_USERINFO|CVAR_ARCHIVE, "player model ('player' is a singleplayer model)" );
topcolor = Cvar_Get( "topcolor", "0", CVAR_USERINFO|CVAR_ARCHIVE, "player top color" );
bottomcolor = Cvar_Get( "bottomcolor", "0", CVAR_USERINFO|CVAR_ARCHIVE, "player bottom color" );
rate = Cvar_Get( "rate", "25000", CVAR_USERINFO|CVAR_ARCHIVE, "player network rate" );
@ -1668,11 +1664,11 @@ void CL_InitLocal( void )
Cmd_AddCommand ("physinfo", CL_Physinfo_f, "print current client physinfo" );
Cmd_AddCommand ("disconnect", CL_Disconnect_f, "disconnect from server" );
Cmd_AddCommand ("record", CL_Record_f, "record a demo" );
Cmd_AddCommand ("playdemo", CL_PlayDemo_f, "playing a demo" );
Cmd_AddCommand ("playdemo", CL_PlayDemo_f, "play a demo" );
Cmd_AddCommand ("killdemo", CL_DeleteDemo_f, "delete a specified demo file and demoshot" );
Cmd_AddCommand ("startdemos", CL_StartDemos_f, "start playing back the selected demos sequentially" );
Cmd_AddCommand ("demos", CL_Demos_f, "restart looping demos defined by the last startdemos command" );
Cmd_AddCommand ("movie", CL_PlayVideo_f, "playing a movie" );
Cmd_AddCommand ("movie", CL_PlayVideo_f, "play a movie" );
Cmd_AddCommand ("stop", CL_Stop_f, "stop playing or recording a demo" );
Cmd_AddCommand ("info", NULL, "collect info about local servers with specified protocol" );
Cmd_AddCommand ("escape", CL_Escape_f, "escape from game to menu" );

View File

@ -152,12 +152,11 @@ void CL_AddLinksToPmove( void )
if( !check || check == &clgame.entities[0] )
continue;
if( clgame.pmove->numvisent < MAX_PHYSENTS )
{
pe = &clgame.pmove->visents[clgame.pmove->numvisent];
if( CL_CopyEntityToPhysEnt( pe, check ))
clgame.pmove->numvisent++;
}
if( check->curstate.solid == SOLID_TRIGGER )
continue;
if( ( check->curstate.owner > 0) && cl.playernum == check->curstate.owner -1 )
continue;
// players will be added later
if( check->player ) continue;
@ -167,6 +166,16 @@ void CL_AddLinksToPmove( void )
continue;
solid = check->curstate.solid;
if( solid == SOLID_NOT && ( check->curstate.skin == CONTENTS_NONE || check->curstate.modelindex == 0 ))
continue;
if( clgame.pmove->numvisent < MAX_PHYSENTS )
{
pe = &clgame.pmove->visents[clgame.pmove->numvisent];
if( CL_CopyEntityToPhysEnt( pe, check ))
clgame.pmove->numvisent++;
}
if( solid == SOLID_BSP || solid == SOLID_BBOX || solid == SOLID_SLIDEBOX || solid == SOLID_CUSTOM )
{
@ -711,24 +720,20 @@ CL_RunUsercmd
Runs prediction code for user cmd
=================
*/
void CL_RunUsercmd(local_state_t * from, local_state_t * to, usercmd_t * u, qboolean runfuncs, double * pfElapsed, unsigned int random_seed)
void CL_RunUsercmd( local_state_t *from, local_state_t *to, usercmd_t *u, qboolean runfuncs, double *pfElapsed, unsigned int random_seed )
{
usercmd_t cmd;
entity_state_t * fs;
entity_state_t * ts;
clientdata_t * fcd;
clientdata_t * tcd;
playermove_t *pmove = clgame.pmove;
usercmd_t cmd;
entity_state_t *fs, *ts;
clientdata_t *fcd, *tcd;
playermove_t *pmove = clgame.pmove;
local_state_t temp;
usercmd_t split;
while (u->msec > 50)
while( u->msec > 50 )
{
local_state_t temp;
usercmd_t split;
split = *u;
split.msec /= 2.0;
CL_RunUsercmd(from, &temp, &split, runfuncs, pfElapsed, random_seed);
split.msec /= 2;
CL_RunUsercmd( from, &temp, &split, runfuncs, pfElapsed, random_seed );
from = &temp;
u = &split;
}
@ -841,12 +846,12 @@ Sets cl.predicted_origin and cl.predicted_angles
*/
void CL_PredictMovement( void )
{
double time;
double time;
int frame = 1;
int ack, outgoing_command;
int current_command;
int current_command_mod;
local_state_t *from, *to;
local_state_t *from = NULL, *to = NULL;
if( cls.state != ca_active ) return;
@ -883,6 +888,9 @@ void CL_PredictMovement( void )
time = cl.frame.time;
CL_SetSolidEntities();
CL_SetSolidPlayers( cl.playernum );
while( 1 )
{
// we've run too far forward
@ -903,14 +911,17 @@ void CL_PredictMovement( void )
cl.runfuncs[current_command_mod],
&time, cls.netchan.incoming_acknowledged + frame );
cl.runfuncs[current_command_mod] = FALSE;
cl.runfuncs[current_command_mod] = false;
from = to;
frame++;
}
VectorCopy( to->playerstate.origin, cl.predicted_origin );
VectorCopy( to->client.velocity, cl.predicted_velocity );
VectorCopy( to->client.view_ofs, cl.predicted_viewofs );
VectorCopy( to->client.punchangle, cl.predicted_punchangle );
if( to )
{
VectorCopy( to->playerstate.origin, cl.predicted_origin );
VectorCopy( to->client.velocity, cl.predicted_velocity );
VectorCopy( to->client.view_ofs, cl.predicted_viewofs );
VectorCopy( to->client.punchangle, cl.predicted_punchangle );
}
}

View File

@ -241,6 +241,17 @@ typedef struct
byte gammaTable[256];
} client_draw_t;
typedef struct cl_predicted_player_s
{
int flags;
int movetype;
int solid;
int usehull;
qboolean active;
vec3_t origin; // predicted origin
vec3_t angles;
} predicted_player_t;
typedef struct
{
int gl_texturenum; // this is a real texnum
@ -431,6 +442,8 @@ typedef struct
int next_client_entities; // next client_entity to use
entity_state_t *packet_entities; // [num_client_entities]
predicted_player_t predicted_players[MAX_CLIENTS];
scrshot_t scrshot_request; // request for screen shot
scrshot_t scrshot_action; // in-action
const float *envshot_vieworg; // envshot position

View File

@ -1228,6 +1228,8 @@ static void GL_UploadTexture( rgbdata_t *pic, gltexture_t *tex, qboolean subImag
int texsize = 0, img_flags = 0, samples;
GLint dataType = GL_UNSIGNED_BYTE;
ASSERT( pic != NULL && tex != NULL );
if( pic->flags & IMAGE_DDS_FORMAT )
{
// special case for DDS textures
@ -1235,8 +1237,6 @@ static void GL_UploadTexture( rgbdata_t *pic, gltexture_t *tex, qboolean subImag
return;
}
ASSERT( pic != NULL && tex != NULL );
tex->srcWidth = tex->width = pic->width;
tex->srcHeight = tex->height = pic->height;
s = tex->srcWidth * tex->srcHeight;

View File

@ -1652,7 +1652,7 @@ void S_Say_f( void )
{
if( Cmd_Argc() == 1 )
{
Msg( "Usage: speak <soundfile\n" );
Msg( "Usage: speak <soundfile>\n" );
return;
}
@ -1829,10 +1829,15 @@ void S_Shutdown( void )
if( !dma.initialized ) return;
Cmd_RemoveCommand( "play" );
Cmd_RemoveCommand( "playvol" );
Cmd_RemoveCommand( "stopsound" );
Cmd_RemoveCommand( "music" );
Cmd_RemoveCommand( "soundlist" );
Cmd_RemoveCommand( "s_info" );
Cmd_RemoveCommand( "+voicerecord" );
Cmd_RemoveCommand( "-voicerecord" );
Cmd_RemoveCommand( "spk" );
Cmd_RemoveCommand( "speak" );
S_StopAllSounds ();
S_FreeSounds ();

View File

@ -351,6 +351,7 @@ extern sysinfo_t SI;
//
void FS_Init( void );
void FS_Path( void );
void FS_Rescan( void );
void FS_Shutdown( void );
void FS_ClearSearchPath( void );
void FS_AllowDirectPaths( qboolean enable );

View File

@ -27,7 +27,7 @@ void DBG_AssertFunction( qboolean fExpr, const char* szExpr, const char* szFile,
if( fExpr ) return;
if( szMessage != NULL )
MsgDev( at_error, "ASSERT FAILED:\n %s \n(%s@%d)\n%s", szExpr, szFile, szLine, szMessage );
MsgDev( at_error, "ASSERT FAILED:\n %s \n(%s@%d)\n%s\n", szExpr, szFile, szLine, szMessage );
else MsgDev( at_error, "ASSERT FAILED:\n %s \n(%s@%d)\n", szExpr, szFile, szLine );
}
#endif // DEBUG

View File

@ -311,13 +311,9 @@ void Con_CheckResize( void )
int charWidth = 8;
if( con.curFont && con.curFont->hFontTexture )
charWidth = con.curFont->charWidths['M'];
charWidth = con.curFont->charWidths['M'] - 1;
width = ( scr_width->integer / charWidth ) - 2;
// NOTE: Con_CheckResize is totally wrong :-(
// g-cont. i've just used fixed width on all resolutions
width = 90;
width = ( scr_width->integer / charWidth );
if( width == con.linewidth )
return;
@ -759,10 +755,12 @@ void Con_Print( const char *txt )
if( txt[l] <= ' ')
break;
}
#if 0
// g-cont. experiment from SDLash3D
// word wrap
if( l != con.linewidth && ( con.x + l >= con.linewidth ))
Con_Linefeed();
#endif
txt++;
switch( c )
@ -1007,6 +1005,7 @@ void Con_CompleteCommand( field_t *field )
{
field_t temp;
string filename;
qboolean nextcmd;
autocomplete_list_t *list;
int i;
@ -1016,6 +1015,8 @@ void Con_CompleteCommand( field_t *field )
// only look at the first token for completion purposes
Cmd_TokenizeString( con.completionField->buffer );
nextcmd = ( con.completionField->buffer[Q_strlen( con.completionField->buffer ) - 1] == ' ' ) ? true : false;
con.completionString = Cmd_Argv( 0 );
// skip backslash
@ -1046,7 +1047,7 @@ void Con_CompleteCommand( field_t *field )
Q_memcpy( &temp, con.completionField, sizeof( field_t ));
if( Cmd_Argc() == 2 )
if(( Cmd_Argc() == 2 ) || (( Cmd_Argc() == 1 ) && nextcmd ))
{
qboolean result = false;

View File

@ -48,13 +48,13 @@ void BF_InitMasks( void )
{
endbit = startbit + nBitsLeft;
BitWriteMasks[startbit][nBitsLeft] = BIT( startbit ) - 1;
if( endbit < 32 ) BitWriteMasks[startbit][nBitsLeft] |= ~(BIT( endbit ) - 1 );
BitWriteMasks[startbit][nBitsLeft] = (uint)BIT( startbit ) - 1;
if( endbit < 32 ) BitWriteMasks[startbit][nBitsLeft] |= ~((uint)BIT( endbit ) - 1 );
}
}
for( maskBit = 0; maskBit < 32; maskBit++ )
ExtraMasks[maskBit] = BIT( maskBit ) - 1;
ExtraMasks[maskBit] = (uint)BIT( maskBit ) - 1;
}
void BF_InitExt( sizebuf_t *bf, const char *pDebugName, void *pData, int nBytes, int nMaxBits )
@ -255,13 +255,13 @@ void BF_WriteBitAngle( sizebuf_t *bf, float fAngle, int numbits )
int d;
// clamp the angle before receiving
if( fAngle > 360.0f ) fAngle -= 360.0f;
else if( fAngle < 0 ) fAngle += 360.0f;
fAngle = fmod( fAngle, 360.0f );
if( fAngle < 0 ) fAngle += 360.0f;
shift = ( 1 << numbits );
mask = shift - 1;
d = (int)( fAngle * shift ) / 360;
d = (int)(( fAngle * shift ) / 360.0f );
d &= mask;
BF_WriteUBitLong( bf, (uint)d, numbits );

View File

@ -885,63 +885,63 @@ int Delta_ClampIntegerField( int iValue, qboolean bSigned, int bits )
iValue = bound( 0, (byte)iValue, 1 );
break;
case 2:
if( bSigned ) iValue = bound( -1, (short)iValue, 2 );
if( bSigned ) iValue = bound( -2, (short)iValue, 1 );
else iValue = bound( 0, (word)iValue, 3 );
break;
case 3:
if( bSigned ) iValue = bound( -3, (short)iValue, 4 );
if( bSigned ) iValue = bound( -4, (short)iValue, 3 );
else iValue = bound( 0, (word)iValue, 7 );
break;
case 4:
if( bSigned ) iValue = bound( -7, (short)iValue, 8 );
if( bSigned ) iValue = bound( -8, (short)iValue, 7 );
else iValue = bound( 0, (word)iValue, 15 );
break;
case 5:
if( bSigned ) iValue = bound( -15, (short)iValue, 16 );
if( bSigned ) iValue = bound( -16, (short)iValue, 15 );
else iValue = bound( 0, (word)iValue, 31 );
break;
case 6:
if( bSigned ) iValue = bound( -31, (short)iValue, 32 );
if( bSigned ) iValue = bound( -32, (short)iValue, 31 );
else iValue = bound( 0, (word)iValue, 63 );
break;
case 7:
if( bSigned ) iValue = bound( -63, (short)iValue, 64 );
if( bSigned ) iValue = bound( -64, (short)iValue, 63 );
else iValue = bound( 0, (word)iValue, 127 );
break;
case 8:
if( bSigned ) iValue = bound( -127, (short)iValue, 128 );
if( bSigned ) iValue = bound( -128, (short)iValue, 127 );
else iValue = bound( 0, (word)iValue, 255 );
break;
case 9:
if( bSigned ) iValue = bound( -255, (short)iValue, 256 );
if( bSigned ) iValue = bound( -256, (short)iValue, 255 );
else iValue = bound( 0, (word)iValue, 511 );
break;
case 10:
if( bSigned ) iValue = bound( -511, (short)iValue, 512 );
if( bSigned ) iValue = bound( -512, (short)iValue, 511 );
else iValue = bound( 0, (word)iValue, 1023 );
break;
case 11:
if( bSigned ) iValue = bound( -1023, (short)iValue, 1024 );
if( bSigned ) iValue = bound( -1024, (short)iValue, 1023 );
else iValue = bound( 0, (word)iValue, 2047 );
break;
case 12:
if( bSigned ) iValue = bound( -2047, (short)iValue, 2048 );
if( bSigned ) iValue = bound( -2048, (short)iValue, 2047 );
else iValue = bound( 0, (word)iValue, 4095 );
break;
case 13:
if( bSigned ) iValue = bound( -4095, (short)iValue, 4096 );
if( bSigned ) iValue = bound( -4096, (short)iValue, 4095 );
else iValue = bound( 0, (word)iValue, 8191 );
break;
case 14:
if( bSigned ) iValue = bound( -8191, (short)iValue, 8192 );
if( bSigned ) iValue = bound( -8192, (short)iValue, 8191 );
else iValue = bound( 0, (word)iValue, 16383 );
break;
case 15:
if( bSigned ) iValue = bound( -16383, (short)iValue, 16384 );
if( bSigned ) iValue = bound( -16384, (short)iValue, 16383 );
else iValue = bound( 0, (word)iValue, 32767 );
break;
case 16:
if( bSigned ) iValue = bound( -32767, (short)iValue, 32768 );
if( bSigned ) iValue = bound( -32768, (short)iValue, 32767 );
else iValue = bound( 0, (word)iValue, 65535 );
break;
}
@ -988,8 +988,8 @@ qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timeba
fromF = Delta_ClampIntegerField( fromF, bSigned, pField->bits );
toF = Delta_ClampIntegerField( toF, bSigned, pField->bits );
fromF *= pField->multiplier;
toF *= pField->multiplier;
if( pField->multiplier != 1.0f ) fromF *= pField->multiplier;
if( pField->multiplier != 1.0f ) toF *= pField->multiplier;
}
else if( pField->flags & DT_SHORT )
{
@ -1006,8 +1006,8 @@ qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timeba
fromF = Delta_ClampIntegerField( fromF, bSigned, pField->bits );
toF = Delta_ClampIntegerField( toF, bSigned, pField->bits );
fromF *= pField->multiplier;
toF *= pField->multiplier;
if( pField->multiplier != 1.0f ) fromF *= pField->multiplier;
if( pField->multiplier != 1.0f ) toF *= pField->multiplier;
}
else if( pField->flags & DT_INTEGER )
{
@ -1024,8 +1024,8 @@ qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timeba
fromF = Delta_ClampIntegerField( fromF, bSigned, pField->bits );
toF = Delta_ClampIntegerField( toF, bSigned, pField->bits );
fromF *= pField->multiplier;
toF *= pField->multiplier;
if( pField->multiplier != 1.0f ) fromF *= pField->multiplier;
if( pField->multiplier != 1.0f ) toF *= pField->multiplier;
}
else if( pField->flags & ( DT_FLOAT|DT_ANGLE ))
{
@ -1044,10 +1044,22 @@ qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timeba
}
else if( pField->flags & DT_TIMEWINDOW_BIG )
{
val_a = (*(float *)((byte *)from + pField->offset )) * pField->multiplier;
val_b = (*(float *)((byte *)to + pField->offset )) * pField->multiplier;
val_a = (timebase * pField->multiplier) - val_a;
val_b = (timebase * pField->multiplier) - val_b;
val_a = (*(float *)((byte *)from + pField->offset ));
val_b = (*(float *)((byte *)to + pField->offset ));
if( pField->multiplier != 1.0f )
{
val_a *= pField->multiplier;
val_b *= pField->multiplier;
val_a = (timebase * pField->multiplier) - val_a;
val_b = (timebase * pField->multiplier) - val_b;
}
else
{
val_a = timebase - val_a;
val_b = timebase - val_b;
}
fromF = *((int *)&val_a);
toF = *((int *)&val_b);
}
@ -1091,21 +1103,21 @@ qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to
{
iValue = *(byte *)((byte *)to + pField->offset );
iValue = Delta_ClampIntegerField( iValue, bSigned, pField->bits );
iValue *= pField->multiplier;
if( pField->multiplier != 1.0f ) iValue *= pField->multiplier;
BF_WriteBitLong( msg, iValue, pField->bits, bSigned );
}
else if( pField->flags & DT_SHORT )
{
iValue = *(word *)((byte *)to + pField->offset );
iValue = Delta_ClampIntegerField( iValue, bSigned, pField->bits );
iValue *= pField->multiplier;
if( pField->multiplier != 1.0f ) iValue *= pField->multiplier;
BF_WriteBitLong( msg, iValue, pField->bits, bSigned );
}
else if( pField->flags & DT_INTEGER )
{
iValue = *(uint *)((byte *)to + pField->offset );
iValue = Delta_ClampIntegerField( iValue, bSigned, pField->bits );
iValue *= pField->multiplier;
if( pField->multiplier != 1.0f ) iValue *= pField->multiplier;
BF_WriteBitLong( msg, iValue, pField->bits, bSigned );
}
else if( pField->flags & DT_FLOAT )
@ -1172,7 +1184,7 @@ qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, void *to,
if( bChanged )
{
iValue = BF_ReadBitLong( msg, pField->bits, bSigned );
iValue /= pField->multiplier;
if( pField->multiplier != 1.0f ) iValue /= pField->multiplier;
}
else
{
@ -1185,7 +1197,7 @@ qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, void *to,
if( bChanged )
{
iValue = BF_ReadBitLong( msg, pField->bits, bSigned );
iValue /= pField->multiplier;
if( pField->multiplier != 1.0f ) iValue /= pField->multiplier;
}
else
{
@ -1198,7 +1210,7 @@ qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, void *to,
if( bChanged )
{
iValue = BF_ReadBitLong( msg, pField->bits, bSigned );
iValue /= pField->multiplier;
if( pField->multiplier != 1.0f ) iValue /= pField->multiplier;
}
else
{
@ -1251,7 +1263,7 @@ qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, void *to,
if( bChanged )
{
iValue = BF_ReadBitLong( msg, pField->bits, bSigned );
flValue = (float)(iValue * ( 1.0f / pField->multiplier ));
flValue = (float)((int)iValue) * ( 1.0f / pField->multiplier );
flTime = timebase + flValue;
}
else

View File

@ -59,7 +59,7 @@ GNU General Public License for more details.
// bytes will be stripped by the networking channel layer
#define NET_MAX_MESSAGE PAD_NUMBER(( NET_MAX_PAYLOAD + HEADER_BYTES ), 16 )
#define MASTERSERVER_ADR "hl1master.steampowered.com:27010"
#define MASTERSERVER_ADR "celest.in:27010"
#define PORT_MASTER 27010
#define PORT_CLIENT 27005
#define PORT_SERVER 27015

View File

@ -297,7 +297,7 @@ pmtrace_t PM_PlayerTraceExt( playermove_t *pmove, vec3_t start, vec3_t end, int
vec3_t temp, mins, maxs;
int i, j, hullcount;
qboolean rotated, transform_bbox;
hull_t *hull;
hull_t *hull = NULL;
Q_memset( &trace_total, 0, sizeof( trace_total ));
VectorCopy( end, trace_total.endpos );
@ -503,9 +503,9 @@ int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, p
{
int i, j, hullcount;
vec3_t pos_l, offset;
hull_t *hull = NULL;
vec3_t mins, maxs;
pmtrace_t trace;
hull_t *hull;
physent_t *pe;
trace = PM_PlayerTraceExt( pmove, pmove->origin, pmove->origin, 0, pmove->numphysent, pmove->physents, -1, pmFilter );

View File

@ -50,6 +50,8 @@ typedef struct resourceinfo_s
// or is it a server startup resource.
#define RES_REQUESTED (1<<3) // Already requested a download of this one
#define RES_PRECACHED (1<<4) // Already precached
#define RES_ALWAYS (1<<5) // Download always even if available on client
#define RES_CHECKFILE (1<<7) // Check file on client
typedef struct resource_s
{

View File

@ -517,6 +517,7 @@ void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed );
qboolean SV_IsPlayerIndex( int idx );
void SV_InitClientMove( void );
void SV_UpdateServerInfo( void );
void SV_EndRedirect( void );
//
// sv_cmds.c

View File

@ -122,7 +122,7 @@ void SV_DirectConnect( netadr_t from )
// quick reject
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
{
if( cl->state == cs_free )
if( cl->state == cs_free || cl->state == cs_zombie )
continue;
if( NET_CompareBaseAdr( from, cl->netchan.remote_address ) && ( cl->netchan.qport == qport || from.port == cl->netchan.remote_address.port ))
@ -169,7 +169,7 @@ void SV_DirectConnect( netadr_t from )
// if there is already a slot for this ip, reuse it
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
{
if( cl->state == cs_free )
if( cl->state == cs_free || cl->state == cs_zombie )
continue;
if( NET_CompareBaseAdr( from, cl->netchan.remote_address ) && ( cl->netchan.qport == qport || from.port == cl->netchan.remote_address.port ))
@ -438,9 +438,17 @@ void SV_DropClient( sv_client_t *drop )
Mem_Free( drop->frames ); // fakeclients doesn't have frames
drop->frames = NULL;
if( NET_CompareBaseAdr( drop->netchan.remote_address, host.rd.address ) )
SV_EndRedirect();
// throw away any residual garbage in the channel.
Netchan_Clear( &drop->netchan );
// clean client data on disconnect
Q_memset( drop->userinfo, 0, MAX_INFO_STRING );
Q_memset( drop->physinfo, 0, MAX_INFO_STRING );
drop->edict->v.frags = 0;
// send notification to all other clients
SV_FullClientUpdate( drop, &sv.reliable_datagram );
@ -502,7 +510,8 @@ void SV_FlushRedirect( netadr_t adr, int dest, char *buf )
void SV_EndRedirect( void )
{
host.rd.flush( host.rd.address, host.rd.target, host.rd.buffer );
if( host.rd.flush )
host.rd.flush( host.rd.address, host.rd.target, host.rd.buffer );
host.rd.target = 0;
host.rd.buffer = NULL;
@ -1985,10 +1994,9 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
char *args;
char *c, buf[MAX_SYSPATH];
int len = sizeof( buf );
dword challenge;
uint challenge;
int index, count = 0;
char query[512];
word port;
char query[512], ostype = 'w';
BF_Clear( msg );
BF_ReadLong( msg );// skip the -1 marker
@ -2007,12 +2015,9 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
else if( !Q_strcmp( c, "connect" )) SV_DirectConnect( from );
else if( !Q_strcmp( c, "rcon" )) SV_RemoteCommand( from, msg );
else if( !Q_strcmp( c, "netinfo" )) SV_BuildNetAnswer( from );
else if( msg->pData[0] == 0xFF && msg->pData[1] == 0xFF && msg->pData[2] == 0xFF && msg->pData[3] == 0xFF && msg->pData[4] == 0x4E && msg->pData[5] == 0x0A )
else if( msg->pData[0] == 0xFF && msg->pData[1] == 0xFF && msg->pData[2] == 0xFF && msg->pData[3] == 0xFF && msg->pData[4] == 0x73 && msg->pData[5] == 0x0A )
{
challenge = *(dword *)&msg->pData[6];
port = Cvar_Get( "ip_hostport", "0", CVAR_INIT, "network server port" )->integer;
if( !port ) port = Cvar_Get( "port", va( "%i", PORT_SERVER ), CVAR_INIT, "network default port" )->integer;
Q_memcpy(&challenge, &msg->pData[6], sizeof(int));
for( index = 0; index < sv_maxclients->integer; index++ )
{
@ -2021,8 +2026,32 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
}
Q_snprintf( query, sizeof( query ),
"0\n\\protocol\\7\\challenge\\%ld\\players\\%d\\max\\%d\\bots\\0\\gamedir\\%s_xash\\map\\%s\\password\\0\\os\\w\\lan\\0\\region\\255\\gameport\\%d\\specport\\27015\\dedicated\\1\\appid\\70\\type\\d\\secure\\0\\version\\1.1.2.1\\product\\valve\n",
challenge, count, sv_maxclients->integer, GI->gamefolder, sv.name, port );
"0\n"
"\\protocol\\%d" // protocol version
"\\challenge\\%u" // challenge number that got after FF FF FF FF 73 0A
"\\players\\%d" // current player number
"\\max\\%d" // max_players
"\\bots\\0" // bot number?
"\\gamedir\\%s" // gamedir. _xash appended, because Xash3D is not compatible with GS in multiplayer
"\\map\\%s" // current map
"\\type\\d" // server type
"\\password\\0" // is password set
"\\os\\%c" // server OS?
"\\secure\\0" // server anti-cheat? VAC?
"\\lan\\0" // is LAN server?
"\\version\\%f" // server version
"\\region\\255" // server region
"\\product\\%s\n", // product? Where is the difference with gamedir?
PROTOCOL_VERSION,
challenge,
count,
sv_maxclients->integer,
GI->gamefolder,
sv.name,
ostype,
XASH_VERSION,
GI->gamefolder
);
NET_SendPacket( NS_SERVER, Q_strlen( query ), query, from );
}

View File

@ -109,7 +109,7 @@ qboolean SV_SetPlayer( void )
sv_client_t *cl;
int i, idnum;
if( !svs.clients )
if( !svs.clients || sv.background )
{
Msg( "^3no server running.\n" );
return false;
@ -418,7 +418,7 @@ void SV_DeleteSave_f( void )
{
if( Cmd_Argc() != 2 )
{
Msg( "Usage: delsave <name>\n" );
Msg( "Usage: killsave <name>\n" );
return;
}
@ -599,18 +599,18 @@ void SV_Kick_f( void )
{
if( Cmd_Argc() != 2 )
{
Msg( "Usage: kick <userid>\n" );
return;
}
if( !svs.clients || sv.background )
{
Msg( "^3no server running.\n" );
Msg( "Usage: kick <userid> | <name>\n" );
return;
}
if( !SV_SetPlayer( )) return;
if( NET_IsLocalAddress( svs.currentPlayer->netchan.remote_address ))
{
Msg( "The local player cannot be kicked!\n" );
return;
}
SV_BroadcastPrintf( PRINT_HIGH, "%s was kicked\n", svs.currentPlayer->name );
SV_ClientPrintf( svs.currentPlayer, PRINT_HIGH, "You were kicked from the game\n" );
SV_DropClient( svs.currentPlayer );
@ -626,8 +626,7 @@ SV_Kill_f
*/
void SV_Kill_f( void )
{
if( !SV_SetPlayer() || sv.background )
return;
if( !SV_SetPlayer( )) return;
if( !svs.currentPlayer || !SV_IsValidEdict( svs.currentPlayer->edict ))
return;

View File

@ -507,7 +507,7 @@ void SV_WriteClientdataToMessage( sv_client_t *cl, sizebuf_t *msg )
{
Q_memset( &nullwd, 0, sizeof( nullwd ));
for( i = 0; i < 32; i++ )
for( i = 0; i < 64; i++ )
{
if( cl->delta_sequence == -1 ) from_wd = &nullwd;
else from_wd = &cl->frames[cl->delta_sequence & SV_UPDATE_MASK].weapondata[i];

View File

@ -866,6 +866,12 @@ void SV_FreeEdict( edict_t *pEdict )
pEdict->v.takedamage = 0;
pEdict->v.modelindex = 0;
pEdict->v.nextthink = -1;
pEdict->v.colormap = 0;
pEdict->v.frame = 0;
pEdict->v.scale = 0;
pEdict->v.gravity = 0;
VectorClear( pEdict->v.angles );
VectorClear( pEdict->v.origin );
pEdict->free = true;
}

View File

@ -583,7 +583,7 @@ void Master_Add( void )
if( !NET_StringToAdr( MASTERSERVER_ADR, &adr ))
MsgDev( D_INFO, "Can't resolve adr: %s\n", MASTERSERVER_ADR );
NET_SendPacket( NS_SERVER, 2, "\x4D\xFF", adr );
NET_SendPacket( NS_SERVER, 1, "q", adr );
}
/*
@ -620,6 +620,14 @@ Informs all masters that this server is going down
*/
void Master_Shutdown( void )
{
netadr_t adr;
NET_Config( true ); // allow remote
if( !NET_StringToAdr( MASTERSERVER_ADR, &adr ))
MsgDev( D_INFO, "Can't resolve addr: %s\n", MASTERSERVER_ADR );
NET_SendPacket( NS_SERVER, 2, "\x62\x0A", adr );
}
//============================================================================
@ -785,10 +793,17 @@ void SV_Shutdown( qboolean reconnect )
// already freed
if( !SV_Active( )) return;
if( host.type == HOST_DEDICATED ) MsgDev( D_INFO, "SV_Shutdown: %s\n", host.finalmsg );
if( svs.clients ) SV_FinalMessage( host.finalmsg, reconnect );
// rcon will be disconnected
SV_EndRedirect();
Master_Shutdown();
if( host.type == HOST_DEDICATED )
MsgDev( D_INFO, "SV_Shutdown: %s\n", host.finalmsg );
if( svs.clients )
SV_FinalMessage( host.finalmsg, reconnect );
if( public_server->integer && sv_maxclients->integer != 1 )
Master_Shutdown();
if( !reconnect ) SV_UnloadProgs ();
else SV_DeactivateServer ();

View File

@ -67,7 +67,8 @@ qboolean SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed )
if( ed->v.flags & ( FL_CLIENT|FL_FAKECLIENT ))
{
// client or bot
SV_GetTrueOrigin( svs.currentPlayer, (pe->info - 1), pe->origin );
if( svs.currentPlayer )
SV_GetTrueOrigin( svs.currentPlayer, (pe->info - 1), pe->origin );
Q_strncpy( pe->name, "player", sizeof( pe->name ));
pe->player = pe->info;
}
@ -141,7 +142,7 @@ qboolean SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed )
void SV_GetTrueOrigin( sv_client_t *cl, int edictnum, vec3_t origin )
{
if( !cl->local_weapons || !cl->lag_compensation || !sv_unlag->integer )
if( !cl->lag_compensation || !sv_unlag->integer )
return;
// don't allow unlag in singleplayer
@ -158,7 +159,7 @@ void SV_GetTrueOrigin( sv_client_t *cl, int edictnum, vec3_t origin )
void SV_GetTrueMinMax( sv_client_t *cl, int edictnum, vec3_t mins, vec3_t maxs )
{
if( !cl->local_weapons || !cl->lag_compensation || !sv_unlag->integer )
if( !cl->lag_compensation || !sv_unlag->integer )
return;
// don't allow unlag in singleplayer
@ -235,7 +236,8 @@ void SV_AddLinksToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3_t
if( check->v.flags & FL_CLIENT )
{
// trying to get interpolated values
SV_GetTrueMinMax( svs.currentPlayer, ( NUM_FOR_EDICT( check ) - 1), mins, maxs );
if( svs.currentPlayer )
SV_GetTrueMinMax( svs.currentPlayer, ( NUM_FOR_EDICT( check ) - 1), mins, maxs );
}
if( !BoundsIntersect( pmove_mins, pmove_maxs, mins, maxs ))
@ -819,7 +821,7 @@ void SV_SetupMoveInterpolant( sv_client_t *cl )
return;
// unlag disabled for current client
if( !cl->local_weapons || !cl->lag_compensation )
if( !cl->lag_compensation )
return;
has_update = true;
@ -976,7 +978,7 @@ void SV_RestoreMoveInterpolant( sv_client_t *cl )
return;
// unlag disabled for current client
if( !cl->local_weapons || !cl->lag_compensation )
if( !cl->lag_compensation )
return;
for( i = 0, check = svs.clients; i < sv_maxclients->integer; i++, check++ )

View File

@ -1250,6 +1250,9 @@ void UI_AddServerToList( netadr_t adr, const char *info )
if( uiStatic.numServers == UI_MAX_SERVERS )
return; // full
if( stricmp( gMenu.m_gameinfo.gamefolder, Info_ValueForKey( info, "gamedir" )))
return;
// ignore if duplicated
for( i = 0; i < uiStatic.numServers; i++ )
{

View File

@ -124,12 +124,7 @@ static void UI_InternetGames_GetGamesList( void )
{
if( i >= UI_MAX_SERVERS ) break;
info = uiStatic.serverNames[i];
#if 1
// NOTE: Xash3D is support hot switching between games in multiplayer
// but this feature not detail tested and may be bugly
if( stricmp( gMenu.m_gameinfo.gamefolder, Info_ValueForKey( info, "gamedir" )))
continue; // filter by game
#endif
StringConcat( uiInternetGames.gameDescription[i], Info_ValueForKey( info, "host" ), GAME_LENGTH );
StringConcat( uiInternetGames.gameDescription[i], uiEmptyString, GAME_LENGTH );
StringConcat( uiInternetGames.gameDescription[i], Info_ValueForKey( info, "map" ), MAPNAME_LENGTH );