11 Jul 2008

This commit is contained in:
g-cont 2008-07-11 00:00:00 +04:00 committed by Alibek Omarov
parent 2f66b421d0
commit 58d4865f0a
25 changed files with 509 additions and 490 deletions

View File

@ -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" );
}

View File

@ -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;

View File

@ -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 );
}
/*

View File

@ -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");

View File

@ -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();

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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 );

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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 );

View File

@ -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:

View File

@ -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;

View File

@ -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);

View File

@ -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))

View File

@ -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 );

View File

@ -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 );
}
}

View File

@ -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);

View File

@ -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'

View File

@ -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. Убрать отскоки от стен