11 Jul 2008
This commit is contained in:
parent
2f66b421d0
commit
58d4865f0a
|
@ -1387,7 +1387,6 @@ Called when either the cinematic completes, or it is aborted
|
|||
void SCR_FinishCinematic( void )
|
||||
{
|
||||
// tell the server to advance to the next map / cinematic
|
||||
MSG_WriteByte( &cl.netmsg, clc_stringcmd );
|
||||
SZ_Print(&cl.netmsg, "disconnect" );
|
||||
MSG_WriteByte( &cl.netmsg, clc_eof ); // end of message
|
||||
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
|
||||
SZ_Print(&cls.netchan.message, "disconnect" );
|
||||
}
|
||||
|
|
|
@ -270,10 +270,10 @@ void CL_ParsePlayerstate( sizebuf_t *msg, frame_t *oldframe, frame_t *newframe )
|
|||
int i;
|
||||
int statbits;
|
||||
|
||||
state = &newframe->playerstate;
|
||||
state = &newframe->ps;
|
||||
|
||||
// clear to old value before delta parsing
|
||||
if (oldframe) *state = oldframe->playerstate;
|
||||
if (oldframe) *state = oldframe->ps;
|
||||
else memset (state, 0, sizeof(*state));
|
||||
|
||||
flags = MSG_ReadLong(msg);//four bytes
|
||||
|
@ -281,7 +281,8 @@ void CL_ParsePlayerstate( sizebuf_t *msg, frame_t *oldframe, frame_t *newframe )
|
|||
// parse the pmove_state_t
|
||||
if (flags & PS_M_ORIGIN) MSG_ReadPos32(msg, state->origin );
|
||||
if (flags & PS_M_VELOCITY) MSG_ReadPos32(msg, state->velocity );
|
||||
if (flags & PS_M_TIME) state->pm_time = MSG_ReadLong (msg);
|
||||
if (flags & PS_M_TIME) state->pm_time = MSG_ReadByte (msg);
|
||||
if (flags & PS_M_COMMANDMSEC) state->cmd_time = MSG_ReadLong (msg);
|
||||
if (flags & PS_M_FLAGS) state->pm_flags = MSG_ReadByte (msg);
|
||||
if (flags & PS_M_GRAVITY) state->gravity = MSG_ReadShort (msg);
|
||||
if (flags & PS_M_DELTA_ANGLES) MSG_ReadPos32(msg, state->delta_angles );
|
||||
|
@ -448,8 +449,8 @@ void CL_ParseFrame( sizebuf_t *msg )
|
|||
cls.state = ca_active;
|
||||
cl.force_refdef = true;
|
||||
// getting a valid frame message ends the connection process
|
||||
VectorScale( cl.frame.playerstate.origin, CL_COORD_FRAC, cl.predicted_origin );
|
||||
VectorCopy( cl.frame.playerstate.viewangles, cl.predicted_angles );
|
||||
VectorScale( cl.frame.ps.origin, CL_COORD_FRAC, cl.predicted_origin );
|
||||
VectorCopy( cl.frame.ps.viewangles, cl.predicted_angles );
|
||||
}
|
||||
CL_CheckPredictionError();
|
||||
}
|
||||
|
@ -650,12 +651,12 @@ void CL_CalcViewValues( void )
|
|||
}
|
||||
|
||||
// find the previous frame to interpolate from
|
||||
ps = &cl.frame.playerstate;
|
||||
ps = &cl.frame.ps;
|
||||
i = (cl.frame.serverframe - 1) & UPDATE_MASK;
|
||||
oldframe = &cl.frames[i];
|
||||
if( oldframe->serverframe != cl.frame.serverframe-1 || !oldframe->valid )
|
||||
oldframe = &cl.frame; // previous frame was dropped or invalid
|
||||
ops = &oldframe->playerstate;
|
||||
ops = &oldframe->ps;
|
||||
|
||||
// see if the player entity was teleported this frame
|
||||
if( ps->pm_flags & PMF_TIME_TELEPORT )
|
||||
|
@ -663,7 +664,7 @@ void CL_CalcViewValues( void )
|
|||
lerp = cl.lerpfrac;
|
||||
|
||||
// calculate the origin
|
||||
if((cl_predict->value) && !(cl.frame.playerstate.pm_flags & PMF_NO_PREDICTION) && !cls.demoplayback )
|
||||
if((cl_predict->value) && !(cl.frame.ps.pm_flags & PMF_NO_PREDICTION) && !cls.demoplayback )
|
||||
{
|
||||
// use predicted values
|
||||
int delta;
|
||||
|
|
|
@ -85,7 +85,7 @@ void CL_MouseMove( usercmd_t *cmd )
|
|||
if( cls.key_dest != key_menu )
|
||||
{
|
||||
accel_sensitivity = cl_sensitivity->value + rate * cl_mouseaccel->value;
|
||||
accel_sensitivity *= cl.mouse_sens; // scale by fov
|
||||
//accel_sensitivity *= cl.mouse_sens; // scale by fov
|
||||
mx *= accel_sensitivity;
|
||||
my *= accel_sensitivity;
|
||||
|
||||
|
@ -251,7 +251,7 @@ void IN_Attack2Down(void) {IN_KeyDown(&in_attack2);}
|
|||
void IN_Attack2Up(void) {IN_KeyUp(&in_attack2);}
|
||||
void IN_UseDown (void) {IN_KeyDown(&in_use);}
|
||||
void IN_UseUp (void) {IN_KeyUp(&in_use);}
|
||||
void IN_CenterView (void) {cl.viewangles[PITCH] = -SHORT2ANGLE(cl.frame.playerstate.delta_angles[PITCH]);}
|
||||
void IN_CenterView (void) {cl.viewangles[PITCH] = -SHORT2ANGLE(cl.frame.ps.delta_angles[PITCH]);}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
|
@ -407,6 +407,8 @@ void CL_CreateNewCommands( void )
|
|||
{
|
||||
int cmd_num;
|
||||
|
||||
if( cls.state < ca_connected ) return;
|
||||
|
||||
frame_msec = host.frametime[0] - host.frametime[1];
|
||||
if( frame_msec > 200 ) frame_msec = 200;
|
||||
host.frametime[1] = host.frametime[0];
|
||||
|
@ -438,12 +440,12 @@ bool CL_ReadyToSendPacket( void )
|
|||
return false;
|
||||
|
||||
// If we are downloading, we send no less than 50ms between packets
|
||||
if( *cls.downloadtempname && cls.realtime - cls.last_sent < 50 )
|
||||
if( *cls.downloadtempname && cls.realtime - cls.netchan.last_sent < 50 )
|
||||
return false;
|
||||
|
||||
// if we don't have a valid gamestate yet, only send
|
||||
// one packet a second
|
||||
if( cls.state < ca_connected && !*cls.downloadtempname && cls.realtime - cls.last_sent < 1000 )
|
||||
if( cls.state < ca_connected && !*cls.downloadtempname && cls.realtime - cls.netchan.last_sent < 1000 )
|
||||
return false;
|
||||
|
||||
// send every frame for loopbacks
|
||||
|
@ -488,29 +490,24 @@ During normal gameplay, a client packet will contain something like:
|
|||
void CL_WritePacket( void )
|
||||
{
|
||||
int i, j;
|
||||
sizebuf_t buf;
|
||||
usercmd_t *cmd, *oldcmd, nullcmd;
|
||||
int packet_num, old_packetnum;
|
||||
int count, checksumIndex, crc;
|
||||
byte data[MAX_MSGLEN];
|
||||
sizebuf_t usercmd;
|
||||
|
||||
// don't send anything if playing back a demo
|
||||
if( cls.demoplayback || cls.state == ca_cinematic )
|
||||
return;
|
||||
|
||||
|
||||
if( cls.state == ca_connected )
|
||||
{
|
||||
if( cl.netmsg.cursize || cls.realtime - cls.last_sent > 1000 )
|
||||
{
|
||||
Msg("CL_WritePacket: %s\n", cl.netmsg.data );
|
||||
Netchan_Transmit( &cls.netchan, cl.netmsg.cursize, cl.netmsg.data);
|
||||
SZ_Clear( &cl.netmsg );
|
||||
}
|
||||
if (cls.netchan.message.cursize || cls.realtime - cls.netchan.last_sent > 1000 )
|
||||
Netchan_Transmit (&cls.netchan, 0, NULL );
|
||||
return;
|
||||
}
|
||||
|
||||
SZ_Init( &buf, data, sizeof( data ));
|
||||
SZ_Init(&usercmd, data, sizeof(data));
|
||||
memset( &nullcmd, 0, sizeof(nullcmd));
|
||||
oldcmd = &nullcmd;
|
||||
|
||||
|
@ -518,58 +515,48 @@ void CL_WritePacket( void )
|
|||
if( userinfo_modified )
|
||||
{
|
||||
userinfo_modified = false;
|
||||
MSG_WriteByte( &buf, clc_userinfo);
|
||||
MSG_WriteString (&buf, Cvar_Userinfo());
|
||||
MSG_WriteByte( &buf, clc_eof ); // end of message
|
||||
MSG_WriteByte( &cls.netchan.message, clc_userinfo);
|
||||
MSG_WriteString (&cls.netchan.message, Cvar_Userinfo());
|
||||
}
|
||||
|
||||
old_packetnum = ( cls.netchan.outgoing_sequence - 2 ) & PACKET_MASK;
|
||||
count = cl.cmd_number - cl.packets[old_packetnum].cmdnumber;
|
||||
count = cl.cmd_number - cl.packets[old_packetnum].cmd_number;
|
||||
if( count > PACKET_BACKUP ) count = PACKET_BACKUP;
|
||||
|
||||
if( count >= 1 )
|
||||
{
|
||||
// begin a client move command
|
||||
MSG_WriteByte (&buf, clc_move);
|
||||
|
||||
MSG_WriteByte (&usercmd, clc_move);
|
||||
// save the position for a checksum byte
|
||||
checksumIndex = buf.cursize;
|
||||
MSG_WriteByte( &buf, 0 );
|
||||
checksumIndex = usercmd.cursize;
|
||||
MSG_WriteByte( &usercmd, 0 );
|
||||
|
||||
// let the server know what the last frame we
|
||||
// got was, so the next message can be delta compressed
|
||||
if( cl_nodelta->value || !cl.frame.valid || cls.demowaiting )
|
||||
{
|
||||
MSG_WriteLong( &buf, -1 ); // no compression
|
||||
MSG_WriteLong( &usercmd, -1 ); // no compression
|
||||
}
|
||||
else MSG_WriteLong( &buf, cl.frame.serverframe );
|
||||
MSG_WriteByte( &buf, count ); // write the command count
|
||||
else MSG_WriteLong( &usercmd, cl.frame.serverframe );
|
||||
MSG_WriteByte( &usercmd, count ); // write the command count
|
||||
|
||||
// write all the commands, including the predicted command
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
j = (cl.cmd_number - count + i + 1) & CMD_MASK;
|
||||
j = (cls.netchan.outgoing_sequence - count + i + 1) & CMD_MASK;
|
||||
cmd = &cl.cmds[j];
|
||||
MSG_WriteDeltaUsercmd( &buf, oldcmd, cmd );
|
||||
MSG_WriteDeltaUsercmd( &usercmd, oldcmd, cmd );
|
||||
oldcmd = cmd;
|
||||
}
|
||||
|
||||
// calculate a checksum over the move commands
|
||||
crc = CRC_Sequence( usercmd.data+checksumIndex+1, usercmd.cursize-checksumIndex-1, cls.netchan.outgoing_sequence);
|
||||
usercmd.data[checksumIndex] = crc;
|
||||
}
|
||||
MSG_WriteByte( &buf, clc_eof ); // end of message
|
||||
|
||||
// deliver the message
|
||||
packet_num = cls.netchan.outgoing_sequence & PACKET_MASK;
|
||||
cl.packets[packet_num].realtime = cls.realtime;
|
||||
cl.packets[packet_num].servertime = oldcmd->servertime;
|
||||
cl.packets[packet_num].cmdnumber = cl.cmd_number;
|
||||
cls.last_sent = cls.realtime;
|
||||
|
||||
// calculate a checksum over the move commands
|
||||
crc = CRC_Sequence( buf.data+checksumIndex+1, buf.cursize-checksumIndex-1, cls.netchan.outgoing_sequence);
|
||||
buf.data[checksumIndex] = crc;
|
||||
Netchan_Transmit( &cls.netchan, buf.cursize, buf.data );
|
||||
// just in case, not really needed
|
||||
while( cls.netchan.unsent_fragments )
|
||||
Netchan_TransmitNextFragment( &cls.netchan );
|
||||
cls.netchan.last_sent = cls.realtime;
|
||||
Netchan_Transmit( &cls.netchan, usercmd.cursize, usercmd.data );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1115,7 +1115,7 @@ void Key_Event( int key, bool down, uint time )
|
|||
// escape is always handled special
|
||||
if ( key == K_ESCAPE && down )
|
||||
{
|
||||
if (cl.frame.playerstate.stats[STAT_LAYOUTS] && cls.key_dest == key_game)
|
||||
if (cl.frame.ps.stats[STAT_LAYOUTS] && cls.key_dest == key_game)
|
||||
{
|
||||
// put away help computer / inventory
|
||||
Cbuf_AddText ("cmd putaway\n");
|
||||
|
|
|
@ -97,14 +97,14 @@ void Cmd_ForwardToServer (void)
|
|||
return;
|
||||
}
|
||||
|
||||
MSG_WriteByte (&cl.netmsg, clc_stringcmd);
|
||||
SZ_Print (&cl.netmsg, cmd);
|
||||
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
|
||||
SZ_Print (&cls.netchan.message, cmd);
|
||||
if (Cmd_Argc() > 1)
|
||||
{
|
||||
SZ_Print (&cl.netmsg, " ");
|
||||
SZ_Print (&cl.netmsg, Cmd_Args());
|
||||
SZ_Print (&cls.netchan.message, " ");
|
||||
SZ_Print (&cls.netchan.message, Cmd_Args());
|
||||
Msg("clc_stringcmd: %s\n", Cmd_Args());
|
||||
}
|
||||
MSG_WriteByte( &cl.netmsg, clc_eof ); // end of message
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -124,10 +124,8 @@ void CL_ForwardToServer_f (void)
|
|||
// don't forward the first argument
|
||||
if (Cmd_Argc() > 1)
|
||||
{
|
||||
SZ_Init (&cl.netmsg, cl.netbuf, sizeof( cl.netbuf ));
|
||||
MSG_WriteByte( &cl.netmsg, clc_stringcmd );
|
||||
SZ_Print( &cl.netmsg, Cmd_Args());
|
||||
MSG_WriteByte( &cl.netmsg, clc_eof ); // end of message
|
||||
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
|
||||
SZ_Print( &cls.netchan.message, Cmd_Args());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -351,7 +349,7 @@ void CL_ClearState (void)
|
|||
|
||||
// wipe the entire cl structure
|
||||
memset (&cl, 0, sizeof(cl));
|
||||
SZ_Clear (&cl.netmsg);
|
||||
SZ_Clear (&cls.netchan.message);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -382,7 +380,6 @@ void CL_Disconnect( void )
|
|||
// send a disconnect message to the server
|
||||
final[0] = clc_stringcmd;
|
||||
com.strcpy((char *)final + 1, "disconnect");
|
||||
final[com.strlen(final)] = clc_eof;
|
||||
Netchan_Transmit(&cls.netchan, strlen(final), final);
|
||||
Netchan_Transmit(&cls.netchan, strlen(final), final);
|
||||
Netchan_Transmit(&cls.netchan, strlen(final), final);
|
||||
|
@ -420,7 +417,7 @@ void CL_DisconnectPacket( netadr_t from )
|
|||
|
||||
// if we have received packets within three seconds, ignore it
|
||||
// (it might be a malicious spoof)
|
||||
if( cls.realtime - cls.last_received < 3000 )
|
||||
if( cls.realtime - cls.netchan.last_received < 3000 )
|
||||
return;
|
||||
|
||||
// drop the connection
|
||||
|
@ -522,9 +519,8 @@ void CL_Reconnect_f (void)
|
|||
{
|
||||
Msg ("reconnecting...\n");
|
||||
cls.state = ca_connected;
|
||||
MSG_WriteChar (&cl.netmsg, clc_stringcmd);
|
||||
MSG_WriteString (&cl.netmsg, "new");
|
||||
MSG_WriteByte( &cl.netmsg, clc_eof ); // end of message
|
||||
MSG_WriteChar (&cls.netchan.message, clc_stringcmd);
|
||||
MSG_WriteString (&cls.netchan.message, "new");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -752,10 +748,8 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
|||
return;
|
||||
}
|
||||
Netchan_Setup( NS_CLIENT, &cls.netchan, from, Cvar_VariableValue( "net_qport" ));
|
||||
SZ_Init (&cl.netmsg, cl.netbuf, sizeof( cl.netbuf ));
|
||||
MSG_WriteChar( &cl.netmsg, clc_stringcmd );
|
||||
MSG_WriteString( &cl.netmsg, "new" );
|
||||
MSG_WriteByte( &cl.netmsg, clc_eof ); // end of message
|
||||
MSG_WriteChar( &cls.netchan.message, clc_stringcmd );
|
||||
MSG_WriteString( &cls.netchan.message, "new" );
|
||||
cls.state = ca_connected;
|
||||
return;
|
||||
}
|
||||
|
@ -1068,9 +1062,8 @@ void CL_RequestNextDownload (void)
|
|||
CL_PrepRefresh();
|
||||
|
||||
if( cls.demoplayback ) return; // not really connected
|
||||
MSG_WriteByte( &cl.netmsg, clc_stringcmd );
|
||||
MSG_WriteString( &cl.netmsg, va("begin %i\n", precache_spawncount));
|
||||
MSG_WriteByte( &cl.netmsg, clc_eof ); // end of message
|
||||
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
|
||||
MSG_WriteString( &cls.netchan.message, va("begin %i\n", precache_spawncount));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1254,15 +1247,19 @@ void CL_WriteConfiguration (void)
|
|||
//============================================================================
|
||||
void CL_ReadNetMessage( void )
|
||||
{
|
||||
sizebuf_t *msg = &cls.netmsg;
|
||||
sizebuf_t net_message;
|
||||
sizebuf_t *msg = &net_message;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
netadr_t net_from;
|
||||
|
||||
SZ_Init( msg, cls.netbuf, sizeof(cls.netbuf));
|
||||
while( NET_GetPacket(NS_CLIENT, &cls.from, msg ))
|
||||
SZ_Init( msg, buffer, sizeof(buffer));
|
||||
|
||||
while( NET_GetPacket(NS_CLIENT, &net_from, msg ))
|
||||
{
|
||||
if( msg->cursize >= 4 && *(int *)msg->data == -1 )
|
||||
{
|
||||
cls.last_received = cls.realtime;
|
||||
CL_ConnectionlessPacket( cls.from, msg );
|
||||
cls.netchan.last_received = cls.realtime;
|
||||
CL_ConnectionlessPacket( net_from, msg );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1271,14 +1268,14 @@ void CL_ReadNetMessage( void )
|
|||
|
||||
if( msg->cursize < 8 )
|
||||
{
|
||||
MsgDev( D_WARN, "%s: runt packet\n", NET_AdrToString( cls.from ));
|
||||
MsgDev( D_WARN, "%s: runt packet\n", NET_AdrToString( net_from ));
|
||||
continue;
|
||||
}
|
||||
|
||||
// packet from server
|
||||
if (!NET_CompareAdr( cls.from, cls.netchan.remote_address))
|
||||
if (!NET_CompareAdr( net_from, cls.netchan.remote_address))
|
||||
{
|
||||
MsgDev( D_WARN, "CL_ReadPackets: %s:sequenced packet without connection\n", NET_AdrToString( cls.from ));
|
||||
MsgDev( D_WARN, "CL_ReadPackets: %s:sequenced packet without connection\n", NET_AdrToString( net_from ));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1287,8 +1284,7 @@ void CL_ReadNetMessage( void )
|
|||
// the header is different lengths for reliable and unreliable messages
|
||||
int headerBytes = msg->readcount;
|
||||
|
||||
Msg("header bytes %d\n", headerBytes );
|
||||
cls.last_received = cls.realtime;
|
||||
cls.netchan.last_received = cls.realtime;
|
||||
CL_ParseServerMessage( msg );
|
||||
|
||||
// we don't know if it is ok to save a demo message until
|
||||
|
@ -1321,7 +1317,7 @@ void CL_CheckTimeout( void )
|
|||
// check timeout
|
||||
if( !cl_paused->integer && cls.state >= ca_connected && cls.state != ca_cinematic && !cls.demoplayback )
|
||||
{
|
||||
if( cls.realtime - cls.last_received > cl_timeout->integer * 1000 )
|
||||
if( cls.realtime - cls.netchan.last_received > cl_timeout->integer * 1000 )
|
||||
{
|
||||
if( ++cl.timeoutcount > 5 ) // timeoutcount saves debugger
|
||||
{
|
||||
|
@ -1334,6 +1330,26 @@ void CL_CheckTimeout( void )
|
|||
else cl.timeoutcount = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CL_SendCommand
|
||||
|
||||
==================
|
||||
*/
|
||||
void CL_SendCommand (void)
|
||||
{
|
||||
// get new key events
|
||||
CL_CheckTimeout();
|
||||
|
||||
// process console commands
|
||||
Cbuf_Execute();
|
||||
|
||||
// send intentions now
|
||||
CL_SendCmd();
|
||||
|
||||
// resend a connection request if necessary
|
||||
CL_CheckForResend();
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
|
@ -1343,14 +1359,24 @@ CL_Frame
|
|||
*/
|
||||
void CL_Frame( dword time )
|
||||
{
|
||||
static dword extratime;
|
||||
|
||||
if( host.type == HOST_DEDICATED )
|
||||
return;
|
||||
|
||||
// decide the simulation time
|
||||
cl.time += time;
|
||||
cls.realtime = Sys_Milliseconds(); //FIXME: teseing with += time;
|
||||
cls.frametime = time * 0.001;
|
||||
extratime += time;
|
||||
|
||||
if( cls.state == ca_connected && extratime < HOST_FRAMETIME )
|
||||
return; // don't flood packets out while connecting
|
||||
|
||||
// decide the simulation time
|
||||
cl.time += extratime;
|
||||
cls.realtime = Sys_Milliseconds(); //FIXME: teseing with += time;
|
||||
cls.frametime = extratime * 0.001;
|
||||
extratime = 0;
|
||||
|
||||
if( cls.frametime > (1.0 / 5)) cls.frametime = (1.0 / 5);
|
||||
|
||||
// setup the VM frame
|
||||
CL_VM_Begin();
|
||||
|
||||
|
@ -1361,10 +1387,7 @@ void CL_Frame( dword time )
|
|||
CL_CheckTimeout();
|
||||
|
||||
// send intentions now
|
||||
CL_SendCmd();
|
||||
|
||||
// resend a connection request if necessary
|
||||
CL_CheckForResend();
|
||||
CL_SendCommand();
|
||||
|
||||
// predict all unacknowledged movements
|
||||
CL_PredictMovement();
|
||||
|
|
|
@ -81,16 +81,14 @@ bool CL_CheckOrDownloadFile (char *filename)
|
|||
|
||||
// give the server an offset to start the download
|
||||
Msg ("Resuming %s\n", cls.downloadname);
|
||||
MSG_WriteByte (&cl.netmsg, clc_stringcmd);
|
||||
MSG_WriteString (&cl.netmsg, va("download %s %i", cls.downloadname, len));
|
||||
MSG_WriteByte( &cl.netmsg, clc_eof ); // end of message
|
||||
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
|
||||
MSG_WriteString (&cls.netchan.message, va("download %s %i", cls.downloadname, len));
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg ("Downloading %s\n", cls.downloadname);
|
||||
MSG_WriteByte (&cl.netmsg, clc_stringcmd);
|
||||
MSG_WriteString (&cl.netmsg, va("download %s", cls.downloadname));
|
||||
MSG_WriteByte( &cl.netmsg, clc_eof ); // end of message
|
||||
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
|
||||
MSG_WriteString (&cls.netchan.message, va("download %s", cls.downloadname));
|
||||
}
|
||||
|
||||
cls.downloadnumber++;
|
||||
|
@ -146,9 +144,8 @@ void CL_Download_f (void)
|
|||
FS_StripExtension (cls.downloadtempname);
|
||||
FS_DefaultExtension(cls.downloadtempname, ".tmp");
|
||||
|
||||
MSG_WriteByte (&cl.netmsg, clc_stringcmd);
|
||||
MSG_WriteString (&cl.netmsg, va("download %s", cls.downloadname));
|
||||
MSG_WriteByte( &cl.netmsg, clc_eof ); // end of message
|
||||
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
|
||||
MSG_WriteString (&cls.netchan.message, va("download %s", cls.downloadname));
|
||||
|
||||
cls.downloadnumber++;
|
||||
}
|
||||
|
@ -225,9 +222,8 @@ void CL_ParseDownload( sizebuf_t *msg )
|
|||
// request next block
|
||||
cls.downloadpercent = percent;
|
||||
|
||||
MSG_WriteByte (&cl.netmsg, clc_stringcmd);
|
||||
SZ_Print (&cl.netmsg, "nextdl");
|
||||
MSG_WriteByte( &cl.netmsg, clc_eof ); // end of message
|
||||
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
|
||||
SZ_Print (&cls.netchan.message, "nextdl");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -271,8 +267,6 @@ void CL_ParseServerData( sizebuf_t *msg )
|
|||
char *str;
|
||||
int i;
|
||||
|
||||
MsgDev(D_INFO, "Serverdata packet received.\n");
|
||||
|
||||
// wipe the client_t struct
|
||||
CL_ClearState ();
|
||||
cls.state = ca_connected;
|
||||
|
|
|
@ -32,14 +32,15 @@ void CL_CheckPredictionError (void)
|
|||
int delta[3];
|
||||
int len;
|
||||
|
||||
if (!cl_predict->value || (cl.frame.playerstate.pm_flags & PMF_NO_PREDICTION))
|
||||
if (!cl_predict->value || (cl.frame.ps.pm_flags & PMF_NO_PREDICTION))
|
||||
return;
|
||||
|
||||
// calculate the last usercmd_t we sent that the server has processed
|
||||
frame = cl.cmd_number & CMD_MASK;
|
||||
frame = cls.netchan.incoming_acknowledged;
|
||||
frame &= (CMD_BACKUP-1);
|
||||
|
||||
// compare what the server returned with what we had predicted it to be
|
||||
VectorSubtract (cl.frame.playerstate.origin, cl.predicted_origins[frame], delta);
|
||||
VectorSubtract (cl.frame.ps.origin, cl.predicted_origins[frame], delta);
|
||||
|
||||
// save the prediction error for interpolation
|
||||
len = abs(delta[0]) + abs(delta[1]) + abs(delta[2]);
|
||||
|
@ -52,7 +53,7 @@ void CL_CheckPredictionError (void)
|
|||
if (cl_showmiss->value && (delta[0] || delta[1] || delta[2]))
|
||||
Msg ("prediction miss on %i: %i\n", cl.frame.serverframe, delta[0] + delta[1] + delta[2]);
|
||||
|
||||
VectorCopy (cl.frame.playerstate.origin, cl.predicted_origins[frame]);
|
||||
VectorCopy (cl.frame.ps.origin, cl.predicted_origins[frame]);
|
||||
|
||||
// save for error itnerpolation
|
||||
VectorScale( delta, CL_COORD_FRAC, cl.prediction_error );
|
||||
|
@ -189,18 +190,18 @@ void CL_PredictMovement (void)
|
|||
if(cls.state != ca_active) return;
|
||||
if(cl_paused->value) return;
|
||||
|
||||
if (!cl_predict->value || (cl.frame.playerstate.pm_flags & PMF_NO_PREDICTION))
|
||||
if (!cl_predict->value || (cl.frame.ps.pm_flags & PMF_NO_PREDICTION))
|
||||
{
|
||||
// just set angles
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
cl.predicted_angles[i] = cl.viewangles[i] + SHORT2ANGLE(cl.frame.playerstate.delta_angles[i]);
|
||||
cl.predicted_angles[i] = cl.viewangles[i] + SHORT2ANGLE(cl.frame.ps.delta_angles[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ack = cl.cmd_number & CMD_MASK;
|
||||
current = cl.cmd_number;
|
||||
ack = cls.netchan.incoming_acknowledged;
|
||||
current = cls.netchan.outgoing_sequence;
|
||||
|
||||
// if we are too far out of date, just freeze
|
||||
if (current - ack >= CMD_BACKUP)
|
||||
|
@ -214,7 +215,7 @@ void CL_PredictMovement (void)
|
|||
memset (&pm, 0, sizeof(pm));
|
||||
pm.trace = CL_PMTrace;
|
||||
pm.pointcontents = CL_PMpointcontents;
|
||||
pm.ps = cl.frame.playerstate;
|
||||
pm.ps = cl.frame.ps;
|
||||
|
||||
// SCR_DebugGraph (current - ack - 1, COLOR_0);
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ void CL_DrawHUD( void )
|
|||
if(!prog) return; // too early (just skip one frame)
|
||||
|
||||
// setup pparms
|
||||
prog->globals.cl->health = cl.frame.playerstate.stats[STAT_HEALTH];
|
||||
prog->globals.cl->health = cl.frame.ps.stats[STAT_HEALTH];
|
||||
prog->globals.cl->maxclients = com.atoi(cl.configstrings[CS_MAXCLIENTS]);
|
||||
prog->globals.cl->realtime = cls.realtime * 0.001f;
|
||||
prog->globals.cl->paused = cl_paused->integer;
|
||||
|
@ -70,7 +70,7 @@ bool CL_ParseUserMessage( int svc_number )
|
|||
bool msg_parsed = false;
|
||||
|
||||
// setup pparms
|
||||
prog->globals.cl->health = cl.frame.playerstate.stats[STAT_HEALTH];
|
||||
prog->globals.cl->health = cl.frame.ps.stats[STAT_HEALTH];
|
||||
prog->globals.cl->maxclients = com.atoi(cl.configstrings[CS_MAXCLIENTS]);
|
||||
prog->globals.cl->realtime = cls.realtime * 0.001f;
|
||||
prog->globals.cl->paused = cl_paused->integer;
|
||||
|
|
|
@ -460,7 +460,7 @@ void V_RenderView( void )
|
|||
cl.refdef.dlights = r_dlights;
|
||||
cl.refdef.lightstyles = r_lightstyles;
|
||||
|
||||
cl.refdef.rdflags = cl.frame.playerstate.effects;
|
||||
cl.refdef.rdflags = cl.frame.ps.effects;
|
||||
|
||||
// sort entities for better cache locality
|
||||
qsort( cl.refdef.entities, cl.refdef.num_entities, sizeof( cl.refdef.entities[0] ), (int (*)(const void *, const void *))entitycmpfnc );
|
||||
|
|
|
@ -34,13 +34,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
typedef struct
|
||||
{
|
||||
bool valid; // cleared if delta parsing was invalid
|
||||
int serverframe;
|
||||
int servertime; // server time the message is valid for (in msec)
|
||||
int deltaframe;
|
||||
byte areabits[MAX_MAP_AREAS/8]; // portalarea visibility bits
|
||||
player_state_t playerstate;
|
||||
int num_entities;
|
||||
int parse_entities; // non-masked index into cl_parse_entities array
|
||||
int serverframe;
|
||||
int servertime; // server time the message is valid for (in msec)
|
||||
int deltaframe;
|
||||
byte areabits[MAX_MAP_AREAS/8]; // portalarea visibility bits
|
||||
int num_entities;
|
||||
int parse_entities; // non-masked index into cl_parse_entities array
|
||||
player_state_t ps;
|
||||
} frame_t;
|
||||
|
||||
// console stuff
|
||||
|
@ -100,10 +100,6 @@ typedef struct
|
|||
frame_t frames[UPDATE_BACKUP];
|
||||
outpacket_t packets[PACKET_BACKUP]; // information about each packet we have sent out
|
||||
|
||||
// network channel to server
|
||||
sizebuf_t netmsg;
|
||||
byte netbuf[MAX_MSGLEN];
|
||||
|
||||
// mouse current position
|
||||
int mouse_x[2];
|
||||
int mouse_y[2];
|
||||
|
@ -217,9 +213,6 @@ typedef struct
|
|||
float connect_time; // for connection retransmits
|
||||
// to work around address translating routers
|
||||
netchan_t netchan; // network channel from server
|
||||
netadr_t from;
|
||||
sizebuf_t netmsg;
|
||||
byte netbuf[MAX_MSGLEN];
|
||||
int serverProtocol; // in case we are doing some kind of version hack
|
||||
sizebuf_t *multicast; // ptr for current message buffer (net or demo flow)
|
||||
|
||||
|
@ -242,9 +235,6 @@ typedef struct
|
|||
int numservers;
|
||||
int pingtime; // servers timebase
|
||||
|
||||
int last_received; // for retransmits
|
||||
int last_sent; // last sending message
|
||||
|
||||
// cursor mouse pos for uimenu
|
||||
int mouse_x;
|
||||
int mouse_y;
|
||||
|
|
|
@ -175,7 +175,8 @@ typedef struct host_redirect_s
|
|||
int target;
|
||||
char *buffer;
|
||||
int buffersize;
|
||||
void (*flush)(int target, char *buffer);
|
||||
netadr_t address;
|
||||
void (*flush)( netadr_t adr, int target, char *buffer );
|
||||
} host_redirect_t;
|
||||
|
||||
typedef struct host_parm_s
|
||||
|
|
|
@ -31,13 +31,6 @@ packet header (quake2)
|
|||
1 acknowledge receipt of even/odd message
|
||||
16 qport
|
||||
|
||||
packet header (quake3)
|
||||
-------------
|
||||
4 outgoing sequence. high bit will be set if this is a fragmented message
|
||||
[2 qport (only for client to server)]
|
||||
[2 fragment start byte]
|
||||
[2 fragment length. if < FRAGMENT_SIZE, this is the last fragment]
|
||||
|
||||
if the sequence number is -1, the packet should be handled as an out-of-band
|
||||
message instead of as part of a netcon.
|
||||
|
||||
|
@ -107,52 +100,44 @@ void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport )
|
|||
chan->qport = qport;
|
||||
chan->incoming_sequence = 0;
|
||||
chan->outgoing_sequence = 1;
|
||||
chan->last_received = Sys_Milliseconds();
|
||||
|
||||
SZ_Init( &chan->message, chan->message_buf, sizeof(chan->message_buf));
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Netchan_TransmitNextFragment
|
||||
===============
|
||||
Netchan_CanReliable
|
||||
|
||||
Send one fragment of the current message
|
||||
=================
|
||||
Returns true if the last reliable message has acked
|
||||
================
|
||||
*/
|
||||
void Netchan_TransmitNextFragment( netchan_t *chan )
|
||||
bool Netchan_CanReliable( netchan_t *chan )
|
||||
{
|
||||
sizebuf_t send;
|
||||
byte send_buf[MAX_PACKETLEN];
|
||||
int fragment_length;
|
||||
if( chan->reliable_length )
|
||||
return false; // waiting for ack
|
||||
return true;
|
||||
}
|
||||
|
||||
// write the packet header
|
||||
SZ_Init( &send, send_buf, sizeof(send_buf));
|
||||
MSG_WriteLong( &send, chan->outgoing_sequence | FRAGMENT_BIT );
|
||||
|
||||
// send the qport if we are a client
|
||||
if( chan->sock == NS_CLIENT )
|
||||
bool Netchan_NeedReliable( netchan_t *chan )
|
||||
{
|
||||
bool send_reliable;
|
||||
|
||||
// if the remote side dropped the last reliable message, resend it
|
||||
send_reliable = false;
|
||||
|
||||
if (chan->incoming_acknowledged > chan->last_reliable_sequence
|
||||
&& chan->incoming_reliable_acknowledged != chan->reliable_sequence)
|
||||
send_reliable = true;
|
||||
|
||||
// if the reliable transmit buffer is empty, copy the current message out
|
||||
if( !chan->reliable_length && chan->message.cursize )
|
||||
{
|
||||
MSG_WriteShort( &send, qport->integer );
|
||||
send_reliable = true;
|
||||
}
|
||||
|
||||
// copy the reliable message to the packet first
|
||||
fragment_length = FRAGMENT_SIZE;
|
||||
if( chan->unsent_fragment_start + fragment_length > chan->unsent_length )
|
||||
fragment_length = chan->unsent_length - chan->unsent_fragment_start;
|
||||
|
||||
MSG_WriteShort( &send, chan->unsent_fragment_start );
|
||||
MSG_WriteShort( &send, fragment_length );
|
||||
MSG_WriteData( &send, chan->unsent_buffer + chan->unsent_fragment_start, fragment_length );
|
||||
|
||||
// send the datagram
|
||||
NET_SendPacket( chan->sock, send.cursize, send.data, chan->remote_address );
|
||||
|
||||
if( showpackets->integer )
|
||||
MsgDev( D_INFO, "%s send %4i : s=%i fragment=%i,%i\n", netsrcString[chan->sock], send.cursize, chan->outgoing_sequence, chan->unsent_fragment_start, fragment_length );
|
||||
|
||||
chan->unsent_fragment_start += fragment_length;
|
||||
if ( chan->unsent_fragment_start == chan->unsent_length && fragment_length != FRAGMENT_SIZE )
|
||||
{
|
||||
chan->outgoing_sequence++;
|
||||
chan->unsent_fragments = false;
|
||||
}
|
||||
return send_reliable;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -166,36 +151,74 @@ A 0 length will still generate a packet.
|
|||
void Netchan_Transmit( netchan_t *chan, int length, const byte *data )
|
||||
{
|
||||
sizebuf_t send;
|
||||
byte send_buf[MAX_PACKETLEN];
|
||||
byte send_buf[MAX_MSGLEN];
|
||||
bool send_reliable;
|
||||
uint w1, w2;
|
||||
|
||||
if( length > MAX_MSGLEN ) Host_Error( "Netchan_Transmit: %i > MAX_MSGLEN\n", length );
|
||||
chan->unsent_fragment_start = 0;
|
||||
|
||||
// fragment large reliable messages
|
||||
if( length >= FRAGMENT_SIZE )
|
||||
// check for message overflow
|
||||
if (chan->message.overflowed)
|
||||
{
|
||||
chan->unsent_fragments = true;
|
||||
chan->unsent_length = length;
|
||||
Mem_Copy( chan->unsent_buffer, data, length );
|
||||
// only send the first fragment now
|
||||
Msg("netchan transmit nextfragment %d\n", length );
|
||||
Netchan_TransmitNextFragment( chan );
|
||||
Host_Error( "%s:Outgoing message overflow\n", NET_AdrToString (chan->remote_address));
|
||||
return;
|
||||
}
|
||||
|
||||
send_reliable = Netchan_NeedReliable (chan);
|
||||
|
||||
if (!chan->reliable_length && chan->message.cursize)
|
||||
{
|
||||
memcpy (chan->reliable_buf, chan->message_buf, chan->message.cursize);
|
||||
chan->reliable_length = chan->message.cursize;
|
||||
chan->message.cursize = 0;
|
||||
chan->reliable_sequence ^= 1;
|
||||
}
|
||||
|
||||
|
||||
// write the packet header
|
||||
SZ_Init( &send, send_buf, sizeof(send_buf));
|
||||
MSG_WriteLong( &send, chan->outgoing_sequence );
|
||||
SZ_Init (&send, send_buf, sizeof(send_buf));
|
||||
|
||||
w1 = ( chan->outgoing_sequence & ~(1<<31) ) | (send_reliable<<31);
|
||||
w2 = ( chan->incoming_sequence & ~(1<<31) ) | (chan->incoming_reliable_sequence<<31);
|
||||
|
||||
chan->outgoing_sequence++;
|
||||
chan->last_sent = Sys_Milliseconds();
|
||||
|
||||
MSG_WriteLong (&send, w1);
|
||||
MSG_WriteLong (&send, w2);
|
||||
|
||||
// send the qport if we are a client
|
||||
if( chan->sock == NS_CLIENT ) MSG_WriteWord( &send, qport->integer );
|
||||
if (chan->sock == NS_CLIENT) MSG_WriteWord (&send, qport->value);
|
||||
|
||||
MSG_WriteData( &send, data, length );
|
||||
NET_SendPacket( chan->sock, send.cursize, send.data, chan->remote_address ); // send the datagram
|
||||
// copy the reliable message to the packet first
|
||||
if (send_reliable)
|
||||
{
|
||||
SZ_Write (&send, chan->reliable_buf, chan->reliable_length);
|
||||
chan->last_reliable_sequence = chan->outgoing_sequence;
|
||||
}
|
||||
|
||||
// add the unreliable part if space is available
|
||||
if (send.maxsize - send.cursize >= length)
|
||||
SZ_Write (&send, data, length);
|
||||
else MsgDev( D_WARN, "Netchan_Transmit: dumped unreliable\n");
|
||||
|
||||
if( showpackets->integer )
|
||||
MsgDev( D_INFO, "%s send %4i : s=%i ack=%i\n", netsrcString[chan->sock], send.cursize, chan->outgoing_sequence - 1, chan->incoming_sequence );
|
||||
// send the datagram
|
||||
NET_SendPacket (chan->sock, send.cursize, send.data, chan->remote_address);
|
||||
|
||||
if (showpackets->value)
|
||||
{
|
||||
if (send_reliable)
|
||||
Msg ("send %4i : s=%i reliable=%i ack=%i rack=%i\n"
|
||||
, send.cursize
|
||||
, chan->outgoing_sequence - 1
|
||||
, chan->reliable_sequence
|
||||
, chan->incoming_sequence
|
||||
, chan->incoming_reliable_sequence);
|
||||
else
|
||||
Msg ("send %4i : s=%i ack=%i rack=%i\n"
|
||||
, send.cursize
|
||||
, chan->outgoing_sequence - 1
|
||||
, chan->incoming_sequence
|
||||
, chan->incoming_reliable_sequence);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -212,111 +235,82 @@ copied out.
|
|||
*/
|
||||
bool Netchan_Process( netchan_t *chan, sizebuf_t *msg )
|
||||
{
|
||||
int sequence;
|
||||
uint sequence, sequence_ack;
|
||||
uint reliable_ack, reliable_message;
|
||||
int qport;
|
||||
int fragment_start = 0, fragment_length = 0;
|
||||
bool fragmented = false;
|
||||
|
||||
// get sequence numbers
|
||||
MSG_BeginReading( msg );
|
||||
sequence = MSG_ReadLong( msg );
|
||||
|
||||
// check for fragment information
|
||||
if( sequence & FRAGMENT_BIT )
|
||||
{
|
||||
sequence &= ~FRAGMENT_BIT;
|
||||
fragmented = true;
|
||||
}
|
||||
MSG_BeginReading (msg);
|
||||
sequence = MSG_ReadLong (msg);
|
||||
sequence_ack = MSG_ReadLong (msg);
|
||||
|
||||
// read the qport if we are a server
|
||||
if( chan->sock == NS_SERVER )
|
||||
qport = MSG_ReadShort( msg );
|
||||
if (chan->sock == NS_SERVER)
|
||||
qport = MSG_ReadShort (msg);
|
||||
|
||||
// read the fragment information
|
||||
if( fragmented )
|
||||
reliable_message = sequence >> 31;
|
||||
reliable_ack = sequence_ack >> 31;
|
||||
|
||||
sequence &= ~(1<<31);
|
||||
sequence_ack &= ~(1<<31);
|
||||
|
||||
if (showpackets->value)
|
||||
{
|
||||
fragment_start = MSG_ReadShort( msg );
|
||||
fragment_length = MSG_ReadShort( msg );
|
||||
if (reliable_message)
|
||||
Msg ("recv %4i : s=%i reliable=%i ack=%i rack=%i\n"
|
||||
, msg->cursize
|
||||
, sequence
|
||||
, chan->incoming_reliable_sequence ^ 1
|
||||
, sequence_ack
|
||||
, reliable_ack);
|
||||
else
|
||||
Msg ("recv %4i : s=%i ack=%i rack=%i\n"
|
||||
, msg->cursize
|
||||
, sequence
|
||||
, sequence_ack
|
||||
, reliable_ack);
|
||||
}
|
||||
|
||||
if( showpackets->integer )
|
||||
// discard stale or duplicated packets
|
||||
if (sequence <= chan->incoming_sequence)
|
||||
{
|
||||
if( fragmented )
|
||||
MsgDev( D_INFO, "%s recv %4i : s=%i fragment=%i,%i\n", netsrcString[chan->sock], msg->cursize, sequence, fragment_start, fragment_length );
|
||||
else MsgDev( D_INFO, "%s recv %4i : s=%i\n", netsrcString[chan->sock], msg->cursize, sequence );
|
||||
}
|
||||
|
||||
// discard out of order or duplicated packets
|
||||
if( sequence <= chan->incoming_sequence )
|
||||
{
|
||||
if( showdrop->integer || showpackets->integer )
|
||||
MsgDev( D_INFO, "%s:Out of order packet %i at %i\n", NET_AdrToString(chan->remote_address), sequence, chan->incoming_sequence );
|
||||
if (showdrop->value)
|
||||
Msg ("%s:Out of order packet %i at %i\n"
|
||||
, NET_AdrToString (chan->remote_address)
|
||||
, sequence
|
||||
, chan->incoming_sequence);
|
||||
return false;
|
||||
}
|
||||
|
||||
// dropped packets don't keep the message from being used
|
||||
chan->dropped = sequence - (chan->incoming_sequence + 1);
|
||||
if( chan->dropped > 0 )
|
||||
chan->dropped = sequence - (chan->incoming_sequence+1);
|
||||
if (chan->dropped > 0)
|
||||
{
|
||||
if( showdrop->integer || showpackets->integer )
|
||||
MsgDev( D_INFO, "%s:Dropped %i packets at %i\n", NET_AdrToString( chan->remote_address ), chan->dropped, sequence );
|
||||
if (showdrop->value)
|
||||
Msg ("%s:Dropped %i packets at %i\n"
|
||||
, NET_AdrToString (chan->remote_address)
|
||||
, chan->dropped
|
||||
, sequence);
|
||||
}
|
||||
|
||||
//
|
||||
// if the current outgoing reliable message has been acknowledged
|
||||
// clear the buffer to make way for the next
|
||||
//
|
||||
if (reliable_ack == chan->reliable_sequence)
|
||||
chan->reliable_length = 0; // it has been received
|
||||
|
||||
|
||||
// if this is the final framgent of a reliable message, bump incoming_reliable_sequence
|
||||
if( fragmented )
|
||||
{
|
||||
if( sequence != chan->fragment_sequence )
|
||||
{
|
||||
chan->fragment_sequence = sequence;
|
||||
chan->fragment_length = 0;
|
||||
}
|
||||
// if we missed a fragment, dump the message
|
||||
if( fragment_start != chan->fragment_length )
|
||||
{
|
||||
if( showdrop->integer || showpackets->integer )
|
||||
MsgDev( D_INFO, "%s:Dropped a message fragment\n", NET_AdrToString( chan->remote_address ), sequence);
|
||||
return false;
|
||||
}
|
||||
|
||||
// copy the fragment to the fragment buffer
|
||||
if( fragment_length < 0 || msg->readcount + fragment_length > msg->cursize || chan->fragment_length + fragment_length > sizeof( chan->fragment_buffer ))
|
||||
{
|
||||
if( showdrop->integer || showpackets->integer )
|
||||
MsgDev( D_INFO, "%s:illegal fragment length\n", NET_AdrToString (chan->remote_address ));
|
||||
return false;
|
||||
}
|
||||
|
||||
Mem_Copy( chan->fragment_buffer + chan->fragment_length, msg->data + msg->readcount, fragment_length );
|
||||
chan->fragment_length += fragment_length;
|
||||
|
||||
// if this wasn't the last fragment, don't process anything
|
||||
if( fragment_length == FRAGMENT_SIZE )
|
||||
return false;
|
||||
|
||||
if( chan->fragment_length > msg->maxsize )
|
||||
{
|
||||
MsgDev( D_INFO, "%s:fragmentLength %i > msg->maxsize\n", NET_AdrToString (chan->remote_address ), chan->fragment_length );
|
||||
return false;
|
||||
}
|
||||
|
||||
// copy the full message over the partial fragment
|
||||
// make sure the sequence number is still there
|
||||
*(int *)msg->data = LittleLong( sequence );
|
||||
|
||||
Mem_Copy( msg->data + 4, chan->fragment_buffer, chan->fragment_length );
|
||||
msg->cursize = chan->fragment_length + 4;
|
||||
chan->fragment_length = 0;
|
||||
msg->readcount = 4; // past the sequence number
|
||||
msg->bit = 32; // past the sequence number
|
||||
|
||||
// clients were not acking fragmented messages
|
||||
chan->incoming_sequence = sequence;
|
||||
return true;
|
||||
}
|
||||
// the message can now be read from the current message pointer
|
||||
// if this message contains a reliable message, bump incoming_reliable_sequence
|
||||
chan->incoming_sequence = sequence;
|
||||
chan->incoming_acknowledged = sequence_ack;
|
||||
chan->incoming_reliable_acknowledged = reliable_ack;
|
||||
if (reliable_message)
|
||||
{
|
||||
chan->incoming_reliable_sequence ^= 1;
|
||||
}
|
||||
|
||||
// the message can now be read from the current message pointer
|
||||
chan->last_received = Sys_Milliseconds();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -162,15 +162,15 @@ void _MSG_WriteDeltaUsercmd (sizebuf_t *buf, usercmd_t *from, usercmd_t *cmd, co
|
|||
|
||||
_MSG_WriteByte (buf, bits, filename, fileline );
|
||||
|
||||
if (bits & CM_ANGLE1) _MSG_WriteShort (buf, cmd->angles[0], filename, fileline );
|
||||
if (bits & CM_ANGLE2) _MSG_WriteShort (buf, cmd->angles[1], filename, fileline );
|
||||
if (bits & CM_ANGLE3) _MSG_WriteShort (buf, cmd->angles[2], filename, fileline );
|
||||
if (bits & CM_ANGLE1) _MSG_WriteLong (buf, cmd->angles[0], filename, fileline );
|
||||
if (bits & CM_ANGLE2) _MSG_WriteLong (buf, cmd->angles[1], filename, fileline );
|
||||
if (bits & CM_ANGLE3) _MSG_WriteLong (buf, cmd->angles[2], filename, fileline );
|
||||
|
||||
if (bits & CM_FORWARD) _MSG_WriteShort (buf, cmd->forwardmove, filename, fileline );
|
||||
if (bits & CM_SIDE) _MSG_WriteShort (buf, cmd->sidemove, filename, fileline );
|
||||
if (bits & CM_UP) _MSG_WriteShort (buf, cmd->upmove, filename, fileline );
|
||||
if (bits & CM_FORWARD) _MSG_WriteChar (buf, cmd->forwardmove, filename, fileline );
|
||||
if (bits & CM_SIDE) _MSG_WriteChar (buf, cmd->sidemove, filename, fileline );
|
||||
if (bits & CM_UP) _MSG_WriteChar (buf, cmd->upmove, filename, fileline );
|
||||
|
||||
if (bits & CM_BUTTONS) _MSG_WriteByte (buf, cmd->buttons, filename, fileline );
|
||||
if (bits & CM_BUTTONS) _MSG_WriteLong (buf, cmd->buttons, filename, fileline );
|
||||
if (bits & CM_IMPULSE) _MSG_WriteByte (buf, cmd->impulse, filename, fileline );
|
||||
|
||||
_MSG_WriteLong (buf, cmd->servertime, filename, fileline );
|
||||
|
@ -487,17 +487,17 @@ void MSG_ReadDeltaUsercmd (sizebuf_t *msg_read, usercmd_t *from, usercmd_t *move
|
|||
Mem_Copy (move, from, sizeof(*move));
|
||||
|
||||
// read current angles
|
||||
if (bits & CM_ANGLE1) move->angles[0] = MSG_ReadShort (msg_read);
|
||||
if (bits & CM_ANGLE2) move->angles[1] = MSG_ReadShort (msg_read);
|
||||
if (bits & CM_ANGLE3) move->angles[2] = MSG_ReadShort (msg_read);
|
||||
if (bits & CM_ANGLE1) move->angles[0] = MSG_ReadLong (msg_read);
|
||||
if (bits & CM_ANGLE2) move->angles[1] = MSG_ReadLong (msg_read);
|
||||
if (bits & CM_ANGLE3) move->angles[2] = MSG_ReadLong (msg_read);
|
||||
|
||||
// read movement
|
||||
if (bits & CM_FORWARD) move->forwardmove = MSG_ReadShort (msg_read);
|
||||
if (bits & CM_SIDE) move->sidemove = MSG_ReadShort (msg_read);
|
||||
if (bits & CM_UP) move->upmove = MSG_ReadShort (msg_read);
|
||||
if (bits & CM_FORWARD) move->forwardmove = MSG_ReadChar (msg_read);
|
||||
if (bits & CM_SIDE) move->sidemove = MSG_ReadChar (msg_read);
|
||||
if (bits & CM_UP) move->upmove = MSG_ReadChar (msg_read);
|
||||
|
||||
// read buttons
|
||||
if (bits & CM_BUTTONS) move->buttons = MSG_ReadByte (msg_read);
|
||||
if (bits & CM_BUTTONS) move->buttons = MSG_ReadLong (msg_read);
|
||||
if (bits & CM_IMPULSE) move->impulse = MSG_ReadByte (msg_read);
|
||||
|
||||
move->servertime = MSG_ReadLong (msg_read); // read time to run command
|
||||
|
|
|
@ -66,7 +66,7 @@ typedef enum
|
|||
|
||||
typedef struct
|
||||
{
|
||||
int cmdnumber; // cl.cmdnumber when packet was sent
|
||||
int cmd_number; // cl.cmdnumber when packet was sent
|
||||
int servertime; // usercmd->servertime when packet was sent
|
||||
int realtime; // cls.realtime when packet was sent
|
||||
} outpacket_t;
|
||||
|
@ -75,22 +75,23 @@ typedef struct
|
|||
#define PS_M_ORIGIN (1<<1)
|
||||
#define PS_M_VELOCITY (1<<2)
|
||||
#define PS_M_TIME (1<<3)
|
||||
#define PS_M_FLAGS (1<<4)
|
||||
#define PS_M_GRAVITY (1<<5)
|
||||
#define PS_M_DELTA_ANGLES (1<<6)
|
||||
#define PS_VIEWOFFSET (1<<7)
|
||||
#define PS_VIEWANGLES (1<<8)
|
||||
#define PS_KICKANGLES (1<<9)
|
||||
#define PS_BLEND (1<<10)
|
||||
#define PS_FOV (1<<11)
|
||||
#define PS_WEAPONINDEX (1<<12)
|
||||
#define PS_WEAPONOFFSET (1<<13)
|
||||
#define PS_WEAPONANGLES (1<<14)
|
||||
#define PS_WEAPONFRAME (1<<15)
|
||||
#define PS_WEAPONSEQUENCE (1<<16)
|
||||
#define PS_WEAPONBODY (1<<17)
|
||||
#define PS_WEAPONSKIN (1<<18)
|
||||
#define PS_RDFLAGS (1<<19)
|
||||
#define PS_M_COMMANDMSEC (1<<4)
|
||||
#define PS_M_FLAGS (1<<5)
|
||||
#define PS_M_GRAVITY (1<<6)
|
||||
#define PS_M_DELTA_ANGLES (1<<7)
|
||||
#define PS_VIEWOFFSET (1<<8)
|
||||
#define PS_VIEWANGLES (1<<9)
|
||||
#define PS_KICKANGLES (1<<10)
|
||||
#define PS_BLEND (1<<11)
|
||||
#define PS_FOV (1<<12)
|
||||
#define PS_WEAPONINDEX (1<<13)
|
||||
#define PS_WEAPONOFFSET (1<<14)
|
||||
#define PS_WEAPONANGLES (1<<15)
|
||||
#define PS_WEAPONFRAME (1<<16)
|
||||
#define PS_WEAPONSEQUENCE (1<<17)
|
||||
#define PS_WEAPONBODY (1<<18)
|
||||
#define PS_WEAPONSKIN (1<<19)
|
||||
#define PS_RDFLAGS (1<<20)
|
||||
|
||||
// ms and light always sent, the others are optional
|
||||
#define CM_ANGLE1 (1<<0)
|
||||
|
@ -328,27 +329,33 @@ bool NET_IsLocalAddress( netadr_t adr );
|
|||
//============================================================================
|
||||
typedef struct netchan_s
|
||||
{
|
||||
netsrc_t sock;
|
||||
int dropped; // between last packet and previous
|
||||
netadr_t remote_address;
|
||||
int qport; // qport value to write when transmitting
|
||||
netsrc_t sock;
|
||||
int dropped; // between last packet and previous
|
||||
netadr_t remote_address;
|
||||
|
||||
int last_received; // for timeouts
|
||||
int last_sent; // for retransmits
|
||||
|
||||
int qport; // qport value to write when transmitting
|
||||
|
||||
// sequencing variables
|
||||
int incoming_sequence;
|
||||
int outgoing_sequence;
|
||||
int incoming_sequence;
|
||||
int incoming_acknowledged;
|
||||
int incoming_reliable_acknowledged; // single bit
|
||||
|
||||
// incoming fragment assembly buffer
|
||||
int fragment_sequence;
|
||||
int fragment_length;
|
||||
byte fragment_buffer[MAX_MSGLEN];
|
||||
int incoming_reliable_sequence; // single bit, maintained local
|
||||
|
||||
// outgoing fragment buffer
|
||||
// we need to space out the sending of large fragmented messages
|
||||
bool unsent_fragments;
|
||||
int unsent_fragment_start;
|
||||
int unsent_length;
|
||||
byte unsent_buffer[MAX_MSGLEN];
|
||||
int outgoing_sequence;
|
||||
int reliable_sequence; // single bit
|
||||
int last_reliable_sequence; // sequence number of last send
|
||||
|
||||
// reliable staging and holding areas
|
||||
sizebuf_t message; // writing buffer to send to server
|
||||
byte message_buf[MAX_MSGLEN-16]; // leave space for header
|
||||
|
||||
// message is copied to this buffer when it is first transfered
|
||||
int reliable_length;
|
||||
byte reliable_buf[MAX_MSGLEN-16]; // unacked reliable message
|
||||
} netchan_t;
|
||||
|
||||
#define PROTOCOL_VERSION 35
|
||||
|
|
|
@ -633,7 +633,7 @@ void Host_Print( const char *txt )
|
|||
{
|
||||
if(host.rd.flush)
|
||||
{
|
||||
host.rd.flush(host.rd.target, host.rd.buffer);
|
||||
host.rd.flush( host.rd.address, host.rd.target, host.rd.buffer);
|
||||
*host.rd.buffer = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ typedef enum
|
|||
|
||||
typedef enum
|
||||
{
|
||||
cs_free, // can be reused for a new connection
|
||||
cs_free = 0, // can be reused for a new connection
|
||||
cs_zombie, // client has been disconnected, but don't reuse connection for a couple seconds
|
||||
cs_connected, // has been assigned to a sv_client_t, but not in game yet
|
||||
cs_spawned // client is fully in game
|
||||
|
@ -115,12 +115,12 @@ typedef struct sv_client_s
|
|||
usercmd_t lastcmd; // for filling in big drops
|
||||
usercmd_t ucmd; // current user commands
|
||||
|
||||
netchan_t netchan; // network channel
|
||||
sizebuf_t netmsg; // network message queue
|
||||
byte netbuf[MAX_MSGLEN];
|
||||
|
||||
int commandMsec; // every seconds this is reset, if user
|
||||
// commands exhaust it, assume time cheating
|
||||
// The datagram is written to by sound calls, prints, temp ents, etc.
|
||||
// It can be harmlessly overflowed.
|
||||
sizebuf_t datagram;
|
||||
byte datagram_buf[MAX_MSGLEN];
|
||||
|
||||
int frame_latency[LATENCY_COUNTS];
|
||||
int ping;
|
||||
|
@ -141,9 +141,10 @@ typedef struct sv_client_s
|
|||
|
||||
int lastmessage; // sv.framenum when packet was last received
|
||||
int lastconnect;
|
||||
int nextmsgtime; // time of next message to client
|
||||
|
||||
int challenge; // challenge of this user, randomly generated
|
||||
|
||||
netchan_t netchan; // network channel
|
||||
} sv_client_t;
|
||||
|
||||
/*
|
||||
|
@ -185,10 +186,6 @@ typedef struct
|
|||
entity_state_t *client_entities; // [num_client_entities]
|
||||
|
||||
int last_heartbeat;
|
||||
netadr_t redirect_address; // using for redirect command
|
||||
netadr_t from;
|
||||
sizebuf_t netmsg;
|
||||
byte netbuf[MAX_MSGLEN];
|
||||
|
||||
challenge_t challenges[MAX_CHALLENGES]; // to prevent invalid IPs from connecting
|
||||
} server_static_t;
|
||||
|
@ -265,7 +262,7 @@ typedef enum {RD_NONE, RD_CLIENT, RD_PACKET} redirect_t;
|
|||
|
||||
extern char sv_outputbuf[SV_OUTPUTBUF_LENGTH];
|
||||
|
||||
void SV_FlushRedirect (int sv_redirected, char *outputbuf);
|
||||
void SV_FlushRedirect( netadr_t adr, int sv_redirected, char *outputbuf );
|
||||
|
||||
void SV_SendClientMessages (void);
|
||||
void SV_AmbientSound( edict_t *entity, int soundindex, float volume, float attenuation );
|
||||
|
|
|
@ -154,8 +154,8 @@ void SV_DirectConnect( netadr_t from )
|
|||
}
|
||||
if( !newcl )
|
||||
{
|
||||
Netchan_OutOfBandPrint (NS_SERVER, from, "print\nServer is full.\n");
|
||||
MsgDev(D_INFO, "SVC_DirectConnect: rejected a connection.\n");
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, "print\nServer is full.\n" );
|
||||
MsgDev( D_INFO, "SVC_DirectConnect: rejected a connection.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -186,13 +186,15 @@ gotnewcl:
|
|||
com.strncpy( newcl->userinfo, userinfo, sizeof(newcl->userinfo) - 1);
|
||||
SV_UserinfoChanged( newcl );
|
||||
|
||||
// send the connect packet to the client
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, "client_connect" );
|
||||
|
||||
Netchan_Setup( NS_SERVER, &newcl->netchan, from, qport );
|
||||
SZ_Init( &newcl->netmsg, newcl->netbuf, sizeof( newcl->netbuf ));
|
||||
SZ_Init( &newcl->datagram, newcl->datagram_buf, sizeof(newcl->datagram_buf));
|
||||
|
||||
newcl->state = cs_connected;
|
||||
newcl->lastmessage = svs.realtime;
|
||||
newcl->lastconnect = svs.realtime;
|
||||
newcl->nextmsgtime = svs.realtime;
|
||||
|
||||
// if this was the first client on the server, or the last client
|
||||
// the server can hold, send a heartbeat to the master.
|
||||
|
@ -200,9 +202,6 @@ gotnewcl:
|
|||
if( cl->state >= cs_connected ) count++;
|
||||
if( count == 1 || count == maxclients->integer )
|
||||
svs.last_heartbeat = MAX_HEARTBEAT;
|
||||
|
||||
// send the connect packet to the client
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, "client_connect" );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -222,7 +221,7 @@ void SV_DropClient( sv_client_t *drop )
|
|||
return; // already dropped
|
||||
|
||||
// add the disconnect
|
||||
MSG_WriteByte( &drop->netmsg, svc_disconnect );
|
||||
MSG_WriteByte( &drop->netchan.message, svc_disconnect );
|
||||
|
||||
// let the game known about client state
|
||||
prog->globals.sv->time = sv.time;
|
||||
|
@ -280,12 +279,13 @@ void SV_PutClientInServer( edict_t *ent )
|
|||
|
||||
// setup playerstate
|
||||
memset( &client->ps, 0, sizeof(client->ps));
|
||||
|
||||
|
||||
client->ps.fov = 90;
|
||||
client->ps.fov = bound(1, client->ps.fov, 160);
|
||||
client->ps.vmodel.index = SV_ModelIndex(PRVM_GetString(ent->progs.sv->v_model));
|
||||
client->ps.pmodel.index = SV_ModelIndex(PRVM_GetString(ent->progs.sv->p_model));
|
||||
VectorCopy( ent->progs.sv->origin, client->ps.origin );
|
||||
client->ps.cmd_time = ( sv.time * 1000 ) - 100;
|
||||
VectorScale( ent->progs.sv->origin, SV_COORD_FRAC, client->ps.origin );
|
||||
VectorCopy( ent->progs.sv->v_angle, client->ps.viewangles );
|
||||
for( i = 0; i < 3; i++ ) client->ps.delta_angles[i] = ANGLE2SHORT(ent->progs.sv->v_angle[i]);
|
||||
|
||||
|
@ -322,11 +322,14 @@ void SV_New_f( sv_client_t *cl )
|
|||
playernum = cl - svs.clients;
|
||||
|
||||
// send the serverdata
|
||||
MSG_WriteByte( &cl->netmsg, svc_serverdata );
|
||||
MSG_WriteLong( &cl->netmsg, PROTOCOL_VERSION);
|
||||
MSG_WriteLong( &cl->netmsg, svs.spawncount );
|
||||
MSG_WriteShort( &cl->netmsg, playernum );
|
||||
MSG_WriteString( &cl->netmsg, sv.configstrings[CS_NAME] );
|
||||
MSG_WriteByte( &cl->netchan.message, svc_serverdata );
|
||||
MSG_WriteLong( &cl->netchan.message, PROTOCOL_VERSION);
|
||||
MSG_WriteLong( &cl->netchan.message, svs.spawncount );
|
||||
|
||||
if(sv.state == ss_cinematic) playernum = -1;
|
||||
else playernum = sv_client - svs.clients;
|
||||
MSG_WriteShort( &cl->netchan.message, playernum );
|
||||
MSG_WriteString( &cl->netchan.message, sv.configstrings[CS_NAME] );
|
||||
|
||||
// game server
|
||||
if( sv.state == ss_active )
|
||||
|
@ -338,8 +341,8 @@ void SV_New_f( sv_client_t *cl )
|
|||
memset( &cl->lastcmd, 0, sizeof(cl->lastcmd));
|
||||
|
||||
// begin fetching configstrings
|
||||
MSG_WriteByte( &cl->netmsg, svc_stufftext );
|
||||
MSG_WriteString( &cl->netmsg, va("cmd configstrings %i 0\n",svs.spawncount) );
|
||||
MSG_WriteByte( &cl->netchan.message, svc_stufftext );
|
||||
MSG_WriteString( &cl->netchan.message, va("cmd configstrings %i 0\n",svs.spawncount) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -370,13 +373,13 @@ void SV_Configstrings_f( sv_client_t *cl )
|
|||
start = com.atoi(Cmd_Argv(2));
|
||||
|
||||
// write a packet full of data
|
||||
while( cl->netmsg.cursize < MAX_MSGLEN / 2 && start < MAX_CONFIGSTRINGS )
|
||||
while( cl->netchan.message.cursize < MAX_MSGLEN / 2 && start < MAX_CONFIGSTRINGS )
|
||||
{
|
||||
if( sv.configstrings[start][0])
|
||||
{
|
||||
MSG_WriteByte( &cl->netmsg, svc_configstring );
|
||||
MSG_WriteShort( &cl->netmsg, start );
|
||||
MSG_WriteString( &cl->netmsg, sv.configstrings[start] );
|
||||
MSG_WriteByte( &cl->netchan.message, svc_configstring );
|
||||
MSG_WriteShort( &cl->netchan.message, start );
|
||||
MSG_WriteString( &cl->netchan.message, sv.configstrings[start] );
|
||||
}
|
||||
start++;
|
||||
}
|
||||
|
@ -385,8 +388,8 @@ void SV_Configstrings_f( sv_client_t *cl )
|
|||
else com.snprintf( cs, MAX_STRING, "cmd configstrings %i %i\n", svs.spawncount, start );
|
||||
|
||||
// send next command
|
||||
MSG_WriteByte( &cl->netmsg, svc_stufftext );
|
||||
MSG_WriteString( &cl->netmsg, cs );
|
||||
MSG_WriteByte( &cl->netchan.message, svc_stufftext );
|
||||
MSG_WriteString( &cl->netchan.message, cs );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -419,13 +422,13 @@ void SV_Baselines_f( sv_client_t *cl )
|
|||
memset( &nullstate, 0, sizeof(nullstate));
|
||||
|
||||
// write a packet full of data
|
||||
while( cl->netmsg.cursize < MAX_MSGLEN / 2 && start < MAX_EDICTS )
|
||||
while( cl->netchan.message.cursize < MAX_MSGLEN / 2 && start < MAX_EDICTS )
|
||||
{
|
||||
base = &sv.baselines[start];
|
||||
if( base->modelindex || base->soundindex || base->effects )
|
||||
{
|
||||
MSG_WriteByte( &cl->netmsg, svc_spawnbaseline );
|
||||
MSG_WriteDeltaEntity( &nullstate, base, &cl->netmsg, true, true );
|
||||
MSG_WriteByte( &cl->netchan.message, svc_spawnbaseline );
|
||||
MSG_WriteDeltaEntity( &nullstate, base, &cl->netchan.message, true, true );
|
||||
}
|
||||
start++;
|
||||
}
|
||||
|
@ -434,8 +437,8 @@ void SV_Baselines_f( sv_client_t *cl )
|
|||
else com.snprintf( baseline, MAX_STRING, "cmd baselines %i %i\n",svs.spawncount, start );
|
||||
|
||||
// send next command
|
||||
MSG_WriteByte( &cl->netmsg, svc_stufftext );
|
||||
MSG_WriteString( &cl->netmsg, baseline );
|
||||
MSG_WriteByte( &cl->netchan.message, svc_stufftext );
|
||||
MSG_WriteString( &cl->netchan.message, baseline );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -471,15 +474,15 @@ void SV_NextDownload_f( sv_client_t *cl )
|
|||
r = cl->downloadsize - cl->downloadcount;
|
||||
if( r > 1024 ) r = 1024;
|
||||
|
||||
MSG_WriteByte( &cl->netmsg, svc_download );
|
||||
MSG_WriteShort( &cl->netmsg, r );
|
||||
MSG_WriteByte( &cl->netchan.message, svc_download );
|
||||
MSG_WriteShort( &cl->netchan.message, r );
|
||||
|
||||
cl->downloadcount += r;
|
||||
size = cl->downloadsize;
|
||||
if( !size ) size = 1;
|
||||
percent = cl->downloadcount * 100 / size;
|
||||
MSG_WriteByte( &cl->netmsg, percent );
|
||||
SZ_Write( &cl->netmsg, cl->download + cl->downloadcount - r, r );
|
||||
MSG_WriteByte( &cl->netchan.message, percent );
|
||||
SZ_Write( &cl->netchan.message, cl->download + cl->downloadcount - r, r );
|
||||
if( cl->downloadcount == cl->downloadsize ) cl->download = NULL;
|
||||
}
|
||||
|
||||
|
@ -503,9 +506,9 @@ void SV_BeginDownload_f( sv_client_t *cl )
|
|||
{
|
||||
MsgDev( D_ERROR, "SV_BeginDownload_f: couldn't download %s to %s\n", name, cl->name );
|
||||
if( cl->download ) cl->download = NULL;
|
||||
MSG_WriteByte( &cl->netmsg, svc_download );
|
||||
MSG_WriteShort( &cl->netmsg, -1 );
|
||||
MSG_WriteByte( &cl->netmsg, 0 );
|
||||
MSG_WriteByte( &cl->netchan.message, svc_download );
|
||||
MSG_WriteShort( &cl->netchan.message, -1 );
|
||||
MSG_WriteByte( &cl->netchan.message, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -635,7 +638,6 @@ void SV_ExecuteClientCommand( sv_client_t *cl, char *s )
|
|||
{
|
||||
if(!com.strcmp(Cmd_Argv(0), u->name))
|
||||
{
|
||||
Msg("ucmd->%s\n", u->name );
|
||||
u->func( cl );
|
||||
break;
|
||||
}
|
||||
|
@ -661,11 +663,8 @@ void SV_ClientThink( sv_client_t *cl, usercmd_t *cmd )
|
|||
{
|
||||
cl->lastcmd = *cmd;
|
||||
|
||||
Msg("SV_ClientThink: %s\n", cl->name );
|
||||
|
||||
// may have been kicked during the last usercmd
|
||||
if( cl->state != cs_spawned || sv_paused->integer )
|
||||
return;
|
||||
if( sv_paused->integer ) return;
|
||||
ClientThink( cl->edict, cmd );
|
||||
}
|
||||
|
||||
|
@ -730,8 +729,8 @@ static void SV_UserMove( sv_client_t *cl, sizebuf_t *msg )
|
|||
|
||||
if( calculatedChecksum != checksum )
|
||||
{
|
||||
//MsgDev( D_ERROR, "SV_UserMove: failed checksum for %s (%d != %d)\n", cl->name, calculatedChecksum, checksum );
|
||||
//return;
|
||||
MsgDev( D_ERROR, "SV_UserMove: failed checksum for %s (%d != %d)\n", cl->name, calculatedChecksum, checksum );
|
||||
return;
|
||||
}
|
||||
|
||||
// usually, the first couple commands will be duplicates
|
||||
|
@ -766,6 +765,8 @@ void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg )
|
|||
{
|
||||
c = MSG_ReadByte( msg );
|
||||
if( c == clc_eof ) break;
|
||||
if( c == -1 ) break;
|
||||
|
||||
switch( c )
|
||||
{
|
||||
case clc_nop:
|
||||
|
|
|
@ -355,13 +355,13 @@ void SV_Status_f( void )
|
|||
int j, l, ping;
|
||||
char *s;
|
||||
|
||||
if (!cl->state) continue;
|
||||
if( cl->state == cs_free ) continue;
|
||||
|
||||
Msg("%3i ", i);
|
||||
Msg("%5i ", cl->edict->priv.sv->client->ps.stats[STAT_FRAGS]);
|
||||
|
||||
if (cl->state == cs_connected) Msg("Connect");
|
||||
else if (cl->state == cs_zombie) Msg ("Zombie ");
|
||||
if( cl->state == cs_connected ) Msg("Connect");
|
||||
else if( cl->state == cs_zombie ) Msg( "Zombie ");
|
||||
else
|
||||
{
|
||||
ping = cl->ping < 9999 ? cl->ping : 9999;
|
||||
|
|
|
@ -180,6 +180,7 @@ void SV_WritePlayerstateToClient (client_frame_t *from, client_frame_t *to, size
|
|||
if(!VectorCompare(ps->origin, ops->origin)) pflags |= PS_M_ORIGIN;
|
||||
if(!VectorCompare(ps->velocity, ops->velocity)) pflags |= PS_M_VELOCITY;
|
||||
if (ps->pm_time != ops->pm_time) pflags |= PS_M_TIME;
|
||||
if (ps->cmd_time != ops->cmd_time) pflags |= PS_M_COMMANDMSEC;
|
||||
if (ps->pm_flags != ops->pm_flags) pflags |= PS_M_FLAGS;
|
||||
if (ps->gravity != ops->gravity) pflags |= PS_M_GRAVITY;
|
||||
if(!VectorCompare(ps->delta_angles, ops->delta_angles)) pflags |= PS_M_DELTA_ANGLES;
|
||||
|
@ -209,7 +210,8 @@ void SV_WritePlayerstateToClient (client_frame_t *from, client_frame_t *to, size
|
|||
if (pflags & PS_M_TYPE) MSG_WriteByte (msg, ps->pm_type);
|
||||
if (pflags & PS_M_ORIGIN) MSG_WritePos32(msg, ps->origin);
|
||||
if (pflags & PS_M_VELOCITY) MSG_WritePos32(msg, ps->velocity);
|
||||
if (pflags & PS_M_TIME) MSG_WriteLong (msg, ps->pm_time);
|
||||
if (pflags & PS_M_TIME) MSG_WriteByte (msg, ps->pm_time);
|
||||
if (pflags & PS_M_COMMANDMSEC) MSG_WriteLong (msg, ps->cmd_time);
|
||||
if (pflags & PS_M_FLAGS) MSG_WriteByte (msg, ps->pm_flags);
|
||||
if (pflags & PS_M_GRAVITY) MSG_WriteShort (msg, ps->gravity);
|
||||
if (pflags & PS_M_DELTA_ANGLES) MSG_WritePos32(msg, ps->delta_angles);
|
||||
|
|
|
@ -37,10 +37,10 @@ void Master_Shutdown (void);
|
|||
static int rd_target;
|
||||
static char *rd_buffer;
|
||||
static int rd_buffersize;
|
||||
static void (*rd_flush)(int target, char *buffer);
|
||||
static void (*rd_flush)( netadr_t adr, int target, char *buffer);
|
||||
|
||||
//============================================================================
|
||||
void SVC_BeginRedirect (int target, char *buffer, int buffersize, void (*flush))
|
||||
void SVC_BeginRedirect( netadr_t adr, int target, char *buffer, int buffersize, void (*flush))
|
||||
{
|
||||
if (!target || !buffer || !buffersize || !flush) return;
|
||||
|
||||
|
@ -48,14 +48,16 @@ void SVC_BeginRedirect (int target, char *buffer, int buffersize, void (*flush))
|
|||
host.rd.buffer = buffer;
|
||||
host.rd.buffersize = buffersize;
|
||||
host.rd.flush = flush;
|
||||
host.rd.address = adr;
|
||||
|
||||
*host.rd.buffer = 0;
|
||||
}
|
||||
|
||||
void SVC_EndRedirect (void)
|
||||
void SVC_EndRedirect( netadr_t adr )
|
||||
{
|
||||
host.rd.flush(rd_target, rd_buffer);
|
||||
host.rd.flush( adr, rd_target, rd_buffer );
|
||||
|
||||
memset( &host.rd.address, 0, sizeof(netadr_t));
|
||||
host.rd.target = 0;
|
||||
host.rd.buffer = NULL;
|
||||
host.rd.buffersize = 0;
|
||||
|
@ -205,7 +207,7 @@ void SVC_RemoteCommand( netadr_t from, sizebuf_t *msg )
|
|||
|
||||
if (i == 0) MsgDev(D_INFO, "Bad rcon from %s:\n%s\n", NET_AdrToString (from), msg->data + 4);
|
||||
else MsgDev(D_INFO, "Rcon from %s:\n%s\n", NET_AdrToString (from), msg->data + 4);
|
||||
SVC_BeginRedirect (RD_PACKET, sv_outputbuf, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect);
|
||||
SVC_BeginRedirect( from, RD_PACKET, sv_outputbuf, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect );
|
||||
|
||||
if (!Rcon_Validate()) Msg("Bad rcon_password.\n");
|
||||
else
|
||||
|
@ -219,7 +221,7 @@ void SVC_RemoteCommand( netadr_t from, sizebuf_t *msg )
|
|||
}
|
||||
Cmd_ExecuteString (remaining);
|
||||
}
|
||||
SVC_EndRedirect ();
|
||||
SVC_EndRedirect( from );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -341,15 +343,18 @@ void SV_ReadPackets( void )
|
|||
{
|
||||
sv_client_t *cl;
|
||||
int i, qport;
|
||||
sizebuf_t *msg = &svs.netmsg;
|
||||
sizebuf_t net_message;
|
||||
sizebuf_t *msg = &net_message;
|
||||
byte buffer[MAX_MSGLEN];
|
||||
netadr_t net_from;
|
||||
|
||||
SZ_Init( msg, svs.netbuf, sizeof(svs.netbuf));
|
||||
while( NET_GetPacket( NS_SERVER, &svs.from, msg ))
|
||||
SZ_Init( msg, buffer, sizeof(buffer));
|
||||
while( NET_GetPacket( NS_SERVER, &net_from, msg ))
|
||||
{
|
||||
// check for connectionless packet (0xffffffff) first
|
||||
if( msg->cursize >= 4 && *(int *)msg->data == -1 )
|
||||
{
|
||||
SV_ConnectionlessPacket( svs.from, msg );
|
||||
SV_ConnectionlessPacket( net_from, msg );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -357,18 +362,19 @@ void SV_ReadPackets( void )
|
|||
// stupid address translating routers
|
||||
MSG_BeginReading( msg );
|
||||
MSG_ReadLong( msg ); // sequence number
|
||||
MSG_ReadLong( msg ); // sequence number
|
||||
qport = MSG_ReadShort( msg ) & 0xffff;
|
||||
|
||||
// check for packets from connected clients
|
||||
for( i = 0, cl = svs.clients; i < maxclients->value; i++, cl++ )
|
||||
{
|
||||
if( cl->state == cs_free ) continue;
|
||||
if( !NET_CompareBaseAdr( svs.from, cl->netchan.remote_address)) continue;
|
||||
if( !NET_CompareBaseAdr( net_from, cl->netchan.remote_address)) continue;
|
||||
if( cl->netchan.qport != qport ) continue;
|
||||
if( cl->netchan.remote_address.port != svs.from.port )
|
||||
if( cl->netchan.remote_address.port != net_from.port )
|
||||
{
|
||||
MsgDev(D_INFO, "SV_PacketEvent: fixing up a translated port\n");
|
||||
cl->netchan.remote_address.port = svs.from.port;
|
||||
cl->netchan.remote_address.port = net_from.port;
|
||||
}
|
||||
// make sure it is a valid, in sequence packet
|
||||
if( Netchan_Process(&cl->netchan, msg))
|
||||
|
|
|
@ -1746,8 +1746,8 @@ void PF_clientcmd( void )
|
|||
}
|
||||
|
||||
client = svs.clients + i;
|
||||
MSG_WriteByte( &client->netmsg, svc_stufftext );
|
||||
MSG_WriteString( &client->netmsg, PRVM_G_STRING(OFS_PARM1));
|
||||
MSG_WriteByte( &client->netchan.message, svc_stufftext );
|
||||
MSG_WriteString( &client->netchan.message, PRVM_G_STRING(OFS_PARM1));
|
||||
MSG_Send(MSG_ONE_R, NULL, client->edict );
|
||||
}
|
||||
|
||||
|
@ -2359,7 +2359,7 @@ const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t); /
|
|||
|
||||
/*
|
||||
==============
|
||||
SpawnEntities
|
||||
SV_SpawnEntities
|
||||
|
||||
Creates a server's entity / program execution context by
|
||||
parsing textual entity definitions out of an ent file.
|
||||
|
@ -2389,11 +2389,11 @@ void SV_SpawnEntities( const char *mapname, const char *entities )
|
|||
*prog->time = sv.time;
|
||||
|
||||
// set client fields on player ents
|
||||
for (i = 1; i < maxclients->value; i++)
|
||||
for (i = 0; i < maxclients->value; i++)
|
||||
{
|
||||
// setup all clients
|
||||
ent = PRVM_EDICT_NUM( i );
|
||||
ent->priv.sv->client = svs.clients + i - 1;
|
||||
ent->priv.sv->client = svs.clients + i;
|
||||
}
|
||||
|
||||
PRVM_ED_LoadFromFile( entities );
|
||||
|
|
|
@ -34,42 +34,20 @@ Msg redirection
|
|||
|
||||
char sv_outputbuf[SV_OUTPUTBUF_LENGTH];
|
||||
|
||||
void SV_FlushRedirect( int sv_redirected, char *outputbuf )
|
||||
void SV_FlushRedirect( netadr_t adr, int sv_redirected, char *outputbuf )
|
||||
{
|
||||
if (sv_redirected == RD_PACKET)
|
||||
{
|
||||
Netchan_OutOfBandPrint (NS_SERVER, svs.redirect_address, "print\n%s", outputbuf);
|
||||
Netchan_OutOfBandPrint (NS_SERVER, adr, "print\n%s", outputbuf);
|
||||
}
|
||||
else if (sv_redirected == RD_CLIENT)
|
||||
{
|
||||
MSG_WriteByte (&sv_client->netmsg, svc_print);
|
||||
MSG_WriteByte (&sv_client->netmsg, PRINT_CONSOLE );
|
||||
MSG_WriteString (&sv_client->netmsg, outputbuf);
|
||||
MSG_WriteByte (&sv_client->netchan.message, svc_print);
|
||||
MSG_WriteByte (&sv_client->netchan.message, PRINT_CONSOLE );
|
||||
MSG_WriteString (&sv_client->netchan.message, outputbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
SV_RateMsec
|
||||
|
||||
Return the number of msec a given size message is supposed
|
||||
to take to clear, based on the current rate
|
||||
====================
|
||||
*/
|
||||
|
||||
static int SV_RateMsec( sv_client_t *client, int msg_size )
|
||||
{
|
||||
int rate, rate_msec;
|
||||
|
||||
// individual messages will never be larger than fragment size
|
||||
if( msg_size > 1500 ) msg_size = 1500;
|
||||
|
||||
rate = client->rate;
|
||||
rate_msec = (msg_size + HEADER_RATE_BYTES) * 1000 / rate;
|
||||
|
||||
return rate_msec;
|
||||
}
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
|
@ -98,9 +76,9 @@ void SV_ClientPrintf (sv_client_t *cl, int level, char *fmt, ...)
|
|||
com.vsprintf (string, fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
MSG_WriteByte (&cl->netmsg, svc_print);
|
||||
MSG_WriteByte (&cl->netmsg, level);
|
||||
MSG_WriteString (&cl->netmsg, string);
|
||||
MSG_WriteByte (&cl->netchan.message, svc_print);
|
||||
MSG_WriteByte (&cl->netchan.message, level);
|
||||
MSG_WriteString (&cl->netchan.message, string);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -139,9 +117,9 @@ void SV_BroadcastPrintf (int level, char *fmt, ...)
|
|||
if (level < cl->messagelevel) continue;
|
||||
if (cl->state != cs_spawned) continue;
|
||||
|
||||
MSG_WriteByte (&cl->netmsg, svc_print);
|
||||
MSG_WriteByte (&cl->netmsg, level);
|
||||
MSG_WriteString (&cl->netmsg, string);
|
||||
MSG_WriteByte (&cl->netchan.message, svc_print);
|
||||
MSG_WriteByte (&cl->netchan.message, level);
|
||||
MSG_WriteString (&cl->netchan.message, string);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -252,8 +230,8 @@ void _MSG_Send (msgtype_t to, vec3_t origin, edict_t *ent, const char *filename,
|
|||
if ( mask && (!(mask[cluster>>3] & (1<<(cluster&7))))) continue;
|
||||
}
|
||||
|
||||
if (reliable) _SZ_Write (&client->netmsg, sv.multicast.data, sv.multicast.cursize, filename, fileline);
|
||||
else _SZ_Write (&client->netmsg, sv.multicast.data, sv.multicast.cursize, filename, fileline);
|
||||
if (reliable) _SZ_Write (&client->netchan.message, sv.multicast.data, sv.multicast.cursize, filename, fileline);
|
||||
else _SZ_Write (&client->datagram, sv.multicast.data, sv.multicast.cursize, filename, fileline);
|
||||
}
|
||||
SZ_Clear (&sv.multicast);
|
||||
}
|
||||
|
@ -427,56 +405,77 @@ FRAME UPDATES
|
|||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=======================
|
||||
SV_SendClientDatagram
|
||||
=======================
|
||||
*/
|
||||
void SV_SendClientDatagram (sv_client_t *client )
|
||||
void SV_SendClientDatagram( sv_client_t *client )
|
||||
{
|
||||
int rate_msec;
|
||||
sizebuf_t msg;
|
||||
byte msg_buf[MAX_MSGLEN];
|
||||
|
||||
SV_BuildClientFrame( client );
|
||||
SZ_Init( &msg, msg_buf, sizeof(msg_buf));
|
||||
|
||||
// send over all the relevant entity_state_t
|
||||
// and the player_state_t
|
||||
SV_WriteFrameToClient( client, &client->netmsg );
|
||||
SV_WriteFrameToClient( client, &msg );
|
||||
|
||||
if( client->netmsg.overflowed )
|
||||
// copy the accumulated multicast datagram
|
||||
// for this client out to the message
|
||||
// it is necessary for this to be after the WriteEntities
|
||||
// so that entity references will be current
|
||||
if (client->datagram.overflowed)
|
||||
MsgDev( D_WARN, "datagram overflowed for %s\n", client->name );
|
||||
else SZ_Write( &msg, client->datagram.data, client->datagram.cursize );
|
||||
SZ_Clear( &client->datagram );
|
||||
|
||||
if( msg.overflowed )
|
||||
{
|
||||
// must have room left for the packet header
|
||||
MsgDev( D_WARN, "msg overflowed for %s\n", client->name);
|
||||
SZ_Clear( &client->netmsg );
|
||||
MsgDev( D_WARN, "msg overflowed for %s\n", client->name );
|
||||
SZ_Clear( &msg );
|
||||
}
|
||||
|
||||
// record information about the message
|
||||
client->frames[client->netchan.outgoing_sequence & PACKET_MASK].msg_size = client->netmsg.cursize;
|
||||
client->frames[client->netchan.outgoing_sequence & PACKET_MASK].msg_size = msg.cursize;
|
||||
client->frames[client->netchan.outgoing_sequence & PACKET_MASK].msg_sent = svs.realtime;
|
||||
client->frames[client->netchan.outgoing_sequence & PACKET_MASK].msg_acked = -1;
|
||||
|
||||
// send the datagram
|
||||
Netchan_Transmit( &client->netchan, client->netmsg.cursize, client->netmsg.data );
|
||||
|
||||
if( NET_IsLocalAddress( client->netchan.remote_address ) || NET_IsLANAddress( client->netchan.remote_address ))
|
||||
{
|
||||
client->nextmsgtime = svs.realtime - 1;
|
||||
return;
|
||||
}
|
||||
Netchan_Transmit( &client->netchan, msg.cursize, msg.data );
|
||||
}
|
||||
|
||||
// normal rate / snapshotMsec calculation
|
||||
rate_msec = SV_RateMsec( client, client->netmsg.cursize );
|
||||
client->nextmsgtime = svs.realtime + rate_msec;
|
||||
/*
|
||||
=======================
|
||||
SV_RateDrop
|
||||
|
||||
// don't pile up empty snapshots while connecting
|
||||
if( client->state != cs_spawned )
|
||||
Returns true if the client is over its current
|
||||
bandwidth estimation and should not be sent another packet
|
||||
=======================
|
||||
*/
|
||||
bool SV_RateDrop( sv_client_t *cl )
|
||||
{
|
||||
int i, total = 0;
|
||||
|
||||
// never drop over the loopback
|
||||
if( NET_IsLocalAddress( cl->netchan.remote_address ))
|
||||
return false;
|
||||
|
||||
if( NET_IsLANAddress( cl->netchan.remote_address ))
|
||||
return false;
|
||||
|
||||
for( i = 0; i < UPDATE_BACKUP; i++ )
|
||||
total += cl->frames[i].msg_size;
|
||||
|
||||
if( total > cl->rate )
|
||||
{
|
||||
if( client->nextmsgtime < svs.realtime + 1000 )
|
||||
client->nextmsgtime = svs.realtime + 1000;
|
||||
cl->surpressCount++;
|
||||
cl->frames[cl->netchan.outgoing_sequence & PACKET_MASK].msg_size = 0;
|
||||
return true;
|
||||
}
|
||||
SZ_Clear( &client->netmsg );
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -493,29 +492,29 @@ void SV_SendClientMessages( void )
|
|||
for( i = 0, cl = svs.clients; i < maxclients->integer; i++, cl++ )
|
||||
{
|
||||
if( !cl->state ) continue;
|
||||
if( svs.realtime < cl->nextmsgtime ) continue; // not time yet
|
||||
|
||||
if( cl->state != cs_spawned )
|
||||
if( cl->netchan.message.overflowed )
|
||||
{
|
||||
if( cl->netmsg.cursize || svs.realtime - cl->lastmessage > 1000 )
|
||||
{
|
||||
Msg("SV_WritePacket: %s\n", cl->netmsg.data );
|
||||
Netchan_Transmit( &cl->netchan, cl->netmsg.cursize, cl->netmsg.data );
|
||||
SZ_Clear( &cl->netmsg );
|
||||
continue;
|
||||
}
|
||||
SZ_Clear(&cl->netchan.message);
|
||||
SZ_Clear(&cl->datagram);
|
||||
SV_BroadcastPrintf (PRINT_CONSOLE, "%s overflowed\n", cl->name);
|
||||
SV_DropClient( cl );
|
||||
}
|
||||
|
||||
if( cl->netchan.unsent_fragments )
|
||||
if( sv.state == ss_cinematic )
|
||||
{
|
||||
// send additional message fragments if the last message was too large to send at once
|
||||
int packet_size = cl->netchan.unsent_length - cl->netchan.unsent_fragment_start;
|
||||
cl->nextmsgtime = svs.realtime + SV_RateMsec( cl, packet_size );
|
||||
Netchan_TransmitNextFragment( &cl->netchan );
|
||||
continue;
|
||||
Netchan_Transmit( &cl->netchan, 0, NULL );
|
||||
}
|
||||
else if( cl->state == cs_spawned)
|
||||
{
|
||||
// don't overrun bandwidth
|
||||
if( SV_RateDrop( cl )) continue;
|
||||
SV_SendClientDatagram( cl );
|
||||
}
|
||||
else
|
||||
{
|
||||
// just update reliable if needed
|
||||
if( cl->netchan.message.cursize || svs.realtime - cl->netchan.last_sent > 1000 )
|
||||
Netchan_Transmit( &cl->netchan, 0, NULL );
|
||||
}
|
||||
|
||||
// generate and send a new message
|
||||
SV_SendClientDatagram( cl );
|
||||
}
|
||||
}
|
|
@ -379,7 +379,7 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd)
|
|||
pmove_t pm;
|
||||
vec3_t view;
|
||||
vec3_t oldorigin, oldvelocity;
|
||||
int i, j;
|
||||
int i, j, msec;
|
||||
|
||||
client = ent->priv.sv->client;
|
||||
|
||||
|
@ -415,6 +415,21 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd)
|
|||
pm.ps = client->ps;
|
||||
memcpy( &client->ucmd, ucmd, sizeof(usercmd_t));//IMPORTANT!!!
|
||||
|
||||
// sanity check the command time to prevent speedup cheating
|
||||
if( client->ucmd.servertime > ( sv.time * 1000 ) + 200 )
|
||||
{
|
||||
client->ucmd.servertime = ( sv.time * 1000 ) + 200;
|
||||
Msg("serverTime <<<<<\n" );
|
||||
}
|
||||
if( client->ucmd.servertime < ( sv.time * 1000 ) - 1000 )
|
||||
{
|
||||
client->ucmd.servertime = ( sv.time * 1000 ) - 1000;
|
||||
Msg("serverTime >>>>>\n" );
|
||||
}
|
||||
|
||||
msec = client->ucmd.servertime - client->ps.cmd_time;
|
||||
if( msec > 200 ) msec = 200;
|
||||
|
||||
VectorScale(ent->progs.sv->origin, SV_COORD_FRAC, pm.ps.origin );
|
||||
VectorScale(ent->progs.sv->velocity, SV_COORD_FRAC, pm.ps.velocity );
|
||||
|
||||
|
@ -445,7 +460,7 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd)
|
|||
VectorCopy(ent->progs.sv->v_offset, client->ps.vmodel.offset );
|
||||
VectorCopy(ent->progs.sv->v_angles, client->ps.vmodel.angles );
|
||||
|
||||
SV_LinkEdict(ent);
|
||||
SV_LinkEdict( ent );
|
||||
|
||||
if (ent->progs.sv->movetype != MOVETYPE_NOCLIP)
|
||||
SV_TouchTriggers (ent);
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#define MAX_STRING_TOKENS 80
|
||||
#define MAX_TOKEN_CHARS 128
|
||||
#define MAX_STRING_CHARS 1024
|
||||
#define MAX_MSGLEN 16384 // max length of a message, which may be fragmented into multiple packets
|
||||
#define MAX_MSGLEN 1400 // max length of a message, which may be fragmented into multiple packets
|
||||
|
||||
#define COLOR_BLACK '0'
|
||||
#define COLOR_RED '1'
|
||||
|
|
4
todo.log
4
todo.log
|
@ -32,8 +32,10 @@ fopen
|
|||
9. Вернуть пушку в центр экрана OK
|
||||
10. Исправить отрисовку bbox
|
||||
11. Исправить текстуры для p_model OK
|
||||
12. вернуть старый netchan
|
||||
12. вернуть старый netchan OK
|
||||
13. добавить поля в entity_state_t
|
||||
14. переделать систему maxclients
|
||||
15. организовать сжатие пакетов
|
||||
|
||||
Физика игрока:
|
||||
1. Убрать отскоки от стен
|
||||
|
|
Reference in New Issue