13 Jul 2008
This commit is contained in:
parent
dbe530e5f0
commit
3c0e835e60
|
@ -7,8 +7,8 @@
|
|||
|
||||
#include "platform.h"
|
||||
#include "basefiles.h"
|
||||
#include "mathlib.h"
|
||||
#include "utils.h"
|
||||
#include "mathlib.h"
|
||||
|
||||
#define VALVE_FORMAT 220
|
||||
#define MAX_BRUSH_SIDES 128
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
#define STUDIOMDL_H
|
||||
|
||||
#include "platform.h"
|
||||
#include "mathlib.h"
|
||||
#include "utils.h"
|
||||
#include "mathlib.h"
|
||||
|
||||
#define FILEBUFFER (2 * 1024 * 1024)
|
||||
#define MAXTRIANGLES 2048 //TODO: tune this
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
#include "platform.h"
|
||||
#include "basefiles.h"
|
||||
#include "baseimages.h"
|
||||
#include "mathlib.h"
|
||||
#include "utils.h"
|
||||
#include "mathlib.h"
|
||||
|
||||
#define MAX_FRAMES 512
|
||||
#define MAX_FRAME_DIM 512
|
||||
|
|
|
@ -1388,5 +1388,5 @@ void SCR_FinishCinematic( void )
|
|||
{
|
||||
// tell the server to advance to the next map / cinematic
|
||||
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
|
||||
SZ_Print(&cls.netchan.message, va("nextserver %i\n", cl.servercount));
|
||||
MSG_WriteString(&cls.netchan.message, va("nextserver %i\n", cl.servercount));
|
||||
}
|
||||
|
|
|
@ -450,8 +450,8 @@ void Con_DrawSolidConsole (float frac)
|
|||
char curtime[MAX_QPATH];
|
||||
|
||||
lines = scr_height->integer * frac;
|
||||
if (lines <= 0) return;
|
||||
if (lines > scr_height->integer) lines = scr_height->integer;
|
||||
if( lines <= 0 ) return;
|
||||
if( lines > scr_height->integer ) lines = scr_height->integer;
|
||||
|
||||
con.xadjust = 0; // on wide screens, we will center the text
|
||||
SCR_AdjustSize( &con.xadjust, NULL, NULL, NULL );
|
||||
|
@ -541,16 +541,16 @@ void Con_DrawConsole( void )
|
|||
break;
|
||||
case ca_connected:
|
||||
case ca_connecting:
|
||||
if(host.developer)
|
||||
if( host.developer )
|
||||
{
|
||||
// show console in devmode
|
||||
Con_DrawSolidConsole( 0.5 );
|
||||
Con_DrawSolidConsole( 0.5f );
|
||||
}
|
||||
break;
|
||||
case ca_disconnected:
|
||||
if(cls.key_dest != key_menu)
|
||||
if( cls.key_dest != key_menu )
|
||||
{
|
||||
Con_DrawSolidConsole( 1.0 );
|
||||
Con_DrawSolidConsole( 1.0f );
|
||||
cls.key_dest = key_console;
|
||||
}
|
||||
break;
|
||||
|
@ -571,10 +571,10 @@ Scroll it up or down
|
|||
*/
|
||||
void Con_RunConsole( void )
|
||||
{
|
||||
if(!host.developer) return;
|
||||
if( !host.developer ) return;
|
||||
|
||||
// decide on the destination height of the console
|
||||
if (cls.key_dest == key_console)
|
||||
if( cls.key_dest == key_console )
|
||||
{
|
||||
if ( cls.state == ca_disconnected )
|
||||
con.finalFrac = 1.0;// full screen
|
||||
|
@ -588,7 +588,7 @@ void Con_RunConsole( void )
|
|||
if (con.finalFrac > con.displayFrac)
|
||||
con.displayFrac = con.finalFrac;
|
||||
}
|
||||
else if (con.finalFrac > con.displayFrac)
|
||||
else if( con.finalFrac > con.displayFrac )
|
||||
{
|
||||
con.displayFrac += con_speed->value * cls.frametime;
|
||||
if (con.finalFrac < con.displayFrac)
|
||||
|
|
|
@ -13,7 +13,7 @@ CL_WriteDemoMessage
|
|||
Dumps the current net message, prefixed by the length
|
||||
====================
|
||||
*/
|
||||
void CL_WriteDemoMessage( void )
|
||||
void CL_WriteDemoMessage( sizebuf_t *msg, int head_size )
|
||||
{
|
||||
int len, swlen;
|
||||
|
||||
|
@ -21,11 +21,12 @@ void CL_WriteDemoMessage( void )
|
|||
if( cl_paused->value ) return;
|
||||
|
||||
// the first eight bytes are just packet sequencing stuff
|
||||
len = net_message.cursize - 8;
|
||||
len = msg->cursize - head_size;
|
||||
swlen = LittleLong( len );
|
||||
|
||||
if( !swlen ) return; // ignore null messages
|
||||
FS_Write( cls.demofile, &swlen, 4);
|
||||
FS_Write( cls.demofile, net_message.data + 8, len );
|
||||
FS_Write( cls.demofile, msg->data + head_size, len );
|
||||
}
|
||||
|
||||
void CL_WriteDemoHeader( const char *name )
|
||||
|
@ -50,7 +51,7 @@ void CL_WriteDemoHeader( const char *name )
|
|||
cls.demowaiting = true;
|
||||
|
||||
// write out messages to hold the startup information
|
||||
SZ_Init( &buf, buf_data, sizeof(buf_data));
|
||||
MSG_Init( &buf, buf_data, sizeof(buf_data));
|
||||
|
||||
// send the serverdata
|
||||
MSG_WriteByte( &buf, svc_serverdata );
|
||||
|
@ -99,7 +100,7 @@ void CL_WriteDemoHeader( const char *name )
|
|||
buf.cursize = 0;
|
||||
}
|
||||
MSG_WriteByte( &buf, svc_spawnbaseline );
|
||||
MSG_WriteDeltaEntity (&nullstate, &ent->priv.cl->baseline, &buf, true, true);
|
||||
MSG_WriteDeltaEntity (&nullstate, &ent->priv.cl->baseline, &buf, true );
|
||||
}
|
||||
|
||||
MSG_WriteByte( &buf, svc_stufftext );
|
||||
|
@ -113,6 +114,23 @@ void CL_WriteDemoHeader( const char *name )
|
|||
CL_VM_End();
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_DrawDemoRecording
|
||||
=================
|
||||
*/
|
||||
void CL_DrawDemoRecording( void )
|
||||
{
|
||||
char string[1024];
|
||||
fs_offset_t pos;
|
||||
|
||||
if(!(host.developer && cls.demorecording))
|
||||
return;
|
||||
pos = FS_Tell( cls.demofile );
|
||||
com.sprintf( string, "RECORDING %s: %ik", cls.demoname, pos / 1024 );
|
||||
SCR_DrawBigStringColor( 320 - com.strlen( string ) * 8, 80, string, g_color_table[7] );
|
||||
}
|
||||
|
||||
/*
|
||||
=======================================================================
|
||||
|
||||
|
@ -179,7 +197,7 @@ void CL_ReadDemoMessage( void )
|
|||
return;
|
||||
|
||||
// init the message
|
||||
SZ_Init( &buf, bufData, sizeof( bufData ));
|
||||
MSG_Init( &buf, bufData, sizeof( bufData ));
|
||||
|
||||
// get the length
|
||||
r = FS_Read( cls.demofile, &buf.cursize, 4 );
|
||||
|
@ -199,12 +217,13 @@ void CL_ReadDemoMessage( void )
|
|||
if( buf.cursize > buf.maxsize )
|
||||
{
|
||||
Host_Error( "CL_ReadDemoMessage: demoMsglen > MAX_MSGLEN\n" );
|
||||
return;
|
||||
}
|
||||
r = FS_Read( cls.demofile, buf.data, buf.cursize );
|
||||
|
||||
if( r != buf.cursize )
|
||||
{
|
||||
MsgDev( D_ERROR, "CL_ReadDemoMessage: demo file was truncated\n");
|
||||
MsgDev( D_ERROR, "CL_ReadDemoMessage: demo file was truncated( %d )\n", cls.state );
|
||||
CL_DemoCompleted();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_state_t
|
|||
cl.parse_entities++;
|
||||
frame->num_entities++;
|
||||
|
||||
MSG_ReadDeltaEntity( msg, old, state, newnum, bits );
|
||||
MSG_ReadDeltaEntity( msg, old, state, newnum );
|
||||
|
||||
// some data changes will force no lerping
|
||||
if( state->modelindex != ent->priv.cl->current.modelindex || state->weaponmodel != ent->priv.cl->current.weaponmodel || state->body != ent->priv.cl->current.body
|
||||
|
@ -381,7 +381,7 @@ void CL_ParseFrame( sizebuf_t *msg )
|
|||
int cmd;
|
||||
int len;
|
||||
frame_t *old;
|
||||
|
||||
|
||||
memset( &cl.frame, 0, sizeof(cl.frame));
|
||||
cl.frame.serverframe = MSG_ReadLong (msg);
|
||||
cl.frame.deltaframe = MSG_ReadLong (msg);
|
||||
|
|
|
@ -292,7 +292,7 @@ void CL_ParticleEffect (vec3_t org, vec3_t dir, int color, int count)
|
|||
p->next = active_particles;
|
||||
active_particles = p;
|
||||
|
||||
p->time = cl.time;
|
||||
p->time = cl.time * 0.001;
|
||||
p->color = color + (rand()&7);
|
||||
|
||||
d = rand()&31;
|
||||
|
@ -335,7 +335,7 @@ void CL_TeleportSplash( vec3_t org )
|
|||
p->next = active_particles;
|
||||
active_particles = p;
|
||||
|
||||
p->time = cl.time + RANDOM_FLOAT( 200, 2000 );
|
||||
p->time = (cl.time * 0.001) + RANDOM_FLOAT( 0.02f, 0.2f );
|
||||
p->color = 0xdb;
|
||||
|
||||
dir[0] = j * 8;
|
||||
|
@ -383,10 +383,11 @@ void CL_AddParticles (void)
|
|||
// PMM - added INSTANT_PARTICLE handling for heat beam
|
||||
if( p->alphavel != INSTANT_PARTICLE )
|
||||
{
|
||||
time = (cl.time - p->time);
|
||||
alpha = p->alpha + time*p->alphavel;
|
||||
if (alpha <= 0)
|
||||
{ // faded out
|
||||
time = ( cl.time * 0.001 ) - p->time;
|
||||
alpha = p->alpha + time * p->alphavel;
|
||||
if( alpha <= 0 )
|
||||
{
|
||||
// faded out
|
||||
p->next = free_particles;
|
||||
free_particles = p;
|
||||
continue;
|
||||
|
|
|
@ -92,12 +92,12 @@ void CL_MouseMove( usercmd_t *cmd )
|
|||
|
||||
// add mouse X/Y movement to cmd
|
||||
if( in_strafe.state & 1 )
|
||||
cmd->sidemove = bound( -128, cmd->sidemove + m_side->value * mx, 127 );
|
||||
cmd->sidemove = cmd->sidemove + m_side->value * mx;
|
||||
else cl.viewangles[YAW] -= m_yaw->value * mx;
|
||||
|
||||
if( cl_mouselook->value && !in_strafe.state & 1 )
|
||||
cl.viewangles[PITCH] += m_pitch->value * my;
|
||||
else cmd->forwardmove = bound( -128, cmd->forwardmove - m_forward->value * my, 127 );
|
||||
else cmd->forwardmove = cmd->forwardmove - m_forward->value * my;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -256,9 +256,6 @@ void IN_MoveleftDown(void) {IN_KeyDown(&in_moveleft);}
|
|||
void IN_MoveleftUp(void) {IN_KeyUp(&in_moveleft);}
|
||||
void IN_MoverightDown(void) {IN_KeyDown(&in_moveright);}
|
||||
void IN_MoverightUp(void) {IN_KeyUp(&in_moveright);}
|
||||
void IN_MLookDown( void ){Cvar_SetValue( "cl_mouselook", 1 );}
|
||||
void IN_MLookUp( void ){Cvar_SetValue( "cl_mouselook", 0 );}
|
||||
void IN_Impulse (void) {in_impulse = com.atoi(Cmd_Argv(1));}
|
||||
void IN_SpeedDown(void) {IN_KeyDown(&in_speed);}
|
||||
void IN_SpeedUp(void) {IN_KeyUp(&in_speed);}
|
||||
void IN_StrafeDown(void) {IN_KeyDown(&in_strafe);}
|
||||
|
@ -269,6 +266,9 @@ 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_Impulse (void) {in_impulse = com.atoi(Cmd_Argv(1));}
|
||||
void IN_MLookDown( void ){Cvar_SetValue( "cl_mouselook", 1 );}
|
||||
void IN_MLookUp( void ){ IN_CenterView(); Cvar_SetValue( "cl_mouselook", 0 );}
|
||||
void IN_CenterView (void) {cl.viewangles[PITCH] = -SHORT2ANGLE(cl.frame.ps.delta_angles[PITCH]);}
|
||||
|
||||
|
||||
|
@ -473,7 +473,7 @@ void CL_SendCmd( void )
|
|||
}
|
||||
|
||||
// begin a client move command
|
||||
SZ_Init (&buf, data, sizeof(data));
|
||||
MSG_Init(&buf, data, sizeof(data));
|
||||
MSG_WriteByte (&buf, clc_move);
|
||||
|
||||
// save the position for a checksum byte
|
||||
|
@ -509,10 +509,11 @@ void CL_SendCmd( void )
|
|||
MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
|
||||
|
||||
// calculate a checksum over the move commands
|
||||
buf.data[checksumIndex] = CRC_Sequence(
|
||||
buf.data + checksumIndex + 1, buf.cursize - checksumIndex - 1,
|
||||
cls.netchan.outgoing_sequence);
|
||||
|
||||
//FIXME
|
||||
/*buf.data[checksumIndex] = CRC_Sequence(
|
||||
buf.data + checksumIndex + 1, buf.cursize - checksumIndex - 1,
|
||||
cls.netchan.outgoing_sequence);
|
||||
*/
|
||||
// deliver the message
|
||||
Netchan_Transmit (&cls.netchan, buf.cursize, buf.data);
|
||||
}
|
||||
|
|
|
@ -1,840 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// cl.input.c -- builds an intended movement command to send to the server
|
||||
|
||||
#include "common.h"
|
||||
#include "client.h"
|
||||
|
||||
cvar_t *cl_nodelta;
|
||||
cvar_t *v_centermove;
|
||||
cvar_t *v_centerspeed;
|
||||
cvar_t *m_filter; // mouse sensetivity
|
||||
cvar_t *m_mouse;
|
||||
|
||||
uint frame_msec;
|
||||
int mouse_buttons;
|
||||
int mouse_oldbuttonstate;
|
||||
POINT cur_pos, old_pos;
|
||||
int mouse_x, mouse_y, mx_accum, my_accum;
|
||||
|
||||
bool mouseactive; // false when not focus app
|
||||
|
||||
bool restore_spi;
|
||||
bool mouseinitialized;
|
||||
int originalmouseparms[3], newmouseparms[3] = {0, 0, 1};
|
||||
bool mouseparmsvalid;
|
||||
|
||||
int window_center_x, window_center_y;
|
||||
RECT window_rect;
|
||||
|
||||
cvar_t *cl_sensitivity;
|
||||
cvar_t *ui_sensitivity;
|
||||
/*
|
||||
============================================================
|
||||
|
||||
MOUSE CONTROL
|
||||
|
||||
============================================================
|
||||
*/
|
||||
|
||||
// mouse variables
|
||||
|
||||
|
||||
bool mlooking;
|
||||
|
||||
void IN_MLookDown (void)
|
||||
{
|
||||
mlooking = true;
|
||||
}
|
||||
|
||||
void IN_MLookUp (void)
|
||||
{
|
||||
mlooking = false;
|
||||
if(!freelook->value && lookspring->value)
|
||||
IN_CenterView ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_ActivateMouse
|
||||
|
||||
Called when the window gains focus or changes in some way
|
||||
===========
|
||||
*/
|
||||
void IN_ActivateMouse( void )
|
||||
{
|
||||
int width, height;
|
||||
|
||||
if(!mouseinitialized) return;
|
||||
|
||||
if(!m_mouse->integer)
|
||||
{
|
||||
mouseactive = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if(mouseactive) return;
|
||||
mouseactive = true;
|
||||
|
||||
if( mouseparmsvalid ) restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0);
|
||||
|
||||
width = GetSystemMetrics(SM_CXSCREEN);
|
||||
height = GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
GetWindowRect( host.hWnd, &window_rect);
|
||||
if (window_rect.left < 0) window_rect.left = 0;
|
||||
if (window_rect.top < 0) window_rect.top = 0;
|
||||
if (window_rect.right >= width) window_rect.right = width - 1;
|
||||
if (window_rect.bottom >= height-1) window_rect.bottom = height - 1;
|
||||
|
||||
window_center_x = (window_rect.right + window_rect.left)/2;
|
||||
window_center_y = (window_rect.top + window_rect.bottom)/2;
|
||||
SetCursorPos( window_center_x, window_center_y );
|
||||
|
||||
SetCapture( host.hWnd );
|
||||
ClipCursor(&window_rect);
|
||||
while( ShowCursor(false) >= 0 );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_DeactivateMouse
|
||||
|
||||
Called when the window loses focus
|
||||
===========
|
||||
*/
|
||||
void IN_DeactivateMouse (void)
|
||||
{
|
||||
if(!mouseinitialized || !mouseactive)
|
||||
return;
|
||||
|
||||
if( restore_spi ) SystemParametersInfo (SPI_SETMOUSE, 0, originalmouseparms, 0);
|
||||
|
||||
mouseactive = false;
|
||||
|
||||
ClipCursor( NULL );
|
||||
ReleaseCapture();
|
||||
while( ShowCursor(true) < 0 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_StartupMouse
|
||||
===========
|
||||
*/
|
||||
void IN_StartupMouse (void)
|
||||
{
|
||||
cvar_t *cv;
|
||||
|
||||
cv = Cvar_Get ("in_initmouse", "1", CVAR_INIT, "allow mouse device" );
|
||||
if ( !cv->value ) return;
|
||||
|
||||
mouseinitialized = true;
|
||||
mouseparmsvalid = SystemParametersInfo(SPI_GETMOUSE, 0, originalmouseparms, 0);
|
||||
mouse_buttons = 3;
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
M_Event
|
||||
===========
|
||||
*/
|
||||
void M_Event( int mstate )
|
||||
{
|
||||
int i;
|
||||
|
||||
if(!mouseinitialized) return;
|
||||
|
||||
// perform button actions
|
||||
for (i = 0; i < mouse_buttons; i++)
|
||||
{
|
||||
if((mstate & (1<<i)) && !(mouse_oldbuttonstate & (1<<i)) )
|
||||
{
|
||||
Key_Event (K_MOUSE1 + i, true, host.sv_timer);
|
||||
}
|
||||
if ( !(mstate & (1<<i)) && (mouse_oldbuttonstate & (1<<i)) )
|
||||
{
|
||||
Key_Event (K_MOUSE1 + i, false, host.sv_timer);
|
||||
}
|
||||
}
|
||||
mouse_oldbuttonstate = mstate;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
CL_MouseMove
|
||||
===========
|
||||
*/
|
||||
void CL_MouseMove (usercmd_t *cmd)
|
||||
{
|
||||
int mx, my;
|
||||
|
||||
if (!mouseactive) return;
|
||||
|
||||
// find mouse movement
|
||||
if (!GetCursorPos (&cur_pos))
|
||||
return;
|
||||
|
||||
mx = cur_pos.x - window_center_x;
|
||||
my = cur_pos.y - window_center_y;
|
||||
|
||||
#if 0
|
||||
if (!mx && !my)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (m_filter->value)
|
||||
{
|
||||
mouse_x = (mx + old_pos.x) * 0.5;
|
||||
mouse_y = (my + old_pos.y) * 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
mouse_x = mx;
|
||||
mouse_y = my;
|
||||
}
|
||||
|
||||
old_pos.x = mx;
|
||||
old_pos.y = my;
|
||||
|
||||
if( cls.key_dest != key_menu )
|
||||
{
|
||||
mouse_x *= cl_sensitivity->value;
|
||||
mouse_y *= cl_sensitivity->value;
|
||||
|
||||
// add mouse X/Y movement to cmd
|
||||
if ( (in_strafe.state & 1) || (lookstrafe->value && mlooking ))
|
||||
cmd->sidemove += m_side->value * mouse_x;
|
||||
else cl.viewangles[YAW] -= m_yaw->value * mouse_x;
|
||||
|
||||
if((mlooking || freelook->value) && !(in_strafe.state & 1))
|
||||
cl.viewangles[PITCH] += m_pitch->value * mouse_y;
|
||||
else cmd->forwardmove -= m_forward->value * mouse_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
mouse_x *= ui_sensitivity->value;
|
||||
mouse_y *= ui_sensitivity->value;
|
||||
}
|
||||
|
||||
// force the mouse to the center, so there's room to move
|
||||
if(mx || my) SetCursorPos( window_center_x, window_center_y );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=========================================================================
|
||||
|
||||
VIEW CENTERING
|
||||
|
||||
=========================================================================
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
M_Activate
|
||||
|
||||
Called when the main window gains or loses focus.
|
||||
The window may have been destroyed and recreated
|
||||
between a deactivate and an activate.
|
||||
===========
|
||||
*/
|
||||
void M_Activate( void )
|
||||
{
|
||||
// force a new window check or turn off
|
||||
if(host.state == HOST_FRAME)
|
||||
mouseactive = false;
|
||||
else mouseactive = true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
CL_UpdateMouse
|
||||
|
||||
Called every frame, even if not generating commands
|
||||
==================
|
||||
*/
|
||||
void CL_UpdateMouse( void )
|
||||
{
|
||||
if(!mouseinitialized) return;
|
||||
|
||||
if(!m_mouse || host.state != HOST_FRAME)
|
||||
{
|
||||
IN_DeactivateMouse();
|
||||
return;
|
||||
}
|
||||
|
||||
// uimenu.dat using mouse
|
||||
if((!cl.refresh_prepped && cls.key_dest != key_menu) || cls.key_dest == key_console )
|
||||
{
|
||||
// temporarily deactivate if in fullscreen
|
||||
if(!Cvar_VariableValue ("fullscreen"))
|
||||
{
|
||||
IN_DeactivateMouse();
|
||||
return;
|
||||
}
|
||||
}
|
||||
IN_ActivateMouse();
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
IN_ClearStates
|
||||
===================
|
||||
*/
|
||||
void IN_ClearStates (void)
|
||||
{
|
||||
mx_accum = 0;
|
||||
my_accum = 0;
|
||||
mouse_oldbuttonstate = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
KEY BUTTONS
|
||||
|
||||
Continuous button event tracking is complicated by the fact that two different
|
||||
input sources (say, mouse button 1 and the control key) can both press the
|
||||
same button, but the button should only be released when both of the
|
||||
pressing key have been released.
|
||||
|
||||
When a key event issues a button command (+forward, +attack, etc), it appends
|
||||
its key number as a parameter to the command so it can be matched up with
|
||||
the release.
|
||||
|
||||
state bit 0 is the current state of the key
|
||||
state bit 1 is edge triggered on the up to down transition
|
||||
state bit 2 is edge triggered on the down to up transition
|
||||
|
||||
|
||||
Key_Event (int key, bool down, unsigned time);
|
||||
|
||||
+mlook src time
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
|
||||
kbutton_t in_klook;
|
||||
kbutton_t in_left, in_right, in_forward, in_back;
|
||||
kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright;
|
||||
kbutton_t in_strafe, in_speed, in_use, in_attack;
|
||||
kbutton_t in_up, in_down;
|
||||
|
||||
int in_impulse;
|
||||
|
||||
void KeyDown (kbutton_t *b)
|
||||
{
|
||||
int k;
|
||||
char *c;
|
||||
|
||||
c = Cmd_Argv(1);
|
||||
if (c[0]) k = atoi(c);
|
||||
else k = -1; // typed manually at the console for continuous down
|
||||
|
||||
if (k == b->down[0] || k == b->down[1])
|
||||
return; // repeating key
|
||||
|
||||
if (!b->down[0]) b->down[0] = k;
|
||||
else if (!b->down[1]) b->down[1] = k;
|
||||
else
|
||||
{
|
||||
Msg ("Three keys down for a button!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (b->state & 1) return; // still down
|
||||
|
||||
// save timestamp
|
||||
c = Cmd_Argv(2);
|
||||
b->downtime = com.atoi(c);
|
||||
|
||||
if (!b->downtime) b->downtime = host.cl_timer - HOST_FRAMETIME;
|
||||
b->state |= 1 + 2; // down + impulse down
|
||||
}
|
||||
|
||||
void KeyUp (kbutton_t *b)
|
||||
{
|
||||
int k;
|
||||
char *c;
|
||||
uint uptime;
|
||||
|
||||
c = Cmd_Argv(1);
|
||||
if (c[0]) k = atoi(c);
|
||||
else
|
||||
{
|
||||
// typed manually at the console, assume for unsticking, so clear all
|
||||
b->down[0] = b->down[1] = 0;
|
||||
b->state = 4; // impulse up
|
||||
return;
|
||||
}
|
||||
|
||||
if (b->down[0] == k) b->down[0] = 0;
|
||||
else if (b->down[1] == k) b->down[1] = 0;
|
||||
else return; // key up without coresponding down (menu pass through)
|
||||
|
||||
if (b->down[0] || b->down[1])
|
||||
return; // some other key is still holding it down
|
||||
|
||||
if (!(b->state & 1))
|
||||
return; // still up (this should not happen)
|
||||
|
||||
// save timestamp
|
||||
c = Cmd_Argv(2);
|
||||
uptime = com.atoi(c);
|
||||
if (uptime) b->msec += uptime - b->downtime;
|
||||
else b->msec += 10;
|
||||
|
||||
b->state &= ~1; // now up
|
||||
b->state |= 4; // impulse up
|
||||
}
|
||||
|
||||
void IN_KLookDown (void) {KeyDown(&in_klook);}
|
||||
void IN_KLookUp (void) {KeyUp(&in_klook);}
|
||||
void IN_UpDown(void) {KeyDown(&in_up);}
|
||||
void IN_UpUp(void) {KeyUp(&in_up);}
|
||||
void IN_DownDown(void) {KeyDown(&in_down);}
|
||||
void IN_DownUp(void) {KeyUp(&in_down);}
|
||||
void IN_LeftDown(void) {KeyDown(&in_left);}
|
||||
void IN_LeftUp(void) {KeyUp(&in_left);}
|
||||
void IN_RightDown(void) {KeyDown(&in_right);}
|
||||
void IN_RightUp(void) {KeyUp(&in_right);}
|
||||
void IN_ForwardDown(void) {KeyDown(&in_forward);}
|
||||
void IN_ForwardUp(void) {KeyUp(&in_forward);}
|
||||
void IN_BackDown(void) {KeyDown(&in_back);}
|
||||
void IN_BackUp(void) {KeyUp(&in_back);}
|
||||
void IN_LookupDown(void) {KeyDown(&in_lookup);}
|
||||
void IN_LookupUp(void) {KeyUp(&in_lookup);}
|
||||
void IN_LookdownDown(void) {KeyDown(&in_lookdown);}
|
||||
void IN_LookdownUp(void) {KeyUp(&in_lookdown);}
|
||||
void IN_MoveleftDown(void) {KeyDown(&in_moveleft);}
|
||||
void IN_MoveleftUp(void) {KeyUp(&in_moveleft);}
|
||||
void IN_MoverightDown(void) {KeyDown(&in_moveright);}
|
||||
void IN_MoverightUp(void) {KeyUp(&in_moveright);}
|
||||
|
||||
void IN_SpeedDown(void) {KeyDown(&in_speed);}
|
||||
void IN_SpeedUp(void) {KeyUp(&in_speed);}
|
||||
void IN_StrafeDown(void) {KeyDown(&in_strafe);}
|
||||
void IN_StrafeUp(void) {KeyUp(&in_strafe);}
|
||||
|
||||
void IN_AttackDown(void) {KeyDown(&in_attack);}
|
||||
void IN_AttackUp(void) {KeyUp(&in_attack);}
|
||||
|
||||
void IN_UseDown (void) {KeyDown(&in_use);}
|
||||
void IN_UseUp (void) {KeyUp(&in_use);}
|
||||
|
||||
void IN_Impulse (void) {in_impulse=atoi(Cmd_Argv(1));}
|
||||
|
||||
/*
|
||||
===============
|
||||
CL_KeyState
|
||||
|
||||
Returns the fraction of the frame that the key was down
|
||||
===============
|
||||
*/
|
||||
float CL_KeyState (kbutton_t *key)
|
||||
{
|
||||
float val;
|
||||
int msec;
|
||||
|
||||
key->state &= 1; // clear impulses
|
||||
|
||||
msec = key->msec;
|
||||
key->msec = 0;
|
||||
|
||||
if (key->state)
|
||||
{ // still down
|
||||
msec += host.cl_timer - key->downtime;
|
||||
key->downtime = host.cl_timer;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (msec)
|
||||
{
|
||||
Msg ("%i ", msec);
|
||||
}
|
||||
#endif
|
||||
|
||||
val = (float)msec / frame_msec;
|
||||
if (val < 0)
|
||||
val = 0;
|
||||
if (val > 1)
|
||||
val = 1;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
|
||||
cvar_t *cl_upspeed;
|
||||
cvar_t *cl_forwardspeed;
|
||||
cvar_t *cl_sidespeed;
|
||||
|
||||
cvar_t *cl_yawspeed;
|
||||
cvar_t *cl_pitchspeed;
|
||||
|
||||
cvar_t *cl_run;
|
||||
|
||||
cvar_t *cl_anglespeedkey;
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
CL_AdjustAngles
|
||||
|
||||
Moves the local angle positions
|
||||
================
|
||||
*/
|
||||
void CL_AdjustAngles( void )
|
||||
{
|
||||
float speed;
|
||||
float up, down;
|
||||
|
||||
if (in_speed.state & 1)
|
||||
speed = cls.frametime * cl_anglespeedkey->value;
|
||||
else
|
||||
speed = cls.frametime;
|
||||
|
||||
if (!(in_strafe.state & 1))
|
||||
{
|
||||
cl.viewangles[YAW] -= speed*cl_yawspeed->value*CL_KeyState (&in_right);
|
||||
cl.viewangles[YAW] += speed*cl_yawspeed->value*CL_KeyState (&in_left);
|
||||
}
|
||||
if (in_klook.state & 1)
|
||||
{
|
||||
cl.viewangles[PITCH] -= speed*cl_pitchspeed->value * CL_KeyState (&in_forward);
|
||||
cl.viewangles[PITCH] += speed*cl_pitchspeed->value * CL_KeyState (&in_back);
|
||||
}
|
||||
|
||||
up = CL_KeyState (&in_lookup);
|
||||
down = CL_KeyState(&in_lookdown);
|
||||
|
||||
cl.viewangles[PITCH] -= speed*cl_pitchspeed->value * up;
|
||||
cl.viewangles[PITCH] += speed*cl_pitchspeed->value * down;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CL_BaseMove
|
||||
|
||||
Send the intended movement message to the server
|
||||
================
|
||||
*/
|
||||
void CL_BaseMove (usercmd_t *cmd)
|
||||
{
|
||||
CL_AdjustAngles ();
|
||||
|
||||
memset (cmd, 0, sizeof(*cmd));
|
||||
|
||||
VectorCopy (cl.viewangles, cmd->angles);
|
||||
if (in_strafe.state & 1)
|
||||
{
|
||||
cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_right);
|
||||
cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_left);
|
||||
}
|
||||
|
||||
cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_moveright);
|
||||
cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_moveleft);
|
||||
|
||||
cmd->upmove += cl_upspeed->value * CL_KeyState (&in_up);
|
||||
cmd->upmove -= cl_upspeed->value * CL_KeyState (&in_down);
|
||||
|
||||
if (! (in_klook.state & 1) )
|
||||
{
|
||||
cmd->forwardmove += cl_forwardspeed->value * CL_KeyState (&in_forward);
|
||||
cmd->forwardmove -= cl_forwardspeed->value * CL_KeyState (&in_back);
|
||||
}
|
||||
|
||||
//
|
||||
// adjust for speed key / running
|
||||
//
|
||||
if ( (in_speed.state & 1) ^ (int)(cl_run->value) )
|
||||
{
|
||||
cmd->forwardmove *= 2;
|
||||
cmd->sidemove *= 2;
|
||||
cmd->upmove *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
void CL_ClampPitch (void)
|
||||
{
|
||||
float pitch;
|
||||
|
||||
pitch = SHORT2ANGLE(cl.frame.ps.delta_angles[PITCH]);
|
||||
if (pitch > 180) pitch -= 360;
|
||||
|
||||
if (cl.viewangles[PITCH] + pitch < -360) cl.viewangles[PITCH] += 360; // wrapped
|
||||
if (cl.viewangles[PITCH] + pitch > 360) cl.viewangles[PITCH] -= 360; // wrapped
|
||||
|
||||
if (cl.viewangles[PITCH] + pitch > 89) cl.viewangles[PITCH] = 89 - pitch;
|
||||
if (cl.viewangles[PITCH] + pitch < -89) cl.viewangles[PITCH] = -89 - pitch;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
CL_FinishMove
|
||||
==============
|
||||
*/
|
||||
void CL_FinishMove (usercmd_t *cmd)
|
||||
{
|
||||
int ms;
|
||||
int i;
|
||||
|
||||
//
|
||||
// figure button bits
|
||||
//
|
||||
if ( in_attack.state & 3 )
|
||||
cmd->buttons |= BUTTON_ATTACK;
|
||||
in_attack.state &= ~2;
|
||||
|
||||
if (in_use.state & 3)
|
||||
cmd->buttons |= BUTTON_USE;
|
||||
in_use.state &= ~2;
|
||||
|
||||
if (anykeydown && cls.key_dest == key_game)
|
||||
cmd->buttons |= BUTTON_ANY;
|
||||
|
||||
// send milliseconds of time to apply the move
|
||||
ms = cls.frametime * 1000;
|
||||
if( ms > 250 ) ms = 100; // time was unreasonable
|
||||
cmd->msec = ms;
|
||||
|
||||
CL_ClampPitch ();
|
||||
for (i=0 ; i<3 ; i++)
|
||||
cmd->angles[i] = ANGLE2SHORT(cl.viewangles[i]);
|
||||
|
||||
cmd->impulse = in_impulse;
|
||||
in_impulse = 0;
|
||||
|
||||
// send the ambient light level at the player's current position
|
||||
cmd->lightlevel = (byte)cl_lightlevel->value;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_CreateCmd
|
||||
=================
|
||||
*/
|
||||
usercmd_t CL_CreateCmd (void)
|
||||
{
|
||||
usercmd_t cmd;
|
||||
|
||||
frame_msec = host.cl_timer - host.old_cl_timer;
|
||||
if (frame_msec < 1) frame_msec = 1;
|
||||
if (frame_msec > 200) frame_msec = 200;
|
||||
|
||||
// get basic movement from keyboard
|
||||
CL_BaseMove(&cmd);
|
||||
CL_MouseMove(&cmd);
|
||||
|
||||
CL_FinishMove (&cmd);
|
||||
|
||||
host.old_cl_timer = host.cl_timer;
|
||||
|
||||
//cmd.impulse = cls.framecount;
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
void IN_CenterView (void)
|
||||
{
|
||||
cl.viewangles[PITCH] = -SHORT2ANGLE(cl.frame.ps.delta_angles[PITCH]);
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
CL_InitInput
|
||||
============
|
||||
*/
|
||||
void CL_InitInput (void)
|
||||
{
|
||||
// mouse variables
|
||||
m_filter = Cvar_Get("m_filter", "0", 0, "enable mouse filter" );
|
||||
m_mouse = Cvar_Get("mouse", "1", CVAR_ARCHIVE, "allow mouse in-game" );
|
||||
cl_sensitivity = Cvar_Get( "cl_sensitivity", "3", CVAR_ARCHIVE, "mouse in-game sensitivity" );
|
||||
ui_sensitivity = Cvar_Get( "ui_sensitivity", "0.5", CVAR_ARCHIVE, "mouse in-menu sensitivity" );
|
||||
|
||||
// centering
|
||||
v_centermove = Cvar_Get ("v_centermove", "0.15", 0, "client center moving" );
|
||||
v_centerspeed = Cvar_Get ("v_centerspeed", "500", 0, "client center speed" );
|
||||
cl_nodelta = Cvar_Get ("cl_nodelta", "0", 0, "disable delta-compression for usercommnds" );
|
||||
|
||||
Cmd_AddCommand ("centerview", IN_CenterView, "gradually recenter view (stop looking up/down)" );
|
||||
|
||||
// input commands
|
||||
Cmd_AddCommand ("+moveup",IN_UpDown, "swim upward");
|
||||
Cmd_AddCommand ("-moveup",IN_UpUp, "stop swimming upward");
|
||||
Cmd_AddCommand ("+movedown",IN_DownDown, "swim downward");
|
||||
Cmd_AddCommand ("-movedown",IN_DownUp, "stop swimming downward");
|
||||
Cmd_AddCommand ("+left",IN_LeftDown, "turn left");
|
||||
Cmd_AddCommand ("-left",IN_LeftUp, "stop turning left");
|
||||
Cmd_AddCommand ("+right",IN_RightDown, "turn right");
|
||||
Cmd_AddCommand ("-right",IN_RightUp, "stop turning right");
|
||||
Cmd_AddCommand ("+forward",IN_ForwardDown, "move forward");
|
||||
Cmd_AddCommand ("-forward",IN_ForwardUp, "stop moving forward");
|
||||
Cmd_AddCommand ("+back",IN_BackDown, "move backward");
|
||||
Cmd_AddCommand ("-back",IN_BackUp, "stop moving backward");
|
||||
Cmd_AddCommand ("+lookup", IN_LookupDown, "look upward");
|
||||
Cmd_AddCommand ("-lookup", IN_LookupUp, "stop looking upward");
|
||||
Cmd_AddCommand ("+lookdown", IN_LookdownDown, "look downward");
|
||||
Cmd_AddCommand ("-lookdown", IN_LookdownUp, "stop looking downward");
|
||||
Cmd_AddCommand ("+strafe", IN_StrafeDown, "activate strafing mode (move instead of turn)\n");
|
||||
Cmd_AddCommand ("-strafe", IN_StrafeUp, "deactivate strafing mode");
|
||||
Cmd_AddCommand ("+moveleft", IN_MoveleftDown, "strafe left");
|
||||
Cmd_AddCommand ("-moveleft", IN_MoveleftUp, "stop strafing left");
|
||||
Cmd_AddCommand ("+moveright", IN_MoverightDown, "strafe right");
|
||||
Cmd_AddCommand ("-moveright", IN_MoverightUp, "stop strafing right");
|
||||
Cmd_AddCommand ("+speed", IN_SpeedDown, "activate run mode (faster movement and turning)");
|
||||
Cmd_AddCommand ("-speed", IN_SpeedUp, "deactivate run mode");
|
||||
Cmd_AddCommand ("+attack", IN_AttackDown, "begin firing");
|
||||
Cmd_AddCommand ("-attack", IN_AttackUp, "stop firing");
|
||||
Cmd_AddCommand ("+use", IN_UseDown, "use item (doors, monsters, inventory, etc" );
|
||||
Cmd_AddCommand ("-use", IN_UseUp, "stop using item" );
|
||||
Cmd_AddCommand ("impulse", IN_Impulse, "send an impulse number to server (select weapon, use item, etc)");
|
||||
Cmd_AddCommand ("+klook", IN_KLookDown, "activate keyboard looking mode, do not recenter view");
|
||||
Cmd_AddCommand ("-klook", IN_KLookUp, "deactivate keyboard looking mode");
|
||||
Cmd_AddCommand ("+mlook", IN_MLookDown, "activate mouse looking mode, do not recenter view" );
|
||||
Cmd_AddCommand ("-mlook", IN_MLookUp, "deactivate mouse looking mode" );
|
||||
|
||||
IN_StartupMouse(); // init mouse
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
CL_ShutdownInput
|
||||
============
|
||||
*/
|
||||
void CL_ShutdownInput( void )
|
||||
{
|
||||
IN_DeactivateMouse();
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_SendCmd
|
||||
=================
|
||||
*/
|
||||
void CL_SendCmd (void)
|
||||
{
|
||||
sizebuf_t buf;
|
||||
byte data[128];
|
||||
int i;
|
||||
usercmd_t *cmd, *oldcmd;
|
||||
usercmd_t nullcmd;
|
||||
int checksumIndex;
|
||||
int curtime;
|
||||
|
||||
// build a command even if not connected
|
||||
|
||||
// save this command off for prediction
|
||||
i = cls.netchan.outgoing_sequence & (CMD_BACKUP-1);
|
||||
cmd = &cl.cmds[i];
|
||||
cl.cmd_time[i] = cls.realtime; // for netgraph ping calculation
|
||||
curtime = Sys_Milliseconds();
|
||||
|
||||
*cmd = CL_CreateCmd ();
|
||||
|
||||
cl.cmd = *cmd;
|
||||
|
||||
SZ_Init (&buf, data, sizeof(data));
|
||||
|
||||
if(cls.state == ca_disconnected || cls.state == ca_connecting)
|
||||
return;
|
||||
|
||||
// ignore commands for demo mode
|
||||
if(cls.state == ca_cinematic || cls.demoplayback)
|
||||
return;
|
||||
|
||||
if( cls.state == ca_connected )
|
||||
{
|
||||
if (cls.netchan.message.cursize || curtime - cls.netchan.last_sent > 1000 )
|
||||
Netchan_Transmit (&cls.netchan, 0, buf.data);
|
||||
return;
|
||||
}
|
||||
|
||||
// send a userinfo update if needed
|
||||
if (userinfo_modified)
|
||||
{
|
||||
userinfo_modified = false;
|
||||
MSG_WriteByte (&cls.netchan.message, clc_userinfo);
|
||||
MSG_WriteString (&cls.netchan.message, Cvar_Userinfo());
|
||||
}
|
||||
|
||||
// begin a client move command
|
||||
MSG_WriteByte (&buf, clc_move);
|
||||
|
||||
// save the position for a checksum byte
|
||||
checksumIndex = buf.cursize;
|
||||
MSG_WriteByte (&buf, 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
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_WriteLong (&buf, cl.frame.serverframe);
|
||||
}
|
||||
|
||||
// send this and the previous cmds in the message, so
|
||||
// if the last packet was dropped, it can be recovered
|
||||
i = (cls.netchan.outgoing_sequence-2) & (CMD_BACKUP-1);
|
||||
cmd = &cl.cmds[i];
|
||||
memset (&nullcmd, 0, sizeof(nullcmd));
|
||||
MSG_WriteDeltaUsercmd (&buf, &nullcmd, cmd);
|
||||
oldcmd = cmd;
|
||||
|
||||
i = (cls.netchan.outgoing_sequence-1) & (CMD_BACKUP-1);
|
||||
cmd = &cl.cmds[i];
|
||||
MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
|
||||
oldcmd = cmd;
|
||||
|
||||
i = (cls.netchan.outgoing_sequence) & (CMD_BACKUP-1);
|
||||
cmd = &cl.cmds[i];
|
||||
MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
|
||||
|
||||
// calculate a checksum over the move commands
|
||||
buf.data[checksumIndex] = CRC_Sequence(
|
||||
buf.data + checksumIndex + 1, buf.cursize - checksumIndex - 1,
|
||||
cls.netchan.outgoing_sequence);
|
||||
|
||||
//
|
||||
// deliver the message
|
||||
//
|
||||
Netchan_Transmit (&cls.netchan, buf.cursize, buf.data);
|
||||
}
|
||||
|
||||
|
|
@ -103,12 +103,12 @@ void Cmd_ForwardToServer (void)
|
|||
return;
|
||||
}
|
||||
|
||||
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
|
||||
SZ_Print (&cls.netchan.message, cmd);
|
||||
MSG_WriteByte(&cls.netchan.message, clc_stringcmd);
|
||||
MSG_WriteString(&cls.netchan.message, cmd);
|
||||
if (Cmd_Argc() > 1)
|
||||
{
|
||||
SZ_Print (&cls.netchan.message, " ");
|
||||
SZ_Print (&cls.netchan.message, Cmd_Args());
|
||||
MSG_WriteString(&cls.netchan.message, " ");
|
||||
MSG_WriteString(&cls.netchan.message, Cmd_Args());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,10 +127,11 @@ void CL_ForwardToServer_f (void)
|
|||
}
|
||||
|
||||
// don't forward the first argument
|
||||
if (Cmd_Argc() > 1)
|
||||
if( Cmd_Argc() > 1 )
|
||||
{
|
||||
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
|
||||
SZ_Print (&cls.netchan.message, Cmd_Args());
|
||||
MSG_WriteByte(&cls.netchan.message, clc_stringcmd);
|
||||
MSG_WriteString(&cls.netchan.message, Cmd_Args());
|
||||
Msg("CL->clc_stringcmd %s\n", Cmd_Args());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,11 +201,11 @@ void CL_SendConnectPacket (void)
|
|||
cls.connect_time = 0;
|
||||
return;
|
||||
}
|
||||
if(adr.port == 0) adr.port = BigShort (PORT_SERVER);
|
||||
port = Cvar_VariableValue ("net_qport");
|
||||
if( adr.port == 0 ) adr.port = BigShort( PORT_SERVER );
|
||||
port = Cvar_VariableValue( "net_qport" );
|
||||
|
||||
userinfo_modified = false;
|
||||
Netchan_OutOfBandPrint(NS_CLIENT, adr, "connect %i %i %i \"%s\"\n", PROTOCOL_VERSION, port, cls.challenge, Cvar_Userinfo() );
|
||||
Netchan_OutOfBandPrint(NS_CLIENT, adr, "connect %i %i %i \"%s\"\n", PROTOCOL_VERSION, port, cls.challenge, Cvar_Userinfo());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -354,7 +355,7 @@ void CL_ClearState (void)
|
|||
|
||||
// wipe the entire cl structure
|
||||
memset (&cl, 0, sizeof(cl));
|
||||
SZ_Clear (&cls.netchan.message);
|
||||
MSG_Clear( &cls.netchan.message );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -684,14 +685,14 @@ CL_ParseStatusMessage
|
|||
Handle a reply from a ping
|
||||
=================
|
||||
*/
|
||||
void CL_ParseStatusMessage (void)
|
||||
void CL_ParseStatusMessage( netadr_t from, sizebuf_t *msg )
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = MSG_ReadString(&net_message);
|
||||
s = MSG_ReadString( msg );
|
||||
|
||||
Msg ("%s\n", s);
|
||||
CL_ParseServerStatus( NET_AdrToString(net_from), s );
|
||||
CL_ParseServerStatus( NET_AdrToString(from), s );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -701,53 +702,53 @@ CL_ConnectionlessPacket
|
|||
Responses to broadcasts, etc
|
||||
=================
|
||||
*/
|
||||
void CL_ConnectionlessPacket( void )
|
||||
void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
||||
{
|
||||
char *s, *c;
|
||||
|
||||
MSG_BeginReading (&net_message);
|
||||
MSG_ReadLong (&net_message); // skip the -1
|
||||
MSG_BeginReading( msg );
|
||||
MSG_ReadLong( msg ); // skip the -1
|
||||
|
||||
s = MSG_ReadStringLine (&net_message);
|
||||
s = MSG_ReadStringLine( msg );
|
||||
|
||||
Cmd_TokenizeString(s);
|
||||
Cmd_TokenizeString( s );
|
||||
c = Cmd_Argv(0);
|
||||
|
||||
MsgDev(D_INFO, "%s: %s\n", NET_AdrToString (net_from), c);
|
||||
MsgDev(D_INFO, "%s: %s\n", NET_AdrToString (from), c);
|
||||
|
||||
// server connection
|
||||
if (!strcmp(c, "client_connect"))
|
||||
if(!com.strcmp( c, "client_connect"))
|
||||
{
|
||||
if (cls.state == ca_connected)
|
||||
{
|
||||
Msg ("Dup connect received. Ignored.\n");
|
||||
return;
|
||||
}
|
||||
Netchan_Setup (NS_CLIENT, &cls.netchan, net_from, Cvar_VariableValue ("net_qport"));
|
||||
MSG_WriteChar (&cls.netchan.message, clc_stringcmd);
|
||||
MSG_WriteString (&cls.netchan.message, "new");
|
||||
Netchan_Setup( NS_CLIENT, &cls.netchan, from, Cvar_VariableValue( "net_qport" ));
|
||||
MSG_WriteChar( &cls.netchan.message, clc_stringcmd );
|
||||
MSG_WriteString( &cls.netchan.message, "new" );
|
||||
cls.state = ca_connected;
|
||||
return;
|
||||
}
|
||||
|
||||
// server responding to a status broadcast
|
||||
if (!strcmp(c, "info"))
|
||||
if(!com.strcmp( c, "info"))
|
||||
{
|
||||
CL_ParseStatusMessage ();
|
||||
CL_ParseStatusMessage( from, msg );
|
||||
return;
|
||||
}
|
||||
|
||||
// remote command from gui front end
|
||||
if (!strcmp(c, "cmd"))
|
||||
if(!strcmp(c, "cmd"))
|
||||
{
|
||||
if(!NET_IsLocalAddress(net_from))
|
||||
if(!NET_IsLocalAddress(from))
|
||||
{
|
||||
Msg ("Command packet from remote host. Ignored.\n");
|
||||
return;
|
||||
}
|
||||
ShowWindow( host.hWnd, SW_RESTORE);
|
||||
SetForegroundWindow ( host.hWnd );
|
||||
s = MSG_ReadString (&net_message);
|
||||
s = MSG_ReadString( msg );
|
||||
Cbuf_AddText(s);
|
||||
Cbuf_AddText("\n");
|
||||
return;
|
||||
|
@ -756,8 +757,8 @@ void CL_ConnectionlessPacket( void )
|
|||
if (!strcmp(c, "print"))
|
||||
{
|
||||
// print command from somewhere
|
||||
s = MSG_ReadString (&net_message);
|
||||
if(!CL_ParseServerStatus( NET_AdrToString(net_from), s ))
|
||||
s = MSG_ReadString( msg );
|
||||
if(!CL_ParseServerStatus( NET_AdrToString( from ), s ))
|
||||
Msg( s );
|
||||
return;
|
||||
}
|
||||
|
@ -765,76 +766,35 @@ void CL_ConnectionlessPacket( void )
|
|||
// ping from somewhere
|
||||
if (!strcmp(c, "ping"))
|
||||
{
|
||||
Netchan_OutOfBandPrint (NS_CLIENT, net_from, "ack");
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, from, "ack" );
|
||||
return;
|
||||
}
|
||||
|
||||
// challenge from the server we are connecting to
|
||||
if (!strcmp(c, "challenge"))
|
||||
{
|
||||
cls.challenge = atoi(Cmd_Argv(1));
|
||||
CL_SendConnectPacket ();
|
||||
cls.challenge = com.atoi(Cmd_Argv(1));
|
||||
CL_SendConnectPacket();
|
||||
return;
|
||||
}
|
||||
|
||||
// echo request from server
|
||||
if (!strcmp(c, "echo"))
|
||||
{
|
||||
Netchan_OutOfBandPrint (NS_CLIENT, net_from, "%s", Cmd_Argv(1) );
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, from, "%s", Cmd_Argv(1) );
|
||||
return;
|
||||
}
|
||||
|
||||
// a disconnect message from the server, which will happen if the server
|
||||
// dropped the connection but it is still getting packets from us
|
||||
if(!com.strcmp( c, "disconnect" ))
|
||||
{
|
||||
CL_Disconnect();
|
||||
return;
|
||||
}
|
||||
Msg ("Unknown command.\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_DumpPackets
|
||||
|
||||
A vain attempt to help bad TCP stacks that cause problems
|
||||
when they overflow
|
||||
=================
|
||||
*/
|
||||
void CL_DumpPackets (void)
|
||||
{
|
||||
while (NET_GetPacket (NS_CLIENT, &net_from, &net_message))
|
||||
{
|
||||
Msg ("dumnping a packet\n");
|
||||
}
|
||||
}
|
||||
|
||||
void CL_ReadNetMessage( void )
|
||||
{
|
||||
while (NET_GetPacket (NS_CLIENT, &net_from, &net_message))
|
||||
{
|
||||
// remote command packet
|
||||
if(*(int *)net_message.data == -1)
|
||||
{
|
||||
CL_ConnectionlessPacket();
|
||||
continue;
|
||||
}
|
||||
|
||||
if( cls.state == ca_disconnected || cls.state == ca_connecting )
|
||||
continue; // dump it if not connected
|
||||
|
||||
if( net_message.cursize < 8 )
|
||||
{
|
||||
Msg( "%s: Runt packet\n", NET_AdrToString(net_from));
|
||||
continue;
|
||||
}
|
||||
|
||||
// packet from server
|
||||
if (!NET_CompareAdr (net_from, cls.netchan.remote_address))
|
||||
{
|
||||
MsgDev( D_WARN, "CL_ReadPackets: %s:sequenced packet without connection\n",NET_AdrToString(net_from));
|
||||
continue;
|
||||
}
|
||||
if(!Netchan_Process(&cls.netchan, &net_message))
|
||||
continue; // wasn't accepted for some reason
|
||||
CL_ParseServerMessage( &net_message );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_ReadPackets
|
||||
|
@ -842,13 +802,52 @@ CL_ReadPackets
|
|||
*/
|
||||
void CL_PacketEvent( netadr_t from, sizebuf_t *msg )
|
||||
{
|
||||
if( host.type == HOST_DEDICATED || cls.demoplayback )
|
||||
return;
|
||||
|
||||
CL_VM_Begin();
|
||||
|
||||
if( msg->cursize >= 4 && *(int *)msg->data == -1 )
|
||||
{
|
||||
cls.netchan.last_received = cls.realtime;
|
||||
CL_ConnectionlessPacket( from, msg );
|
||||
return;
|
||||
}
|
||||
|
||||
// can't be a valid sequenced packet
|
||||
if( cls.state < ca_connected ) return;
|
||||
|
||||
if( msg->cursize < 8 )
|
||||
{
|
||||
MsgDev( D_WARN, "%s: runt packet\n", NET_AdrToString( from ));
|
||||
return;
|
||||
}
|
||||
|
||||
// packet from server
|
||||
if (!NET_CompareAdr( from, cls.netchan.remote_address))
|
||||
{
|
||||
MsgDev( D_WARN, "CL_ReadPackets: %s:sequenced packet without connection\n", NET_AdrToString( from ));
|
||||
return;
|
||||
}
|
||||
if(Netchan_Process( &cls.netchan, msg ))
|
||||
{
|
||||
// the header is different lengths for reliable and unreliable messages
|
||||
int headerBytes = msg->readcount;
|
||||
|
||||
cls.netchan.last_received = cls.realtime;
|
||||
CL_ParseServerMessage( msg );
|
||||
|
||||
// we don't know if it is ok to save a demo message until
|
||||
// after we have parsed the frame
|
||||
if( cls.demorecording && !cls.demowaiting )
|
||||
CL_WriteDemoMessage( msg, headerBytes );
|
||||
}
|
||||
CL_VM_End();
|
||||
}
|
||||
|
||||
void CL_ReadPackets (void)
|
||||
void CL_ReadPackets( void )
|
||||
{
|
||||
if( cls.demoplayback )
|
||||
CL_ReadDemoMessage();
|
||||
else CL_ReadNetMessage();
|
||||
if( cls.demoplayback ) CL_ReadDemoMessage();
|
||||
|
||||
if(NET_IsLocalAddress( cls.netchan.remote_address ))
|
||||
return;
|
||||
|
@ -1377,12 +1376,6 @@ CL_SendCommand
|
|||
*/
|
||||
void CL_SendCommand (void)
|
||||
{
|
||||
// get new key events
|
||||
Sys_SendKeyEvents ();
|
||||
|
||||
// process console commands
|
||||
Cbuf_Execute ();
|
||||
|
||||
// fix any cheating cvars
|
||||
CL_FixCvarCheats ();
|
||||
|
||||
|
@ -1401,23 +1394,13 @@ CL_Frame
|
|||
*/
|
||||
void CL_Frame( dword time )
|
||||
{
|
||||
static dword extratime;
|
||||
|
||||
if( host.type == HOST_DEDICATED )
|
||||
return;
|
||||
|
||||
extratime += time;
|
||||
|
||||
if( cls.state == ca_connected && extratime < HOST_FRAMETIME )
|
||||
return; // don't flood packets out while connecting
|
||||
if( extratime < 1000 / cl_maxfps->value)
|
||||
return; // framerate is too high
|
||||
|
||||
// decide the simulation time
|
||||
cl.time += extratime;
|
||||
cls.realtime = Sys_Milliseconds();
|
||||
cls.frametime = extratime * 0.001;
|
||||
extratime = 0;
|
||||
cl.time += time; // can be merged by cl.frame.servertime
|
||||
cls.realtime += time;
|
||||
cls.frametime = time * 0.001;
|
||||
|
||||
if( cls.frametime > (1.0 / 5)) cls.frametime = (1.0 / 5);
|
||||
|
||||
|
@ -1480,10 +1463,6 @@ void CL_Init( void )
|
|||
VID_Init();
|
||||
V_Init();
|
||||
CL_InitClientProgs();
|
||||
|
||||
net_message.data = net_message_buffer;
|
||||
net_message.maxsize = sizeof(net_message_buffer);
|
||||
|
||||
UI_Init();
|
||||
SCR_Init();
|
||||
CL_InitLocal();
|
||||
|
|
|
@ -39,7 +39,7 @@ void UI_KeyEvent( int key )
|
|||
PRVM_G_FLOAT(OFS_PARM0) = key;
|
||||
prog->globals.ui->time = cls.realtime * 0.001f;
|
||||
PRVM_G_INT(OFS_PARM1) = PRVM_SetEngineString(ascii);
|
||||
PRVM_ExecuteProgram (prog->globals.ui->m_keydown, "QC function m_keydown is missing");
|
||||
PRVM_ExecuteProgram (prog->globals.ui->m_keydown, "m_keydown");
|
||||
|
||||
CL_VM_Begin(); // restore clvm state
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ void UI_Draw( void )
|
|||
|
||||
UI_VM_Begin();
|
||||
prog->globals.ui->time = cls.realtime * 0.001f;
|
||||
PRVM_ExecuteProgram (prog->globals.ui->m_draw, "QC function m_draw is missing");
|
||||
PRVM_ExecuteProgram (prog->globals.ui->m_draw, "m_draw");
|
||||
UI_DrawCredits(); // display game credits
|
||||
|
||||
CL_VM_Begin(); // restore clvm state
|
||||
|
@ -87,7 +87,7 @@ void UI_DrawCredits( void )
|
|||
credits_active = false; // end of credits
|
||||
|
||||
// let menu progs known about credits state
|
||||
PRVM_ExecuteProgram( prog->globals.ui->m_endofcredits, "QC function m_endofcredits is missing");
|
||||
PRVM_ExecuteProgram( prog->globals.ui->m_endofcredits, "m_endofcredits");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ void UI_ShowMenu( void )
|
|||
|
||||
ui_active = true;
|
||||
prog->globals.ui->time = cls.realtime * 0.001f;
|
||||
PRVM_ExecuteProgram (prog->globals.ui->m_show, "QC function m_toggle is missing");
|
||||
PRVM_ExecuteProgram (prog->globals.ui->m_show, "m_toggle");
|
||||
CL_VM_Begin(); // restore clvm state
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ void UI_HideMenu( void )
|
|||
UI_VM_Begin();
|
||||
ui_active = false;
|
||||
prog->globals.ui->time = cls.realtime * 0.001f;
|
||||
PRVM_ExecuteProgram (prog->globals.ui->m_hide, "QC function m_toggle is missing");
|
||||
PRVM_ExecuteProgram (prog->globals.ui->m_hide, "m_toggle");
|
||||
CL_VM_Begin(); // restore clvm state
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ void UI_Shutdown( void )
|
|||
{
|
||||
UI_VM_Begin();
|
||||
|
||||
PRVM_ExecuteProgram (prog->globals.ui->m_shutdown, "QC function m_shutdown is missing");
|
||||
PRVM_ExecuteProgram (prog->globals.ui->m_shutdown, "m_shutdown");
|
||||
cls.key_dest = key_game;
|
||||
|
||||
// AK not using this cause Im not sure whether this is useful at all instead :
|
||||
|
@ -742,6 +742,6 @@ void UI_Init( void )
|
|||
PRVM_LoadProgs( GI->uimenu_prog, 0, NULL, UI_NUM_REQFIELDS, ui_reqfields );
|
||||
*prog->time = cls.realtime * 0.001f;
|
||||
|
||||
PRVM_ExecuteProgram (prog->globals.ui->m_init, "QC function m_init is missing");
|
||||
PRVM_ExecuteProgram (prog->globals.ui->m_init, "m_init");
|
||||
PRVM_End;
|
||||
}
|
|
@ -223,8 +223,8 @@ void CL_ParseDownload( sizebuf_t *msg )
|
|||
// request next block
|
||||
cls.downloadpercent = percent;
|
||||
|
||||
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
|
||||
SZ_Print (&cls.netchan.message, "nextdl");
|
||||
MSG_WriteByte(&cls.netchan.message, clc_stringcmd);
|
||||
MSG_WriteString(&cls.netchan.message, "nextdl");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -271,14 +271,14 @@ void CL_ParseServerData( sizebuf_t *msg )
|
|||
MsgDev(D_INFO, "Serverdata packet received.\n");
|
||||
|
||||
// wipe the client_t struct
|
||||
CL_ClearState ();
|
||||
CL_ClearState();
|
||||
cls.state = ca_connected;
|
||||
|
||||
// parse protocol version number
|
||||
i = MSG_ReadLong( msg );
|
||||
cls.serverProtocol = i;
|
||||
|
||||
if (i != PROTOCOL_VERSION) Host_Error("Server returned version %i, not %i", i, PROTOCOL_VERSION);
|
||||
if( i != PROTOCOL_VERSION ) Host_Error("Server returned version %i, not %i", i, PROTOCOL_VERSION );
|
||||
|
||||
cl.servercount = MSG_ReadLong( msg );
|
||||
|
||||
|
@ -288,13 +288,21 @@ void CL_ParseServerData( sizebuf_t *msg )
|
|||
// get the full level name
|
||||
str = MSG_ReadString( msg );
|
||||
|
||||
if (cl.playernum == -1)
|
||||
if( cl.playernum == -1 )
|
||||
{
|
||||
// playing a cinematic or showing a pic, not a level
|
||||
SCR_PlayCinematic( str, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// get splash name
|
||||
Cvar_Set( "cl_levelshot_name", va("background/%s.tga", str ));
|
||||
Cvar_SetValue("scr_loading", 0.0f ); // reset progress bar
|
||||
if(!FS_FileExists(va("gfx/%s", Cvar_VariableString("cl_levelshot_name"))))
|
||||
{
|
||||
Cvar_Set("cl_levelshot_name", "common/black");
|
||||
cl.make_levelshot = true; // make levelshot
|
||||
}
|
||||
// seperate the printfs so the server message can have a color
|
||||
Msg("\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n");
|
||||
// need to prep refresh at next oportunity
|
||||
|
@ -321,7 +329,7 @@ void CL_ParseBaseline( sizebuf_t *msg )
|
|||
while( newnum >= prog->num_edicts ) PRVM_ED_Alloc();
|
||||
ent = PRVM_EDICT_NUM( newnum );
|
||||
|
||||
MSG_ReadDeltaEntity( msg, &nullstate, &ent->priv.cl->baseline, newnum, bits );
|
||||
MSG_ReadDeltaEntity( msg, &nullstate, &ent->priv.cl->baseline, newnum );
|
||||
}
|
||||
|
||||
|
||||
|
@ -582,24 +590,20 @@ void CL_ParseServerMessage( sizebuf_t *msg )
|
|||
if (cl_shownet->value == 1) Msg ("%i ",msg->cursize);
|
||||
else if (cl_shownet->value >= 2) Msg ("------------------\n");
|
||||
|
||||
MSG_UseHuffman( msg, true );
|
||||
cls.multicast = msg; // client progs can recivied messages too
|
||||
|
||||
// parse the message
|
||||
while( 1 )
|
||||
{
|
||||
if (msg->readcount > msg->cursize)
|
||||
if( msg->readcount > msg->cursize )
|
||||
{
|
||||
Host_Error("CL_ParseServerMessage: Bad server message\n");
|
||||
break;
|
||||
}
|
||||
|
||||
cmd = MSG_ReadByte( msg );
|
||||
|
||||
if (cmd == -1)
|
||||
{
|
||||
SHOWNET( msg, "END OF MESSAGE" );
|
||||
break;
|
||||
}
|
||||
if( cmd == -1 ) break;
|
||||
|
||||
// other commands
|
||||
switch( cmd )
|
||||
|
@ -623,6 +627,7 @@ void CL_ParseServerMessage( sizebuf_t *msg )
|
|||
break;
|
||||
case svc_stufftext:
|
||||
s = MSG_ReadString( msg );
|
||||
Msg("CL<-svc_stufftext %s\n", s );
|
||||
Cbuf_AddText( s );
|
||||
break;
|
||||
case svc_serverdata:
|
||||
|
@ -665,10 +670,4 @@ void CL_ParseServerMessage( sizebuf_t *msg )
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// we don't know if it is ok to save a demo message until
|
||||
// after we have parsed the frame
|
||||
if (cls.demorecording && !cls.demowaiting)
|
||||
CL_WriteDemoMessage();
|
||||
|
||||
}
|
|
@ -52,7 +52,7 @@ float *CL_FadeColor( float starttime, float endtime )
|
|||
|
||||
void CL_DrawHUD( void )
|
||||
{
|
||||
if(!prog) return; // too early (just skip one frame)
|
||||
CL_VM_Begin();
|
||||
|
||||
// setup pparms
|
||||
prog->globals.cl->health = cl.frame.ps.stats[STAT_HEALTH];
|
||||
|
@ -62,7 +62,7 @@ void CL_DrawHUD( void )
|
|||
|
||||
// setup args
|
||||
PRVM_G_FLOAT(OFS_PARM0) = (float)cls.state;
|
||||
PRVM_ExecuteProgram (prog->globals.cl->HUD_Render, "QC function HUD_Render is missing");
|
||||
PRVM_ExecuteProgram (prog->globals.cl->HUD_Render, "HUD_Render");
|
||||
}
|
||||
|
||||
bool CL_ParseUserMessage( int svc_number )
|
||||
|
@ -77,7 +77,7 @@ bool CL_ParseUserMessage( int svc_number )
|
|||
|
||||
// setup args
|
||||
PRVM_G_FLOAT(OFS_PARM0) = (float)svc_number;
|
||||
PRVM_ExecuteProgram (prog->globals.cl->HUD_ParseMessage, "QC function HUD_ParseMessage is missing");
|
||||
PRVM_ExecuteProgram (prog->globals.cl->HUD_ParseMessage, "HUD_ParseMessage");
|
||||
msg_parsed = PRVM_G_FLOAT(OFS_RETURN);
|
||||
|
||||
return msg_parsed;
|
||||
|
@ -97,7 +97,7 @@ void CL_StudioEvent ( mstudioevent_t *event, entity_t *ent )
|
|||
PRVM_G_INT(OFS_PARM1) = PRVM_SetEngineString( event->options );
|
||||
VectorCopy( ent->origin, PRVM_G_VECTOR(OFS_PARM2));
|
||||
VectorCopy( ent->angles, PRVM_G_VECTOR(OFS_PARM3));
|
||||
PRVM_ExecuteProgram( prog->globals.cl->HUD_StudioEvent, "QC function HUD_StudioEvent is missing");
|
||||
PRVM_ExecuteProgram( prog->globals.cl->HUD_StudioEvent, "HUD_StudioEvent");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -625,7 +625,7 @@ void CL_InitClientProgs( void )
|
|||
prog->globals.cl->playernum = cl.playernum;
|
||||
|
||||
// call the prog init
|
||||
PRVM_ExecuteProgram( prog->globals.cl->HUD_Init, "QC function HUD_Init is missing");
|
||||
PRVM_ExecuteProgram( prog->globals.cl->HUD_Init, "HUD_Init");
|
||||
PRVM_End;
|
||||
}
|
||||
|
||||
|
@ -635,7 +635,7 @@ void CL_FreeClientProgs( void )
|
|||
|
||||
prog->globals.cl->realtime = cls.realtime * 0.001f;
|
||||
prog->globals.cl->pev = 0;
|
||||
PRVM_ExecuteProgram(prog->globals.cl->HUD_Shutdown, "QC function HUD_Shutdown is missing");
|
||||
PRVM_ExecuteProgram(prog->globals.cl->HUD_Shutdown, "HUD_Shutdown");
|
||||
PRVM_ResetProg();
|
||||
|
||||
CL_VM_End();
|
||||
|
|
|
@ -247,23 +247,6 @@ void SCR_DrawSmallStringExt( int x, int y, const char *string, float *setColor,
|
|||
re->SetColor( NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
SCR_DrawDemoRecording
|
||||
=================
|
||||
*/
|
||||
void SCR_DrawDemoRecording( void )
|
||||
{
|
||||
char string[1024];
|
||||
fs_offset_t pos;
|
||||
|
||||
if(!(host.developer && cls.demorecording))
|
||||
return;
|
||||
pos = FS_Tell( cls.demofile );
|
||||
com.sprintf( string, "RECORDING %s: %ik", cls.demoname, pos / 1024 );
|
||||
SCR_DrawBigStringColor( 320 - com.strlen( string ) * 8, 80, string, g_color_table[7] );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SCR_UpdateScreen
|
||||
|
@ -278,12 +261,7 @@ void SCR_UpdateScreen( void )
|
|||
|
||||
switch( cls.state )
|
||||
{
|
||||
case ca_cinematic:
|
||||
SCR_DrawCinematic();
|
||||
break;
|
||||
case ca_disconnected:
|
||||
CL_DrawHUD();
|
||||
break;
|
||||
case ca_connecting:
|
||||
case ca_connected:
|
||||
CL_DrawHUD();
|
||||
|
@ -292,7 +270,10 @@ void SCR_UpdateScreen( void )
|
|||
V_CalcRect();
|
||||
V_RenderView();
|
||||
CL_DrawHUD();
|
||||
SCR_DrawDemoRecording();
|
||||
CL_DrawDemoRecording();
|
||||
break;
|
||||
case ca_cinematic:
|
||||
SCR_DrawCinematic();
|
||||
break;
|
||||
default:
|
||||
Host_Error("SCR_UpdateScreen: bad cls.state" );
|
||||
|
|
|
@ -278,16 +278,6 @@ void CL_PrepRefresh( void )
|
|||
|
||||
Msg("CL_PrepRefresh: %s\n", cl.configstrings[CS_NAME] );
|
||||
|
||||
// get splash name
|
||||
Cvar_Set( "cl_levelshot_name", va("background/%s.tga", cl.configstrings[CS_NAME]));
|
||||
if(!FS_FileExists(va("gfx/%s", Cvar_VariableString("cl_levelshot_name"))))
|
||||
{
|
||||
Cvar_Set("cl_levelshot_name", "common/black");
|
||||
cl.make_levelshot = true; // make levelshot
|
||||
}
|
||||
Con_Close();
|
||||
Cvar_SetValue("scr_loading", 0.0f ); // reset progress bar
|
||||
|
||||
// let the render dll load the map
|
||||
FS_FileBase( cl.configstrings[CS_MODELS+1], mapname );
|
||||
SCR_UpdateScreen();
|
||||
|
|
|
@ -162,7 +162,7 @@ of server connections
|
|||
|
||||
typedef enum
|
||||
{
|
||||
ca_uninitialized,
|
||||
ca_uninitialized = 0,
|
||||
ca_disconnected, // not talking to a server
|
||||
ca_connecting, // sending request packets to the server
|
||||
ca_connected, // netchan_t established, waiting for svc_serverdata
|
||||
|
@ -307,7 +307,6 @@ extern cvar_t *cl_run;
|
|||
|
||||
extern cvar_t *cl_anglespeedkey;
|
||||
|
||||
extern cvar_t *cl_shownet;
|
||||
extern cvar_t *cl_showmiss;
|
||||
extern cvar_t *cl_showclamp;
|
||||
|
||||
|
@ -353,9 +352,6 @@ extern entity_state_t cl_parse_entities[MAX_PARSE_ENTITIES];
|
|||
|
||||
//=============================================================================
|
||||
|
||||
extern netadr_t net_from;
|
||||
extern sizebuf_t net_message;
|
||||
|
||||
bool CL_CheckOrDownloadFile (char *filename);
|
||||
|
||||
void CL_AddNetgraph (void);
|
||||
|
@ -474,7 +470,8 @@ char *Key_KeynumToString (int keynum);
|
|||
//
|
||||
// cl_demo.c
|
||||
//
|
||||
void CL_WriteDemoMessage( void );
|
||||
void CL_DrawDemoRecording( void );
|
||||
void CL_WriteDemoMessage( sizebuf_t *msg, int head_size );
|
||||
void CL_ReadDemoMessage( void );
|
||||
void CL_StopPlayback( void );
|
||||
void CL_StopRecord( void );
|
||||
|
|
|
@ -157,12 +157,21 @@ typedef enum
|
|||
|
||||
} host_state;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
RD_NONE = 0,
|
||||
RD_CLIENT,
|
||||
RD_PACKET,
|
||||
|
||||
} e_redirect_t;
|
||||
|
||||
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
|
||||
|
@ -281,7 +290,6 @@ void VM_Cmd_Reset( void );
|
|||
#define PRVM_ResetProg vm->ResetProg
|
||||
#define PRVM_LoadProgs vm->LoadProgs
|
||||
#define PRVM_ProgLoaded vm->ProgLoaded
|
||||
#define PRVM_ExecuteProgram vm->ExecuteProgram
|
||||
#define PRVM_ED_LoadFromFile vm->LoadFromFile
|
||||
#define PRVM_ED_ParseGlobals vm->ParseGlobals
|
||||
#define PRVM_ED_WriteGlobals vm->WriteGlobals
|
||||
|
@ -291,6 +299,7 @@ void VM_Cmd_Reset( void );
|
|||
#define PRVM_ED_Alloc vm->AllocEdict
|
||||
#define PRVM_ED_Free vm->FreeEdict
|
||||
#define PRVM_MEM_IncreaseEdicts vm->IncreaseEdicts
|
||||
#define PRVM_ExecuteProgram( func, name ) vm->ExecuteProgram( func, name, __FILE__, __LINE__ )
|
||||
|
||||
#define PRVM_StackTrace vm->StackTrace
|
||||
#define VM_Warning vm->Warning
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
#include "mathlib.h"
|
||||
|
||||
/*
|
||||
|
||||
packet header
|
||||
packet header ( size in bits )
|
||||
-------------
|
||||
31 sequence
|
||||
1 does this message contain a reliable payload
|
||||
|
@ -67,9 +66,11 @@ cvar_t *net_showpackets;
|
|||
cvar_t *net_showdrop;
|
||||
cvar_t *net_qport;
|
||||
|
||||
netadr_t net_from;
|
||||
sizebuf_t net_message;
|
||||
byte net_message_buffer[MAX_MSGLEN];
|
||||
static char *net_src[2] =
|
||||
{
|
||||
"client",
|
||||
"server"
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -83,16 +84,14 @@ typedef struct
|
|||
int get, send;
|
||||
} loopback_t;
|
||||
|
||||
loopback_t loopbacks[2];
|
||||
|
||||
loopback_t loopbacks[2];
|
||||
|
||||
/*
|
||||
===============
|
||||
Netchan_Init
|
||||
|
||||
===============
|
||||
*/
|
||||
void Netchan_Init (void)
|
||||
void Netchan_Init( void )
|
||||
{
|
||||
int port;
|
||||
|
||||
|
@ -111,7 +110,7 @@ Netchan_Setup
|
|||
called to open a channel to a remote system
|
||||
==============
|
||||
*/
|
||||
void Netchan_Setup (netsrc_t sock, netchan_t *chan, netadr_t adr, int qport)
|
||||
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport )
|
||||
{
|
||||
memset( chan, 0, sizeof(*chan));
|
||||
|
||||
|
@ -122,7 +121,7 @@ void Netchan_Setup (netsrc_t sock, netchan_t *chan, netadr_t adr, int qport)
|
|||
chan->incoming_sequence = 0;
|
||||
chan->outgoing_sequence = 1;
|
||||
|
||||
SZ_Init (&chan->message, chan->message_buf, sizeof(chan->message_buf));
|
||||
MSG_Init( &chan->message, chan->message_buf, sizeof(chan->message_buf));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -132,19 +131,19 @@ Netchan_OutOfBand
|
|||
Sends an out-of-band datagram
|
||||
================
|
||||
*/
|
||||
void Netchan_OutOfBand (int net_socket, netadr_t adr, int length, byte *data)
|
||||
void Netchan_OutOfBand( int net_socket, netadr_t adr, int length, byte *data )
|
||||
{
|
||||
sizebuf_t send;
|
||||
byte send_buf[MAX_MSGLEN];
|
||||
byte send_buf[MAX_MSGLEN];
|
||||
|
||||
// write the packet header
|
||||
SZ_Init (&send, send_buf, sizeof(send_buf));
|
||||
MSG_Init( &send, send_buf, sizeof(send_buf));
|
||||
|
||||
MSG_WriteLong (&send, -1); // -1 sequence means out of band
|
||||
SZ_Write(&send, data, length);
|
||||
MSG_WriteLong( &send, -1 ); // -1 sequence means out of band
|
||||
MSG_WriteData( &send, data, length );
|
||||
|
||||
// send the datagram
|
||||
NET_SendPacket (net_socket, send.cursize, send.data, adr);
|
||||
NET_SendPacket( net_socket, send.cursize, send.data, adr );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -154,16 +153,23 @@ Netchan_OutOfBandPrint
|
|||
Sends a text message in an out-of-band datagram
|
||||
================
|
||||
*/
|
||||
void Netchan_OutOfBandPrint (int net_socket, netadr_t adr, char *format, ...)
|
||||
void Netchan_OutOfBandPrint( int net_socket, netadr_t adr, char *format, ... )
|
||||
{
|
||||
va_list argptr;
|
||||
static char string[MAX_MSGLEN - 4];
|
||||
va_list argptr;
|
||||
char string[MAX_MSGLEN];
|
||||
|
||||
va_start (argptr, format);
|
||||
com.vsprintf (string, format,argptr);
|
||||
va_end (argptr);
|
||||
// set the header
|
||||
string[0] = -1;
|
||||
string[1] = -1;
|
||||
string[2] = -1;
|
||||
string[3] = -1;
|
||||
|
||||
Netchan_OutOfBand (net_socket, adr, strlen(string), (byte *)string);
|
||||
va_start( argptr, format );
|
||||
com.vsprintf( string + 4, format, argptr );
|
||||
va_end( argptr );
|
||||
|
||||
// send the datagram
|
||||
NET_SendPacket( net_socket, com.strlen(string), string, adr );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -173,30 +179,27 @@ Netchan_CanReliable
|
|||
Returns true if the last reliable message has acked
|
||||
================
|
||||
*/
|
||||
bool Netchan_CanReliable (netchan_t *chan)
|
||||
bool Netchan_CanReliable( netchan_t *chan )
|
||||
{
|
||||
if (chan->reliable_length)
|
||||
return false; // waiting for ack
|
||||
if( chan->reliable_length )
|
||||
return false; // waiting for ack
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Netchan_NeedReliable (netchan_t *chan)
|
||||
bool Netchan_NeedReliable( netchan_t *chan )
|
||||
{
|
||||
bool send_reliable;
|
||||
bool send_reliable = false;
|
||||
|
||||
// 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)
|
||||
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)
|
||||
{
|
||||
if( !chan->reliable_length && chan->message.cursize )
|
||||
send_reliable = true;
|
||||
}
|
||||
|
||||
return send_reliable;
|
||||
}
|
||||
|
@ -211,163 +214,133 @@ transmition / retransmition of the reliable messages.
|
|||
A 0 length will still generate a packet and deal with the reliable messages.
|
||||
================
|
||||
*/
|
||||
void Netchan_Transmit (netchan_t *chan, int length, byte *data)
|
||||
void Netchan_Transmit( netchan_t *chan, int length, byte *data )
|
||||
{
|
||||
sizebuf_t send;
|
||||
byte send_buf[MAX_MSGLEN];
|
||||
bool send_reliable;
|
||||
uint w1, w2;
|
||||
sizebuf_t send;
|
||||
static bool overflow = false;
|
||||
byte send_buf[MAX_MSGLEN];
|
||||
bool send_reliable;
|
||||
uint w1, w2;
|
||||
|
||||
// check for message overflow
|
||||
if (chan->message.overflowed)
|
||||
if( chan->message.overflowed )
|
||||
{
|
||||
chan->fatal_error = true;
|
||||
Msg ("%s:Outgoing message overflow\n", NET_AdrToString (chan->remote_address));
|
||||
MsgDev( D_ERROR, "%s:outgoing message overflow\n", NET_AdrToString( chan->remote_address ));
|
||||
return;
|
||||
}
|
||||
|
||||
send_reliable = Netchan_NeedReliable (chan);
|
||||
send_reliable = Netchan_NeedReliable( chan );
|
||||
|
||||
if (!chan->reliable_length && chan->message.cursize)
|
||||
if( !chan->reliable_length && chan->message.cursize )
|
||||
{
|
||||
memcpy (chan->reliable_buf, chan->message_buf, chan->message.cursize);
|
||||
Mem_Copy( 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_Init( &send, send_buf, sizeof(send_buf));
|
||||
MSG_UseHuffman( &send, false );
|
||||
|
||||
w1 = ( chan->outgoing_sequence & ~(1<<31) ) | (send_reliable<<31);
|
||||
w2 = ( chan->incoming_sequence & ~(1<<31) ) | (chan->incoming_reliable_sequence<<31);
|
||||
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);
|
||||
MSG_WriteLong( &send, w1 );
|
||||
MSG_WriteLong( &send, w2 );
|
||||
|
||||
// send the qport if we are a client
|
||||
if (chan->sock == NS_CLIENT) MSG_WriteWord (&send, Cvar_VariableValue( "net_qport" ));
|
||||
if( chan->sock == NS_CLIENT ) MSG_WriteWord( &send, Cvar_VariableValue( "net_qport" ));
|
||||
|
||||
// copy the reliable message to the packet first
|
||||
if (send_reliable)
|
||||
if( send_reliable )
|
||||
{
|
||||
SZ_Write (&send, chan->reliable_buf, chan->reliable_length);
|
||||
MSG_WriteData( &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( send.maxsize - send.cursize >= length )
|
||||
{
|
||||
MSG_WriteData( &send, data, length );
|
||||
overflow = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// don't flood with multiple messages
|
||||
if( !overflow ) MsgDev( D_WARN, "Netchan_Transmit: unreliable msg overflow\n" );
|
||||
overflow = true;
|
||||
}
|
||||
|
||||
// send the datagram
|
||||
NET_SendPacket (chan->sock, send.cursize, send.data, chan->remote_address);
|
||||
NET_SendPacket( chan->sock, send.cursize, send.data, chan->remote_address );
|
||||
|
||||
if( net_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);
|
||||
}
|
||||
MsgDev( D_INFO, "Netchan_Transmit: %4i : %sreliable\n", send.cursize, send_reliable ? "" : "un" );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Netchan_Process
|
||||
|
||||
called when the current net_message is from remote_address
|
||||
modifies net_message so that it points to the packet payload
|
||||
called when the current net message is from remote_address
|
||||
modifies net message so that it points to the packet payload
|
||||
=================
|
||||
*/
|
||||
bool Netchan_Process (netchan_t *chan, sizebuf_t *msg)
|
||||
bool Netchan_Process( netchan_t *chan, sizebuf_t *msg )
|
||||
{
|
||||
uint sequence, sequence_ack;
|
||||
uint reliable_ack, reliable_message;
|
||||
uint reliable_ack, recv_reliable;
|
||||
int qport;
|
||||
|
||||
// get sequence numbers
|
||||
MSG_BeginReading (msg);
|
||||
sequence = MSG_ReadLong (msg);
|
||||
sequence_ack = MSG_ReadLong (msg);
|
||||
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 );
|
||||
|
||||
reliable_message = sequence >> 31;
|
||||
reliable_ack = sequence_ack >> 31;
|
||||
recv_reliable = sequence>>31;
|
||||
reliable_ack = sequence_ack>>31;
|
||||
|
||||
sequence &= ~(1<<31);
|
||||
sequence_ack &= ~(1<<31);
|
||||
|
||||
if (net_showpackets->value)
|
||||
{
|
||||
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( net_showpackets->value )
|
||||
MsgDev( D_INFO, "Netchan_Process: %4i : %sreliable\n", msg->cursize, recv_reliable ? "" : "un" );
|
||||
|
||||
// discard stale or duplicated packets
|
||||
if (sequence <= chan->incoming_sequence)
|
||||
if( sequence <= chan->incoming_sequence )
|
||||
{
|
||||
if (net_showdrop->value)
|
||||
Msg ("%s:Out of order packet %i at %i\n"
|
||||
, NET_AdrToString (chan->remote_address)
|
||||
, sequence
|
||||
, chan->incoming_sequence);
|
||||
if( net_showdrop->value )
|
||||
MsgDev( D_WARN, "%s:Out of order packet\n", NET_AdrToString( chan->remote_address ));
|
||||
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 (net_showdrop->value)
|
||||
Msg ("%s:Dropped %i packets at %i\n"
|
||||
, NET_AdrToString (chan->remote_address)
|
||||
, chan->dropped
|
||||
, sequence);
|
||||
if( net_showdrop->value )
|
||||
MsgDev( D_WARN, "%s:dropped %i packets\n", NET_AdrToString( chan->remote_address ), chan->dropped );
|
||||
}
|
||||
|
||||
//
|
||||
// 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 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 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;
|
||||
}
|
||||
if( recv_reliable ) chan->incoming_reliable_sequence ^= 1;
|
||||
|
||||
// the message can now be read from the current message pointer
|
||||
chan->last_received = Sys_Milliseconds();
|
||||
|
@ -390,10 +363,8 @@ Compares without the port
|
|||
*/
|
||||
bool NET_CompareBaseAdr( netadr_t a, netadr_t b )
|
||||
{
|
||||
if( a.type != b.type )
|
||||
return false;
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return true;
|
||||
if( a.type != b.type ) return false;
|
||||
if( a.type == NA_LOOPBACK ) return true;
|
||||
|
||||
if( a.type == NA_IP )
|
||||
{
|
||||
|
@ -401,6 +372,12 @@ bool NET_CompareBaseAdr( netadr_t a, netadr_t b )
|
|||
return true;
|
||||
return false;
|
||||
}
|
||||
if (a.type == NA_IPX)
|
||||
{
|
||||
if((!memcmp( a.ipx, b.ipx, 10 )))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
MsgDev( D_ERROR, "NET_CompareBaseAdr: bad address type\n" );
|
||||
return false;
|
||||
}
|
||||
|
@ -418,6 +395,12 @@ bool NET_CompareAdr( netadr_t a, netadr_t b )
|
|||
return true;
|
||||
return false;
|
||||
}
|
||||
if( a.type == NA_IPX )
|
||||
{
|
||||
if((memcmp(a.ipx, b.ipx, 10) == 0) && a.port == b.port)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
MsgDev( D_ERROR, "NET_CompareAdr: bad address type\n" );
|
||||
return false;
|
||||
}
|
||||
|
@ -434,7 +417,7 @@ LOOPBACK BUFFERS FOR LOCAL PLAYER
|
|||
|
||||
=============================================================================
|
||||
*/
|
||||
bool NET_GetLoopPacket( netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message )
|
||||
bool NET_GetLoopPacket( netsrc_t sock, netadr_t *from, sizebuf_t *msg )
|
||||
{
|
||||
int i;
|
||||
loopback_t *loop;
|
||||
|
@ -446,14 +429,13 @@ bool NET_GetLoopPacket( netsrc_t sock, netadr_t *net_from, sizebuf_t *net_messag
|
|||
|
||||
if( loop->get >= loop->send )
|
||||
return false;
|
||||
|
||||
i = loop->get & (MAX_LOOPBACK-1);
|
||||
i = loop->get & MASK_LOOPBACK;
|
||||
loop->get++;
|
||||
|
||||
memcpy( net_message->data, loop->msgs[i].data, loop->msgs[i].datalen );
|
||||
net_message->cursize = loop->msgs[i].datalen;
|
||||
memset( net_from, 0, sizeof(*net_from));
|
||||
net_from->type = NA_LOOPBACK;
|
||||
Mem_Copy( msg->data, loop->msgs[i].data, loop->msgs[i].datalen );
|
||||
msg->cursize = loop->msgs[i].datalen;
|
||||
memset( from, 0, sizeof(*from));
|
||||
from->type = NA_LOOPBACK;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
@ -465,7 +447,7 @@ void NET_SendLoopPacket( netsrc_t sock, int length, void *data, netadr_t to )
|
|||
|
||||
loop = &loopbacks[sock^1];
|
||||
|
||||
i = loop->send & (MAX_LOOPBACK-1);
|
||||
i = loop->send & MASK_LOOPBACK;
|
||||
loop->send++;
|
||||
|
||||
Mem_Copy( loop->msgs[i].data, data, length );
|
||||
|
@ -491,7 +473,7 @@ void NET_SendPacket( netsrc_t sock, int length, void *data, netadr_t to )
|
|||
return;
|
||||
}
|
||||
|
||||
if( to.type == NA_NONE ) return;
|
||||
if( to.type == NA_BAD ) return;
|
||||
Sys_SendPacket( length, data, to );
|
||||
}
|
||||
|
||||
|
@ -535,14 +517,14 @@ bool NET_StringToAdr( const char *s, netadr_t *a )
|
|||
|
||||
if( !r )
|
||||
{
|
||||
a->type = NA_NONE;
|
||||
a->type = NA_BAD;
|
||||
return false;
|
||||
}
|
||||
|
||||
// inet_addr returns this if out of range
|
||||
if( a->ip[0] == 255 && a->ip[1] == 255 && a->ip[2] == 255 && a->ip[3] == 255 )
|
||||
{
|
||||
a->type = NA_NONE;
|
||||
a->type = NA_BAD;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -141,32 +141,6 @@ typedef enum
|
|||
|
||||
#define U_MOREBITS4 (1<<31) // read one additional byte
|
||||
|
||||
// entity_state_t communication
|
||||
typedef struct entity_state_s
|
||||
{
|
||||
uint number; // edict index
|
||||
|
||||
vec3_t origin;
|
||||
vec3_t angles;
|
||||
vec3_t old_origin; // for lerping animation
|
||||
int modelindex;
|
||||
int soundindex;
|
||||
int weaponmodel;
|
||||
|
||||
short skin; // skin for studiomodels
|
||||
float frame; // % playback position in animation sequences (0..512)
|
||||
byte body; // sub-model selection for studiomodels
|
||||
byte sequence; // animation sequence (0 - 255)
|
||||
uint effects; // PGM - we're filling it, so it needs to be unsigned
|
||||
int renderfx;
|
||||
int solid; // for client side prediction, 8*(bits 0-4) is x/y radius
|
||||
// 8*(bits 5-9) is z down distance, 8(bits10-15) is z up
|
||||
// gi.linkentity sets this properly
|
||||
float alpha; // alpha value
|
||||
float animtime; // auto-animating time
|
||||
|
||||
} entity_state_t;
|
||||
|
||||
/*
|
||||
==========================================================
|
||||
|
||||
|
@ -228,32 +202,30 @@ typedef struct entity_state_s
|
|||
Handles byte ordering and avoids alignment errors
|
||||
==============================================================================
|
||||
*/
|
||||
#define SZ_GetSpace(buf, len) _SZ_GetSpace(buf, len, __FILE__, __LINE__ )
|
||||
#define SZ_Write(buf, data, len) _SZ_Write(buf, data, len, __FILE__, __LINE__ )
|
||||
void SZ_Init (sizebuf_t *buf, byte *data, int length);
|
||||
void SZ_Clear (sizebuf_t *buf);
|
||||
void *_SZ_GetSpace (sizebuf_t *buf, int length, const char *filename, int fileline);
|
||||
void _SZ_Write (sizebuf_t *buf, const void *data, int length, const char *filename, int fileline);
|
||||
void SZ_Print (sizebuf_t *buf, char *data); // strcats onto the sizebuf
|
||||
|
||||
void _MSG_Begin ( int dest, const char *filename, int fileline );
|
||||
void _MSG_WriteChar (sizebuf_t *sb, int c, const char *filename, int fileline);
|
||||
void _MSG_WriteByte (sizebuf_t *sb, int c, const char *filename, int fileline);
|
||||
void _MSG_WriteShort (sizebuf_t *sb, int c, const char *filename, int fileline);
|
||||
void _MSG_WriteWord (sizebuf_t *sb, int c, const char *filename, int fileline);
|
||||
void _MSG_WriteLong (sizebuf_t *sb, int c, const char *filename, int fileline);
|
||||
void _MSG_WriteFloat (sizebuf_t *sb, float f, const char *filename, int fileline);
|
||||
void _MSG_WriteString (sizebuf_t *sb, const char *s, const char *filename, int fileline);
|
||||
void _MSG_WriteCoord16(sizebuf_t *sb, int f, const char *filename, int fileline);
|
||||
void _MSG_WriteCoord32(sizebuf_t *sb, float f, const char *filename, int fileline);
|
||||
void _MSG_WriteAngle16(sizebuf_t *sb, float f, const char *filename, int fileline);
|
||||
void _MSG_WriteAngle32(sizebuf_t *sb, float f, const char *filename, int fileline);
|
||||
void _MSG_WritePos16(sizebuf_t *sb, int pos[3], const char *filename, int fileline);
|
||||
void _MSG_WritePos32(sizebuf_t *sb, vec3_t pos, const char *filename, int fileline);
|
||||
void _MSG_WriteUnterminatedString (sizebuf_t *sb, const char *s, const char *filename, int fileline);
|
||||
void _MSG_WriteDeltaUsercmd (sizebuf_t *sb, struct usercmd_s *from, struct usercmd_s *cmd, const char *filename, int fileline);
|
||||
void _MSG_WriteDeltaEntity (struct entity_state_s *from, struct entity_state_s *to, sizebuf_t *msg, bool force, bool newentity, const char *filename, int fileline);
|
||||
void _MSG_Send (msgtype_t to, vec3_t origin, edict_t *ent, const char *filename, int fileline);
|
||||
void MSG_Init( sizebuf_t *buf, byte *data, size_t length );
|
||||
void MSG_Clear( sizebuf_t *buf );
|
||||
void MSG_UseHuffman( sizebuf_t *buf, bool state );
|
||||
void _MSG_WriteBits( sizebuf_t *msg, int value, int bits, const char *filename, int fileline );
|
||||
int _MSG_ReadBits( sizebuf_t *msg, int bits, const char *filename, int fileline );
|
||||
void _MSG_Begin( int dest, const char *filename, int fileline );
|
||||
void _MSG_WriteChar( sizebuf_t *sb, int c, const char *filename, int fileline );
|
||||
void _MSG_WriteByte( sizebuf_t *sb, int c, const char *filename, int fileline );
|
||||
void _MSG_WriteShort( sizebuf_t *sb, int c, const char *filename, int fileline );
|
||||
void _MSG_WriteWord( sizebuf_t *sb, int c, const char *filename, int fileline );
|
||||
void _MSG_WriteLong( sizebuf_t *sb, int c, const char *filename, int fileline );
|
||||
void _MSG_WriteFloat( sizebuf_t *sb, float f, const char *filename, int fileline );
|
||||
void _MSG_WriteString( sizebuf_t *sb, const char *s, const char *filename, int fileline );
|
||||
void _MSG_WriteCoord16( sizebuf_t *sb, int f, const char *filename, int fileline );
|
||||
void _MSG_WriteCoord32( sizebuf_t *sb, float f, const char *filename, int fileline );
|
||||
void _MSG_WriteAngle16( sizebuf_t *sb, float f, const char *filename, int fileline );
|
||||
void _MSG_WriteAngle32( sizebuf_t *sb, float f, const char *filename, int fileline );
|
||||
void _MSG_WritePos16( sizebuf_t *sb, int pos[3], const char *filename, int fileline );
|
||||
void _MSG_WritePos32( sizebuf_t *sb, vec3_t pos, const char *filename, int fileline );
|
||||
void _MSG_WriteData( sizebuf_t *sb, const void *data, size_t length, const char *filename, int fileline );
|
||||
void _MSG_WriteDeltaUsercmd( sizebuf_t *sb, struct usercmd_s *from, struct usercmd_s *cmd, const char *filename, const int fileline );
|
||||
void _MSG_WriteDeltaEntity( struct entity_state_s *from, struct entity_state_s *to, sizebuf_t *msg, bool force, const char *filename, int fileline );
|
||||
void _MSG_Send( msgtype_t to, vec3_t origin, edict_t *ent, const char *filename, int fileline );
|
||||
|
||||
#define MSG_Begin( x ) _MSG_Begin( x, __FILE__, __LINE__);
|
||||
#define MSG_WriteChar(x,y) _MSG_WriteChar (x, y, __FILE__, __LINE__);
|
||||
|
@ -269,29 +241,33 @@ void _MSG_Send (msgtype_t to, vec3_t origin, edict_t *ent, const char *filename,
|
|||
#define MSG_WriteAngle32(x, y) _MSG_WriteAngle32(x, y, __FILE__, __LINE__);
|
||||
#define MSG_WritePos16(x, y) _MSG_WritePos16(x, y, __FILE__, __LINE__);
|
||||
#define MSG_WritePos32(x, y) _MSG_WritePos32(x, y, __FILE__, __LINE__);
|
||||
#define MSG_WriteUnterminatedString(x, y) _MSG_WriteUnterminatedString (x, y, __FILE__, __LINE__);
|
||||
#define MSG_WriteData(x,y,z) _MSG_WriteData (x, y, z, __FILE__, __LINE__);
|
||||
#define MSG_WriteDeltaUsercmd(x, y, z) _MSG_WriteDeltaUsercmd (x, y, z, __FILE__, __LINE__);
|
||||
#define MSG_WriteDeltaEntity(x, y, z, t, m) _MSG_WriteDeltaEntity (x, y, z, t, m, __FILE__, __LINE__);
|
||||
#define MSG_WriteDeltaEntity(x, y, z, t ) _MSG_WriteDeltaEntity (x, y, z, t, __FILE__, __LINE__);
|
||||
#define MSG_WriteBits( buf, value, bits ) _MSG_WriteBits( buf, value, bits, __FILE__, __LINE__ )
|
||||
#define MSG_ReadBits( buf, bits ) _MSG_ReadBits( buf, bits, __FILE__, __LINE__ )
|
||||
#define MSG_Send(x, y, z) _MSG_Send(x, y, z, __FILE__, __LINE__);
|
||||
|
||||
void MSG_BeginReading (sizebuf_t *sb);
|
||||
int MSG_ReadChar (sizebuf_t *sb);
|
||||
int MSG_ReadByte (sizebuf_t *sb);
|
||||
int MSG_ReadShort (sizebuf_t *sb);
|
||||
int MSG_ReadLong (sizebuf_t *sb);
|
||||
float MSG_ReadFloat (sizebuf_t *sb);
|
||||
char *MSG_ReadString (sizebuf_t *sb);
|
||||
char *MSG_ReadStringLine (sizebuf_t *sb);
|
||||
float MSG_ReadCoord16(sizebuf_t *sb);
|
||||
float MSG_ReadCoord32(sizebuf_t *sb);
|
||||
float MSG_ReadAngle16(sizebuf_t *sb);
|
||||
float MSG_ReadAngle32(sizebuf_t *sb);
|
||||
void MSG_ReadPos16(sizebuf_t *sb, int pos[3]);
|
||||
void MSG_ReadPos32(sizebuf_t *sb, vec3_t pos);
|
||||
void MSG_ReadData (sizebuf_t *sb, void *buffer, int size);
|
||||
void MSG_ReadDeltaUsercmd (sizebuf_t *sb, struct usercmd_s *from, struct usercmd_s *cmd);
|
||||
void MSG_ReadDeltaEntity(sizebuf_t *sb, entity_state_t *from, entity_state_t *to, int number, int bits);
|
||||
|
||||
int MSG_ReadChar( sizebuf_t *sb );
|
||||
int MSG_ReadByte( sizebuf_t *sb );
|
||||
int MSG_ReadShort( sizebuf_t *sb );
|
||||
int MSG_ReadWord( sizebuf_t *sb );
|
||||
int MSG_ReadLong( sizebuf_t *sb );
|
||||
float MSG_ReadFloat( sizebuf_t *sb );
|
||||
char *MSG_ReadString( sizebuf_t *sb );
|
||||
char *MSG_ReadStringLine( sizebuf_t *sb );
|
||||
long MSG_ReadCoord16( sizebuf_t *sb );
|
||||
float MSG_ReadCoord32( sizebuf_t *sb );
|
||||
float MSG_ReadAngle16( sizebuf_t *sb );
|
||||
float MSG_ReadAngle32( sizebuf_t *sb );
|
||||
void MSG_ReadPos16( sizebuf_t *sb, int pos[3] );
|
||||
void MSG_ReadPos32( sizebuf_t *sb, vec3_t pos );
|
||||
void MSG_ReadData( sizebuf_t *sb, void *buffer, size_t size );
|
||||
void MSG_ReadDeltaUsercmd( sizebuf_t *sb, usercmd_t *from, usercmd_t *cmd );
|
||||
void MSG_ReadDeltaEntity( sizebuf_t *sb, entity_state_t *from, entity_state_t *to, int number );
|
||||
void MSG_WriteDeltaPlayerstate( player_state_t *from, player_state_t *to, sizebuf_t *msg );
|
||||
void MSG_ReadDeltaPlayerstate( sizebuf_t *msg, player_state_t *from, player_state_t *to );
|
||||
/*
|
||||
==============================================================
|
||||
|
||||
|
@ -299,7 +275,7 @@ NET
|
|||
|
||||
==============================================================
|
||||
*/
|
||||
bool NET_GetLoopPacket( netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message );
|
||||
bool NET_GetLoopPacket( netsrc_t sock, netadr_t *from, sizebuf_t *msg );
|
||||
void NET_SendPacket( netsrc_t sock, int length, void *data, netadr_t to );
|
||||
bool NET_GetPacket( netsrc_t sock, netadr_t *from, sizebuf_t *msg );
|
||||
bool NET_StringToAdr( const char *s, netadr_t *a );
|
||||
|
@ -346,10 +322,6 @@ typedef struct netchan_s
|
|||
|
||||
} netchan_t;
|
||||
|
||||
extern netadr_t net_from;
|
||||
extern sizebuf_t net_message;
|
||||
extern byte net_message_buffer[MAX_MSGLEN];
|
||||
|
||||
#define PROTOCOL_VERSION 35
|
||||
#define PORT_MASTER 27900
|
||||
#define PORT_CLIENT 27901
|
||||
|
@ -366,4 +338,6 @@ void Netchan_OutOfBandPrint (int net_socket, netadr_t adr, char *format, ...);
|
|||
bool Netchan_Process (netchan_t *chan, sizebuf_t *msg);
|
||||
bool Netchan_CanReliable (netchan_t *chan);
|
||||
|
||||
extern cvar_t *cl_shownet;
|
||||
|
||||
#endif//NET_MSG_H
|
|
@ -242,10 +242,6 @@ SOURCE=.\server\sv_studio.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\server\sv_user.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\server\sv_world.c
|
||||
# End Source File
|
||||
# End Group
|
||||
|
|
|
@ -359,7 +359,7 @@ dword Host_EventLoop( void )
|
|||
byte bufData[MAX_MSGLEN];
|
||||
sizebuf_t buf;
|
||||
|
||||
SZ_Init( &buf, bufData, sizeof( bufData ));
|
||||
MSG_Init( &buf, bufData, sizeof( bufData ));
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
|
@ -368,14 +368,14 @@ dword Host_EventLoop( void )
|
|||
{
|
||||
case SE_NONE:
|
||||
// manually send packet events for the loopback channel
|
||||
/*while( NET_GetLoopPacket( NS_CLIENT, &ev_from, &buf ))
|
||||
while( NET_GetLoopPacket( NS_CLIENT, &ev_from, &buf ))
|
||||
{
|
||||
CL_PacketEvent( ev_from, &buf );
|
||||
}
|
||||
while( NET_GetLoopPacket( NS_SERVER, &ev_from, &buf ))
|
||||
{
|
||||
SV_PacketEvent( ev_from, &buf );
|
||||
}*/
|
||||
}
|
||||
return ev.time;
|
||||
case SE_KEY:
|
||||
Key_Event( ev.value[0], ev.value[1], ev.time );
|
||||
|
@ -387,8 +387,9 @@ dword Host_EventLoop( void )
|
|||
CL_MouseEvent( ev.value[0], ev.value[1], ev.time );
|
||||
break;
|
||||
case SE_CONSOLE:
|
||||
Cbuf_AddText( va( "%s\n", ev.data ));
|
||||
Cbuf_AddText(va( "%s\n", ev.data ));
|
||||
break;
|
||||
case SE_PACKET:
|
||||
ev_from = *(netadr_t *)ev.data;
|
||||
buf.cursize = ev.length - sizeof( ev_from );
|
||||
|
||||
|
@ -404,6 +405,7 @@ dword Host_EventLoop( void )
|
|||
Mem_Copy( buf.data, (byte *)((netadr_t *)ev.data + 1), buf.cursize );
|
||||
if ( svs.initialized ) SV_PacketEvent( ev_from, &buf );
|
||||
else CL_PacketEvent( ev_from, &buf );
|
||||
break;
|
||||
default:
|
||||
Host_Error( "Host_EventLoop: bad event type %i", ev.type );
|
||||
break;
|
||||
|
@ -656,17 +658,17 @@ If no console is visible, the text will appear at the top of the game window
|
|||
*/
|
||||
void Host_Print( const char *txt )
|
||||
{
|
||||
if(host.rd.target)
|
||||
if( host.rd.target )
|
||||
{
|
||||
if((strlen (txt) + strlen(host.rd.buffer)) > (host.rd.buffersize - 1))
|
||||
if((com.strlen (txt) + com.strlen(host.rd.buffer)) > (host.rd.buffersize - 1))
|
||||
{
|
||||
if(host.rd.flush)
|
||||
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;
|
||||
}
|
||||
}
|
||||
com.strcat (host.rd.buffer, txt);
|
||||
com.strcat( host.rd.buffer, txt );
|
||||
return;
|
||||
}
|
||||
Con_Print( txt ); // echo to client console
|
||||
|
|
|
@ -30,7 +30,7 @@ void IN_StartupMouse( void )
|
|||
cvar_t *cv;
|
||||
|
||||
cv = Cvar_Get( "in_initmouse", "1", CVAR_SYSTEMINFO, "allow mouse device" );
|
||||
if ( !cv->value ) return;
|
||||
if( !cv->value ) return;
|
||||
|
||||
in_mouse_buttons = 3;
|
||||
in_mouseparmsvalid = SystemParametersInfo( SPI_GETMOUSE, 0, in_originalmouseparms, 0 );
|
||||
|
|
|
@ -93,13 +93,14 @@ typedef struct server_s
|
|||
|
||||
typedef struct
|
||||
{
|
||||
player_state_t ps;
|
||||
int areabytes;
|
||||
byte areabits[MAX_MAP_AREAS/8]; // portalarea visibility bits
|
||||
player_state_t ps;
|
||||
int num_entities;
|
||||
int first_entity; // into the circular sv_packet_entities[]
|
||||
int senttime; // for ping calculations
|
||||
|
||||
int msg_sent; // time the message was transmitted
|
||||
int msg_size; // used to rate drop packets
|
||||
int latency; // message latency time
|
||||
} client_frame_t;
|
||||
|
||||
typedef struct sv_client_s
|
||||
|
@ -112,12 +113,8 @@ typedef struct sv_client_s
|
|||
int lastframe; // for delta compression
|
||||
usercmd_t lastcmd; // for filling in big drops
|
||||
|
||||
int commandMsec; // every seconds this is reset, if user
|
||||
// commands exhaust it, assume time cheating
|
||||
int frame_latency[LATENCY_COUNTS];
|
||||
int ping;
|
||||
|
||||
int message_size[RATE_MESSAGES]; // used to rate drop packets
|
||||
int rate;
|
||||
int surpressCount; // number of messages rate supressed
|
||||
|
||||
|
@ -164,7 +161,7 @@ typedef struct
|
|||
netadr_t adr;
|
||||
int challenge;
|
||||
int time;
|
||||
|
||||
bool connected;
|
||||
} challenge_t;
|
||||
|
||||
typedef struct
|
||||
|
@ -189,9 +186,6 @@ typedef struct
|
|||
|
||||
//=============================================================================
|
||||
|
||||
extern netadr_t net_from;
|
||||
extern sizebuf_t net_message;
|
||||
|
||||
extern netadr_t master_adr[MAX_MASTERS]; // address of the master server
|
||||
|
||||
extern server_static_t svs; // persistant server info
|
||||
|
@ -205,10 +199,12 @@ extern cvar_t *sv_maxvelocity;
|
|||
extern cvar_t *sv_gravity;
|
||||
extern cvar_t *sv_fps; // running server at
|
||||
extern cvar_t *sv_enforcetime;
|
||||
extern cvar_t *sv_reconnect_limit;
|
||||
extern cvar_t *allow_download;
|
||||
extern cvar_t *rcon_password;
|
||||
extern cvar_t *hostname;
|
||||
|
||||
extern sv_client_t *sv_client;
|
||||
extern edict_t *sv_player;
|
||||
|
||||
|
||||
//===========================================================
|
||||
//
|
||||
|
@ -256,13 +252,6 @@ bool SV_CheckBottom (edict_t *ent);
|
|||
//
|
||||
// sv_send.c
|
||||
//
|
||||
typedef enum {RD_NONE, RD_CLIENT, RD_PACKET} redirect_t;
|
||||
#define SV_OUTPUTBUF_LENGTH (MAX_MSGLEN - 16)
|
||||
|
||||
extern char sv_outputbuf[SV_OUTPUTBUF_LENGTH];
|
||||
|
||||
void SV_FlushRedirect (int sv_redirected, char *outputbuf);
|
||||
|
||||
void SV_SendClientMessages (void);
|
||||
void SV_AmbientSound( edict_t *entity, int soundindex, float volume, float attenuation );
|
||||
void SV_StartSound (vec3_t origin, edict_t *entity, int channel, int index, float vol, float attn, float timeofs);
|
||||
|
@ -271,10 +260,14 @@ void SV_BroadcastPrintf (int level, char *fmt, ...);
|
|||
void SV_BroadcastCommand (char *fmt, ...);
|
||||
|
||||
//
|
||||
// sv_user.c
|
||||
// sv_client.c
|
||||
//
|
||||
void SV_Nextserver (void);
|
||||
void SV_ExecuteClientMessage (sv_client_t *cl);
|
||||
char *SV_StatusString( void );
|
||||
void SV_GetChallenge( netadr_t from );
|
||||
void SV_DirectConnect( netadr_t from );
|
||||
void SV_PutClientInServer( edict_t *ent );
|
||||
void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg );
|
||||
void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg );
|
||||
|
||||
//
|
||||
// sv_ccmds.c
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6,6 +6,8 @@
|
|||
#include "common.h"
|
||||
#include "server.h"
|
||||
|
||||
sv_client_t *sv_client; // current client
|
||||
|
||||
/*
|
||||
====================
|
||||
SV_SetMaster_f
|
||||
|
@ -78,7 +80,6 @@ bool SV_SetPlayer( void )
|
|||
return false;
|
||||
}
|
||||
sv_client = &svs.clients[idnum];
|
||||
sv_player = sv_client->edict;
|
||||
if (!sv_client->state)
|
||||
{
|
||||
Msg("Client %i is not active\n", idnum);
|
||||
|
@ -94,7 +95,6 @@ bool SV_SetPlayer( void )
|
|||
if (!strcmp(cl->name, s))
|
||||
{
|
||||
sv_client = cl;
|
||||
sv_player = sv_client->edict;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -355,7 +355,7 @@ void SV_Status_f( void )
|
|||
int j, l, ping;
|
||||
char *s;
|
||||
|
||||
if (!cl->state) continue;
|
||||
if( !cl->state ) continue;
|
||||
|
||||
Msg("%3i ", i);
|
||||
Msg("%5i ", cl->edict->priv.sv->client->ps.stats[STAT_FRAGS]);
|
||||
|
@ -371,7 +371,7 @@ void SV_Status_f( void )
|
|||
Msg("%s", cl->name );
|
||||
l = 16 - com.strlen(cl->name);
|
||||
for (j = 0; j < l; j++) Msg (" ");
|
||||
Msg ("%7i ", svs.realtime - cl->lastmessage );
|
||||
Msg ("%9i ", svs.realtime - cl->lastmessage );
|
||||
s = NET_AdrToString ( cl->netchan.remote_address);
|
||||
Msg ("%s", s);
|
||||
l = 22 - strlen(s);
|
||||
|
|
|
@ -115,7 +115,7 @@ void SV_EmitPacketEntities (client_frame_t *from, client_frame_t *to, sizebuf_t
|
|||
// in any bytes being emited if the entity has not changed at all
|
||||
// note that players are always 'newentities', this updates their oldorigin always
|
||||
// and prevents warping
|
||||
MSG_WriteDeltaEntity( oldent, newent, msg, false, newent->number <= maxclients->value );
|
||||
MSG_WriteDeltaEntity( oldent, newent, msg, false );
|
||||
oldindex++;
|
||||
newindex++;
|
||||
continue;
|
||||
|
@ -123,7 +123,7 @@ void SV_EmitPacketEntities (client_frame_t *from, client_frame_t *to, sizebuf_t
|
|||
|
||||
if( newnum < oldnum )
|
||||
{ // this is a new entity, send it from the baseline
|
||||
MSG_WriteDeltaEntity (&sv.baselines[newnum], newent, msg, true, true);
|
||||
MSG_WriteDeltaEntity (&sv.baselines[newnum], newent, msg, true );
|
||||
newindex++;
|
||||
continue;
|
||||
}
|
||||
|
@ -339,8 +339,8 @@ void SV_WriteFrameToClient (sv_client_t *client, sizebuf_t *msg)
|
|||
client->surpressCount = 0;
|
||||
|
||||
// send over the areabits
|
||||
MSG_WriteByte (msg, frame->areabytes);
|
||||
SZ_Write (msg, frame->areabits, frame->areabytes);
|
||||
MSG_WriteByte(msg, frame->areabytes);
|
||||
MSG_WriteData(msg, frame->areabits, frame->areabytes);
|
||||
|
||||
// delta encode the playerstate
|
||||
SV_WritePlayerstateToClient (oldframe, frame, msg);
|
||||
|
@ -387,7 +387,7 @@ void SV_BuildClientFrame( sv_client_t *client )
|
|||
// this is the frame we are creating
|
||||
frame = &client->frames[sv.framenum & UPDATE_MASK];
|
||||
|
||||
frame->senttime = svs.realtime; // save it for ping calc later
|
||||
frame->msg_sent = svs.realtime; // save it for ping calc later
|
||||
|
||||
// find the client's PVS
|
||||
VectorScale( clent->priv.sv->client->ps.origin, CL_COORD_FRAC, org );
|
||||
|
|
|
@ -53,7 +53,7 @@ int SV_FindIndex (const char *name, int start, int end, bool create)
|
|||
if (sv.state != ss_loading)
|
||||
{
|
||||
// send the update to everyone
|
||||
SZ_Clear (&sv.multicast);
|
||||
MSG_Clear( &sv.multicast );
|
||||
MSG_Begin(svc_configstring);
|
||||
MSG_WriteShort (&sv.multicast, start + i);
|
||||
MSG_WriteString (&sv.multicast, (char *)name);
|
||||
|
@ -164,7 +164,7 @@ void SV_SpawnServer (char *server, char *savename, sv_state_t serverstate )
|
|||
com.sprintf( sv.configstrings[CS_AIRACCEL], "%g", sv_airaccelerate->value );
|
||||
else com.strcpy( sv.configstrings[CS_AIRACCEL], "0" );
|
||||
|
||||
SZ_Init(&sv.multicast, sv.multicast_buf, sizeof(sv.multicast_buf));
|
||||
MSG_Init(&sv.multicast, sv.multicast_buf, sizeof(sv.multicast_buf));
|
||||
com.strcpy( sv.name, server );
|
||||
|
||||
SV_VM_Begin();
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
|
||||
netadr_t master_adr[MAX_MASTERS]; // address of group servers
|
||||
|
||||
sv_client_t *sv_client; // current client
|
||||
|
||||
cvar_t *sv_paused;
|
||||
cvar_t *sv_fps;
|
||||
cvar_t *sv_enforcetime;
|
||||
|
@ -39,459 +37,6 @@ cvar_t *sv_reconnect_limit;// minimum seconds between connect messages
|
|||
|
||||
void Master_Shutdown (void);
|
||||
|
||||
static int rd_target;
|
||||
static char *rd_buffer;
|
||||
static int rd_buffersize;
|
||||
static void (*rd_flush)(int target, char *buffer);
|
||||
|
||||
//============================================================================
|
||||
void SVC_BeginRedirect (int target, char *buffer, int buffersize, void (*flush))
|
||||
{
|
||||
if (!target || !buffer || !buffersize || !flush) return;
|
||||
|
||||
host.rd.target = target;
|
||||
host.rd.buffer = buffer;
|
||||
host.rd.buffersize = buffersize;
|
||||
host.rd.flush = flush;
|
||||
|
||||
*host.rd.buffer = 0;
|
||||
}
|
||||
|
||||
void SVC_EndRedirect (void)
|
||||
{
|
||||
host.rd.flush(rd_target, rd_buffer);
|
||||
|
||||
host.rd.target = 0;
|
||||
host.rd.buffer = NULL;
|
||||
host.rd.buffersize = 0;
|
||||
host.rd.flush = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
SV_DropClient
|
||||
|
||||
Called when the player is totally leaving the server, either willingly
|
||||
or unwillingly. This is NOT called if the entire server is quiting
|
||||
or crashing.
|
||||
=====================
|
||||
*/
|
||||
void SV_DropClient (sv_client_t *drop)
|
||||
{
|
||||
// add the disconnect
|
||||
MSG_WriteByte (&drop->netchan.message, svc_disconnect);
|
||||
|
||||
if (drop->state == cs_spawned)
|
||||
{
|
||||
// call the prog function for removing a client
|
||||
// this will remove the body, among other things
|
||||
SV_ClientDisconnect(drop->edict);
|
||||
}
|
||||
|
||||
if (drop->download)
|
||||
{
|
||||
drop->download = NULL;
|
||||
}
|
||||
|
||||
drop->state = cs_zombie; // become free in a few seconds
|
||||
drop->name[0] = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
CONNECTIONLESS COMMANDS
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
===============
|
||||
SV_StatusString
|
||||
|
||||
Builds the string that is sent as heartbeats and status replies
|
||||
===============
|
||||
*/
|
||||
char *SV_StatusString (void)
|
||||
{
|
||||
char player[1024];
|
||||
static char status[MAX_MSGLEN - 16];
|
||||
int i;
|
||||
sv_client_t *cl;
|
||||
int statusLength;
|
||||
int playerLength;
|
||||
|
||||
com.strcpy( status, Cvar_Serverinfo());
|
||||
com.strcat( status, "\n" );
|
||||
statusLength = strlen(status);
|
||||
|
||||
for( i = 0; i < maxclients->value; i++ )
|
||||
{
|
||||
cl = &svs.clients[i];
|
||||
if (cl->state == cs_connected || cl->state == cs_spawned )
|
||||
{
|
||||
com.sprintf (player, "%i %i \"%s\"\n", cl->edict->priv.sv->client->ps.stats[STAT_FRAGS], cl->ping, cl->name);
|
||||
playerLength = strlen(player);
|
||||
if( statusLength + playerLength >= sizeof(status))
|
||||
break; // can't hold any more
|
||||
com.strcpy( status + statusLength, player );
|
||||
statusLength += playerLength;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SVC_Status
|
||||
|
||||
Responds with all the info that qplug or qspy can see
|
||||
================
|
||||
*/
|
||||
void SVC_Status (void)
|
||||
{
|
||||
Netchan_OutOfBandPrint(NS_SERVER, net_from, "print\n%s", SV_StatusString());
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SVC_Ack
|
||||
|
||||
================
|
||||
*/
|
||||
void SVC_Ack (void)
|
||||
{
|
||||
Msg ("Ping acknowledge from %s\n", NET_AdrToString(net_from));
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SVC_Info
|
||||
|
||||
Responds with short info for broadcast scans
|
||||
The second parameter should be the current protocol version number.
|
||||
================
|
||||
*/
|
||||
void SVC_Info (void)
|
||||
{
|
||||
char string[64];
|
||||
int i, count;
|
||||
int version;
|
||||
|
||||
if (maxclients->value == 1)
|
||||
return; // ignore in single player
|
||||
|
||||
version = atoi (Cmd_Argv(1));
|
||||
|
||||
if (version != PROTOCOL_VERSION)
|
||||
com.sprintf (string, "%s: wrong version\n", hostname->string, sizeof(string));
|
||||
else
|
||||
{
|
||||
count = 0;
|
||||
for (i=0 ; i<maxclients->value ; i++)
|
||||
if (svs.clients[i].state >= cs_connected)
|
||||
count++;
|
||||
|
||||
com.sprintf (string, "%16s %8s %2i/%2i\n", hostname->string, sv.name, count, (int)maxclients->value);
|
||||
}
|
||||
|
||||
Netchan_OutOfBandPrint(NS_SERVER, net_from, "info\n%s", string);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SVC_Ping
|
||||
|
||||
Just responds with an acknowledgement
|
||||
================
|
||||
*/
|
||||
void SVC_Ping (void)
|
||||
{
|
||||
Netchan_OutOfBandPrint (NS_SERVER, net_from, "ack");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
SVC_GetChallenge
|
||||
|
||||
Returns a challenge number that can be used
|
||||
in a subsequent client_connect command.
|
||||
We do this to prevent denial of service attacks that
|
||||
flood the server with invalid connection IPs. With a
|
||||
challenge, they must give a valid IP address.
|
||||
=================
|
||||
*/
|
||||
void SVC_GetChallenge (void)
|
||||
{
|
||||
int i;
|
||||
int oldest;
|
||||
int oldestTime;
|
||||
int curtime;
|
||||
|
||||
oldest = 0;
|
||||
oldestTime = 0x7fffffff;
|
||||
curtime = Sys_Milliseconds();
|
||||
|
||||
// see if we already have a challenge for this ip
|
||||
for (i = 0 ; i < MAX_CHALLENGES ; i++)
|
||||
{
|
||||
if (NET_CompareBaseAdr (net_from, svs.challenges[i].adr))
|
||||
break;
|
||||
if (svs.challenges[i].time < oldestTime)
|
||||
{
|
||||
oldestTime = svs.challenges[i].time;
|
||||
oldest = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == MAX_CHALLENGES)
|
||||
{
|
||||
// overwrite the oldest
|
||||
svs.challenges[oldest].challenge = rand() & 0x7fff;
|
||||
svs.challenges[oldest].adr = net_from;
|
||||
svs.challenges[oldest].time = curtime;
|
||||
i = oldest;
|
||||
}
|
||||
|
||||
// send it back
|
||||
Netchan_OutOfBandPrint (NS_SERVER, net_from, "challenge %i", svs.challenges[i].challenge);
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SVC_DirectConnect
|
||||
|
||||
A connection request that did not come from the master
|
||||
==================
|
||||
*/
|
||||
void SVC_DirectConnect( void )
|
||||
{
|
||||
char userinfo[MAX_INFO_STRING];
|
||||
netadr_t adr;
|
||||
int i;
|
||||
sv_client_t *cl, *newcl;
|
||||
sv_client_t temp;
|
||||
edict_t *ent;
|
||||
int edictnum;
|
||||
int version;
|
||||
int qport;
|
||||
int challenge;
|
||||
|
||||
adr = net_from;
|
||||
|
||||
MsgDev (D_INFO, "SVC_DirectConnect()\n");
|
||||
|
||||
version = atoi(Cmd_Argv(1));
|
||||
if (version != PROTOCOL_VERSION)
|
||||
{
|
||||
Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nServer is version %4.2f.\n", GI->version );
|
||||
MsgDev( D_ERROR, "SVC_DirectConnect: rejected connect from version %i\n", version);
|
||||
return;
|
||||
}
|
||||
|
||||
qport = atoi(Cmd_Argv(2));
|
||||
challenge = atoi(Cmd_Argv(3));
|
||||
|
||||
strncpy (userinfo, Cmd_Argv(4), sizeof(userinfo)-1);
|
||||
userinfo[sizeof(userinfo) - 1] = 0;
|
||||
|
||||
// force the IP key/value pair so the game can filter based on ip
|
||||
Info_SetValueForKey (userinfo, "ip", NET_AdrToString(net_from));
|
||||
|
||||
// movie playback servers are ONLY for local clients
|
||||
if(Host_ServerState() == ss_cinematic)
|
||||
{
|
||||
if(!NET_IsLocalAddress (adr))
|
||||
{
|
||||
Msg ("Remote connect in attract loop. Ignored.\n");
|
||||
Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nConnection refused.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// see if the challenge is valid
|
||||
if (!NET_IsLocalAddress (adr))
|
||||
{
|
||||
for (i=0 ; i<MAX_CHALLENGES ; i++)
|
||||
{
|
||||
if (NET_CompareBaseAdr (net_from, svs.challenges[i].adr))
|
||||
{
|
||||
if (challenge == svs.challenges[i].challenge)
|
||||
break; // good
|
||||
Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nBad challenge->\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (i == MAX_CHALLENGES)
|
||||
{
|
||||
Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nNo challenge for address.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
newcl = &temp;
|
||||
memset (newcl, 0, sizeof(sv_client_t));
|
||||
|
||||
// if there is already a slot for this ip, reuse it
|
||||
for (i = 0, cl = svs.clients; i < maxclients->value; i++, cl++)
|
||||
{
|
||||
if (cl->state == cs_free) continue;
|
||||
if (NET_CompareBaseAdr (adr, cl->netchan.remote_address) && ( cl->netchan.qport == qport || adr.port == cl->netchan.remote_address.port))
|
||||
{
|
||||
if (!NET_IsLocalAddress (adr) && (svs.realtime - cl->lastconnect) < sv_reconnect_limit->value * 1000 )
|
||||
{
|
||||
MsgDev( D_ERROR, "SVC_DirectConnect: %s:reconnect rejected : too soon\n", NET_AdrToString (adr));
|
||||
return;
|
||||
}
|
||||
Msg ("%s:reconnect\n", NET_AdrToString (adr));
|
||||
newcl = cl;
|
||||
goto gotnewcl;
|
||||
}
|
||||
}
|
||||
|
||||
// find a client slot
|
||||
newcl = NULL;
|
||||
for (i = 0, cl = svs.clients; i < maxclients->value; i++, cl++)
|
||||
{
|
||||
if (cl->state == cs_free)
|
||||
{
|
||||
newcl = cl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!newcl)
|
||||
{
|
||||
Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nServer is full.\n");
|
||||
MsgDev(D_INFO, "SVC_DirectConnect: Rejected a connection.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gotnewcl:
|
||||
// build a new connection
|
||||
// accept the new client
|
||||
// this is the only place a sv_client_t is ever initialized
|
||||
*newcl = temp;
|
||||
sv_client = newcl;
|
||||
edictnum = (newcl - svs.clients) + 1;
|
||||
|
||||
ent = PRVM_EDICT_NUM( edictnum );
|
||||
ent->priv.sv->client = newcl;
|
||||
newcl->edict = ent;
|
||||
newcl->challenge = challenge; // save challenge for checksumming
|
||||
|
||||
// get the game a chance to reject this connection or modify the userinfo
|
||||
if (!(SV_ClientConnect(ent, userinfo)))
|
||||
{
|
||||
if (*Info_ValueForKey (userinfo, "rejmsg"))
|
||||
Netchan_OutOfBandPrint (NS_SERVER, adr, "print\n%s\nConnection refused.\n", Info_ValueForKey (userinfo, "rejmsg"));
|
||||
else Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nConnection refused.\n" );
|
||||
MsgDev( D_ERROR, "SVC_DirectConnect: Game rejected a connection.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// parse some info from the info strings
|
||||
strncpy (newcl->userinfo, userinfo, sizeof(newcl->userinfo)-1);
|
||||
SV_UserinfoChanged (newcl);
|
||||
|
||||
// send the connect packet to the client
|
||||
Netchan_OutOfBandPrint (NS_SERVER, adr, "client_connect");
|
||||
|
||||
Netchan_Setup (NS_SERVER, &newcl->netchan , adr, qport);
|
||||
|
||||
newcl->state = cs_connected;
|
||||
|
||||
SZ_Init (&newcl->datagram, newcl->datagram_buf, sizeof(newcl->datagram_buf) );
|
||||
newcl->lastmessage = svs.realtime; // don't timeout
|
||||
newcl->lastconnect = svs.realtime;
|
||||
}
|
||||
|
||||
int Rcon_Validate (void)
|
||||
{
|
||||
if (!strlen (rcon_password->string))
|
||||
return 0;
|
||||
|
||||
if (strcmp (Cmd_Argv(1), rcon_password->string) )
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
SVC_RemoteCommand
|
||||
|
||||
A client issued an rcon command.
|
||||
Shift down the remaining args
|
||||
Redirect all printfs
|
||||
===============
|
||||
*/
|
||||
void SVC_RemoteCommand (void)
|
||||
{
|
||||
int i;
|
||||
char remaining[1024];
|
||||
|
||||
i = Rcon_Validate ();
|
||||
|
||||
if (i == 0) MsgDev(D_INFO, "Bad rcon from %s:\n%s\n", NET_AdrToString (net_from), net_message.data + 4);
|
||||
else MsgDev(D_INFO, "Rcon from %s:\n%s\n", NET_AdrToString (net_from), net_message.data + 4);
|
||||
SVC_BeginRedirect (RD_PACKET, sv_outputbuf, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect);
|
||||
|
||||
if (!Rcon_Validate()) Msg("Bad rcon_password.\n");
|
||||
else
|
||||
{
|
||||
remaining[0] = 0;
|
||||
|
||||
for (i = 2; i < Cmd_Argc(); i++)
|
||||
{
|
||||
strcat (remaining, Cmd_Argv(i) );
|
||||
strcat (remaining, " ");
|
||||
}
|
||||
Cmd_ExecuteString (remaining);
|
||||
}
|
||||
SVC_EndRedirect ();
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
SV_ConnectionlessPacket
|
||||
|
||||
A connectionless packet has four leading 0xff
|
||||
characters to distinguish it from a game channel.
|
||||
Clients that are in the game can still send
|
||||
connectionless packets.
|
||||
=================
|
||||
*/
|
||||
void SV_ConnectionlessPacket (void)
|
||||
{
|
||||
char *s;
|
||||
char *c;
|
||||
|
||||
MSG_BeginReading (&net_message);
|
||||
MSG_ReadLong (&net_message);// skip the -1 marker
|
||||
|
||||
s = MSG_ReadStringLine (&net_message);
|
||||
|
||||
Cmd_TokenizeString(s);
|
||||
|
||||
c = Cmd_Argv(0);
|
||||
MsgDev( D_INFO, "SV_ConnectionlessPacket: %s : %s\n", NET_AdrToString(net_from), c);
|
||||
|
||||
if (!strcmp(c, "ping")) SVC_Ping();
|
||||
else if (!strcmp(c, "ack")) SVC_Ack();
|
||||
else if (!strcmp(c,"status")) SVC_Status();
|
||||
else if (!strcmp(c,"info")) SVC_Info();
|
||||
else if (!strcmp(c,"getchallenge")) SVC_GetChallenge();
|
||||
else if (!strcmp(c,"connect")) SVC_DirectConnect();
|
||||
else if (!strcmp(c, "rcon")) SVC_RemoteCommand();
|
||||
else Msg ("bad connectionless packet from %s:\n%s\n", NET_AdrToString (net_from), s);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
/*
|
||||
|
@ -522,12 +67,12 @@ void SV_CalcPings (void)
|
|||
|
||||
total = 0;
|
||||
count = 0;
|
||||
for (j=0 ; j<LATENCY_COUNTS ; j++)
|
||||
for( j = 0; j < UPDATE_BACKUP; j++ )
|
||||
{
|
||||
if (cl->frame_latency[j] > 0)
|
||||
if( cl->frames[j].latency > 0 )
|
||||
{
|
||||
count++;
|
||||
total += cl->frame_latency[j];
|
||||
total += cl->frames[j].latency;
|
||||
}
|
||||
}
|
||||
if( !count ) cl->ping = 0;
|
||||
|
@ -538,89 +83,63 @@ void SV_CalcPings (void)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
SV_GiveMsec
|
||||
|
||||
Every few frames, gives all clients an allotment of milliseconds
|
||||
for their command moves. If they exceed it, assume cheating.
|
||||
===================
|
||||
*/
|
||||
void SV_GiveMsec (void)
|
||||
{
|
||||
int i;
|
||||
sv_client_t *cl;
|
||||
|
||||
if (sv.framenum & 15)
|
||||
return;
|
||||
|
||||
for (i=0 ; i<maxclients->value ; i++)
|
||||
{
|
||||
cl = &svs.clients[i];
|
||||
if (cl->state == cs_free )
|
||||
continue;
|
||||
|
||||
cl->commandMsec = 1800; // 1600 + some slop
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
SV_ReadPackets
|
||||
SV_PacketEvent
|
||||
=================
|
||||
*/
|
||||
void SV_PacketEvent( netadr_t from, sizebuf_t *msg )
|
||||
{
|
||||
}
|
||||
|
||||
void SV_ReadPackets (void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
sv_client_t *cl;
|
||||
int qport;
|
||||
int qport;
|
||||
|
||||
while (NET_GetPacket (NS_SERVER, &net_from, &net_message))
|
||||
if( !svs.initialized ) return;
|
||||
|
||||
SV_VM_Begin();
|
||||
|
||||
// check for connectionless packet (0xffffffff) first
|
||||
if(*(int *)msg->data == -1)
|
||||
{
|
||||
// check for connectionless packet (0xffffffff) first
|
||||
if (*(int *)net_message.data == -1)
|
||||
{
|
||||
SV_ConnectionlessPacket ();
|
||||
continue;
|
||||
}
|
||||
|
||||
// read the qport out of the message so we can fix up
|
||||
// stupid address translating routers
|
||||
MSG_BeginReading (&net_message);
|
||||
MSG_ReadLong (&net_message); // sequence number
|
||||
MSG_ReadLong (&net_message); // sequence number
|
||||
qport = MSG_ReadShort (&net_message) & 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 (net_from, cl->netchan.remote_address)) continue;
|
||||
if (cl->netchan.qport != qport) continue;
|
||||
if (cl->netchan.remote_address.port != net_from.port)
|
||||
{
|
||||
MsgDev(D_INFO, "SV_ReadPackets: fixing up a translated port\n");
|
||||
cl->netchan.remote_address.port = net_from.port;
|
||||
}
|
||||
if (Netchan_Process(&cl->netchan, &net_message))
|
||||
{
|
||||
// this is a valid, sequenced packet, so process it
|
||||
if (cl->state != cs_zombie)
|
||||
{
|
||||
cl->lastmessage = svs.realtime; // don't timeout
|
||||
SV_ExecuteClientMessage (cl);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if( i != maxclients->integer ) continue;
|
||||
SV_ConnectionlessPacket( from, msg );
|
||||
return;
|
||||
}
|
||||
|
||||
// read the qport out of the message so we can fix up
|
||||
// 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( from, cl->netchan.remote_address )) continue;
|
||||
if( cl->netchan.qport != qport ) continue;
|
||||
if( cl->netchan.remote_address.port != from.port )
|
||||
{
|
||||
MsgDev( D_INFO, "SV_ReadPackets: fixing up a translated port\n");
|
||||
cl->netchan.remote_address.port = from.port;
|
||||
}
|
||||
if( Netchan_Process( &cl->netchan, msg ))
|
||||
{
|
||||
// this is a valid, sequenced packet, so process it
|
||||
if( cl->state != cs_zombie )
|
||||
{
|
||||
cl->lastmessage = svs.realtime; // don't timeout
|
||||
SV_ExecuteClientMessage( cl, msg );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if( i != maxclients->integer ) return;
|
||||
|
||||
// if we received a sequenced packet from an address we don't recognize,
|
||||
// send an out of band disconnect packet to it
|
||||
//Netchan_OutOfBandPrint( NS_SERVER, from, "disconnect\n" );
|
||||
SV_VM_End();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -636,33 +155,32 @@ for a few seconds to make sure any final reliable message gets resent
|
|||
if necessary
|
||||
==================
|
||||
*/
|
||||
void SV_CheckTimeouts (void)
|
||||
void SV_CheckTimeouts( void )
|
||||
{
|
||||
int i;
|
||||
sv_client_t *cl;
|
||||
float droppoint;
|
||||
float zombiepoint;
|
||||
float droppoint;
|
||||
float zombiepoint;
|
||||
|
||||
droppoint = svs.realtime - 1000 * timeout->value;
|
||||
zombiepoint = svs.realtime - 1000 * zombietime->value;
|
||||
|
||||
for (i=0,cl=svs.clients ; i<maxclients->value ; i++,cl++)
|
||||
for( i = 0, cl = svs.clients; i < maxclients->value; i++, cl++ )
|
||||
{
|
||||
// message times may be wrong across a changelevel
|
||||
if (cl->lastmessage > svs.realtime)
|
||||
if( cl->lastmessage > svs.realtime )
|
||||
cl->lastmessage = svs.realtime;
|
||||
|
||||
if (cl->state == cs_zombie
|
||||
&& cl->lastmessage < zombiepoint)
|
||||
if( cl->state == cs_zombie && cl->lastmessage < zombiepoint )
|
||||
{
|
||||
cl->state = cs_free; // can now be reused
|
||||
cl->state = cs_free; // can now be reused
|
||||
continue;
|
||||
}
|
||||
if ( (cl->state == cs_connected || cl->state == cs_spawned) && cl->lastmessage < droppoint)
|
||||
if(( cl->state == cs_connected || cl->state == cs_spawned) && cl->lastmessage < droppoint )
|
||||
{
|
||||
SV_BroadcastPrintf (PRINT_CONSOLE, "%s timed out\n", cl->name);
|
||||
SV_DropClient (cl);
|
||||
cl->state = cs_free; // don't bother with zombie state
|
||||
SV_BroadcastPrintf (PRINT_CONSOLE, "%s timed out\n", cl->name );
|
||||
SV_DropClient( cl );
|
||||
cl->state = cs_free; // don't bother with zombie state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -710,7 +228,6 @@ void SV_Frame( dword time )
|
|||
{
|
||||
// if server is not active, do nothing
|
||||
if( !svs.initialized ) return;
|
||||
|
||||
svs.realtime += time;
|
||||
|
||||
// keep the random time dependent
|
||||
|
@ -722,9 +239,6 @@ void SV_Frame( dword time )
|
|||
// check timeouts
|
||||
SV_CheckTimeouts ();
|
||||
|
||||
// get packets from clients
|
||||
SV_ReadPackets ();
|
||||
|
||||
// move autonomous things around if enough time has passed
|
||||
if( svs.realtime < (sv.time * 1000))
|
||||
{
|
||||
|
@ -743,9 +257,6 @@ void SV_Frame( dword time )
|
|||
// update ping based on the last known frame from all clients
|
||||
SV_CalcPings ();
|
||||
|
||||
// give the clients some timeslices
|
||||
SV_GiveMsec ();
|
||||
|
||||
// let everything in the world think and move
|
||||
SV_RunGameFrame ();
|
||||
|
||||
|
@ -833,59 +344,6 @@ void Master_Shutdown (void)
|
|||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
SV_UserinfoChanged
|
||||
|
||||
Pull specific info from a newly changed userinfo string
|
||||
into a more C freindly form.
|
||||
=================
|
||||
*/
|
||||
void SV_UserinfoChanged (sv_client_t *cl)
|
||||
{
|
||||
char *val;
|
||||
int i;
|
||||
char *cl_name;
|
||||
|
||||
// call prog code to allow overrides
|
||||
SV_ClientUserinfoChanged(cl->edict, cl->userinfo);
|
||||
|
||||
// name for C code
|
||||
cl_name = Info_ValueForKey (cl->userinfo, "name");
|
||||
if(cl_name == "") strncpy (cl->name, "unnamed", sizeof(cl->name) - 1);
|
||||
else strncpy (cl->name, cl_name, sizeof(cl->name) - 1);
|
||||
|
||||
// mask off high bit
|
||||
for (i=0 ; i<sizeof(cl->name) ; i++)
|
||||
cl->name[i] &= 127;
|
||||
|
||||
// rate command
|
||||
val = Info_ValueForKey (cl->userinfo, "rate");
|
||||
if (strlen(val))
|
||||
{
|
||||
i = atoi(val);
|
||||
cl->rate = i;
|
||||
if (cl->rate < 100)
|
||||
cl->rate = 100;
|
||||
if (cl->rate > 15000)
|
||||
cl->rate = 15000;
|
||||
}
|
||||
else
|
||||
cl->rate = 5000;
|
||||
|
||||
// msg command
|
||||
val = Info_ValueForKey (cl->userinfo, "msg");
|
||||
if (strlen(val))
|
||||
{
|
||||
cl->messagelevel = atoi(val);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
/*
|
||||
|
@ -930,8 +388,6 @@ void SV_Init (void)
|
|||
public_server = Cvar_Get ("public", "0", 0, "change server type from private to public" );
|
||||
|
||||
sv_reconnect_limit = Cvar_Get ("sv_reconnect_limit", "3", CVAR_ARCHIVE, "max reconnect attempts" );
|
||||
|
||||
SZ_Init (&net_message, net_message_buffer, sizeof(net_message_buffer));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -946,32 +402,34 @@ to totally exit after returning from this function.
|
|||
*/
|
||||
void SV_FinalMessage (char *message, bool reconnect)
|
||||
{
|
||||
int i;
|
||||
sv_client_t *cl;
|
||||
byte msg_buf[MAX_MSGLEN];
|
||||
sizebuf_t msg;
|
||||
int i;
|
||||
|
||||
SZ_Clear (&net_message);
|
||||
MSG_WriteByte (&net_message, svc_print);
|
||||
MSG_WriteByte (&net_message, PRINT_CONSOLE);
|
||||
MSG_WriteString (&net_message, message);
|
||||
MSG_Init( &msg, msg_buf, sizeof(msg_buf));
|
||||
MSG_WriteByte( &msg, svc_print );
|
||||
MSG_WriteByte( &msg, PRINT_CONSOLE );
|
||||
MSG_WriteString( &msg, message );
|
||||
|
||||
if (reconnect)
|
||||
if( reconnect )
|
||||
{
|
||||
MSG_WriteByte (&net_message, svc_reconnect);
|
||||
MSG_WriteByte( &msg, svc_reconnect );
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_WriteByte (&net_message, svc_disconnect);
|
||||
MSG_WriteByte( &msg, svc_disconnect );
|
||||
}
|
||||
|
||||
// send it twice
|
||||
// stagger the packets to crutch operating system limited buffers
|
||||
for( i = 0, cl = svs.clients; i < maxclients->value; i++, cl++ )
|
||||
if( cl->state >= cs_connected )
|
||||
Netchan_Transmit( &cl->netchan, msg.cursize, msg.data );
|
||||
|
||||
for (i=0, cl = svs.clients ; i<maxclients->value ; i++, cl++)
|
||||
if (cl->state >= cs_connected)
|
||||
Netchan_Transmit (&cl->netchan, net_message.cursize, net_message.data);
|
||||
|
||||
for (i=0, cl = svs.clients ; i<maxclients->value ; i++, cl++)
|
||||
if (cl->state >= cs_connected)
|
||||
Netchan_Transmit (&cl->netchan, net_message.cursize, net_message.data);
|
||||
for( i = 0, cl = svs.clients; i < maxclients->value; i++, cl++ )
|
||||
if( cl->state >= cs_connected )
|
||||
Netchan_Transmit( &cl->netchan, msg.cursize, msg.data );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -224,7 +224,7 @@ void SV_Impact (edict_t *e1, trace_t *trace)
|
|||
prog->globals.sv->trace_plane_dist = trace->plane.dist;
|
||||
if (trace->ent) prog->globals.sv->trace_ent = PRVM_EDICT_TO_PROG(trace->ent);
|
||||
else prog->globals.sv->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
|
||||
PRVM_ExecuteProgram (e1->progs.sv->touch, "QC function pev->touch is missing\n");
|
||||
PRVM_ExecuteProgram( e1->progs.sv->touch, "pev->touch" );
|
||||
}
|
||||
if (!e1->priv.sv->free && !e2->priv.sv->free && e2->progs.sv->touch && e2->progs.sv->solid != SOLID_NOT)
|
||||
{
|
||||
|
@ -239,7 +239,7 @@ void SV_Impact (edict_t *e1, trace_t *trace)
|
|||
VectorSet (prog->globals.sv->trace_plane_normal, 0, 0, 1);
|
||||
prog->globals.sv->trace_plane_dist = 0;
|
||||
prog->globals.sv->trace_ent = PRVM_EDICT_TO_PROG(e1);
|
||||
PRVM_ExecuteProgram (e2->progs.sv->touch, "QC function pev->touch is missing\n");
|
||||
PRVM_ExecuteProgram (e2->progs.sv->touch, "pev->touch");
|
||||
}
|
||||
|
||||
PRVM_POP_GLOBALS;
|
||||
|
@ -594,7 +594,7 @@ bool SV_RunThink (edict_t *ent)
|
|||
prog->globals.sv->time = thinktime;
|
||||
prog->globals.sv->pev = PRVM_EDICT_TO_PROG(ent);
|
||||
prog->globals.sv->other = PRVM_EDICT_TO_PROG(prog->edicts);
|
||||
PRVM_ExecuteProgram (ent->progs.sv->think, "QC function pev->think is missing");
|
||||
PRVM_ExecuteProgram (ent->progs.sv->think, "pev->think");
|
||||
|
||||
return !ent->priv.sv->free;
|
||||
}
|
||||
|
@ -914,7 +914,7 @@ void SV_MovePush(edict_t *pusher, float movetime)
|
|||
{
|
||||
prog->globals.sv->pev = PRVM_EDICT_TO_PROG(pusher);
|
||||
prog->globals.sv->other = PRVM_EDICT_TO_PROG(check);
|
||||
PRVM_ExecuteProgram (pusher->progs.sv->blocked, "QC function self.blocked is missing");
|
||||
PRVM_ExecuteProgram (pusher->progs.sv->blocked, "pev->blocked");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -996,7 +996,7 @@ void SV_PhysicsPush(edict_t *ent)
|
|||
prog->globals.sv->time = sv.time;
|
||||
prog->globals.sv->pev = PRVM_EDICT_TO_PROG(ent);
|
||||
prog->globals.sv->other = PRVM_EDICT_TO_PROG(prog->edicts);
|
||||
PRVM_ExecuteProgram (ent->progs.sv->think, "QC function pev->think is missing");
|
||||
PRVM_ExecuteProgram (ent->progs.sv->think, "pev->think");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -185,7 +185,7 @@ void SV_ConfigString (int index, const char *val)
|
|||
if( sv.state != ss_loading )
|
||||
{
|
||||
// send the update to everyone
|
||||
SZ_Clear (&sv.multicast);
|
||||
MSG_Clear( &sv.multicast );
|
||||
MSG_Begin(svc_configstring);
|
||||
MSG_WriteShort (&sv.multicast, index);
|
||||
MSG_WriteString (&sv.multicast, (char *)val);
|
||||
|
|
|
@ -22,31 +22,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "common.h"
|
||||
#include "server.h"
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
Msg redirection
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
char sv_outputbuf[SV_OUTPUTBUF_LENGTH];
|
||||
|
||||
void SV_FlushRedirect (int sv_redirected, char *outputbuf)
|
||||
{
|
||||
if (sv_redirected == RD_PACKET)
|
||||
{
|
||||
Netchan_OutOfBandPrint (NS_SERVER, net_from, "print\n%s", outputbuf);
|
||||
}
|
||||
else if (sv_redirected == RD_CLIENT)
|
||||
{
|
||||
MSG_WriteByte (&sv_client->netchan.message, svc_print);
|
||||
MSG_WriteByte (&sv_client->netchan.message, PRINT_CONSOLE );
|
||||
MSG_WriteString (&sv_client->netchan.message, outputbuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
|
@ -92,33 +67,25 @@ void SV_BroadcastPrintf (int level, char *fmt, ...)
|
|||
va_list argptr;
|
||||
char string[2048];
|
||||
sv_client_t *cl;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
va_start (argptr,fmt);
|
||||
com.vsprintf (string, fmt,argptr);
|
||||
va_end (argptr);
|
||||
va_start( argptr, fmt );
|
||||
com.vsprintf( string, fmt, argptr );
|
||||
va_end( argptr );
|
||||
|
||||
// echo to console
|
||||
if( host.type == HOST_DEDICATED )
|
||||
{
|
||||
char echo[1024];
|
||||
int i;
|
||||
|
||||
// mask off high bits
|
||||
for (i = 0; i < 1023 && string[i]; i++)
|
||||
echo[i] = string[i] & 127;
|
||||
echo[i] = 0;
|
||||
Msg ("%s", echo );
|
||||
Msg ("%s", string );
|
||||
}
|
||||
|
||||
for (i = 0, cl = svs.clients; i < maxclients->value; i++, cl++)
|
||||
for( i = 0, cl = svs.clients; i < maxclients->value; i++, cl++ )
|
||||
{
|
||||
if (level < cl->messagelevel) continue;
|
||||
if (cl->state != cs_spawned) continue;
|
||||
|
||||
MSG_WriteByte (&cl->netchan.message, svc_print);
|
||||
MSG_WriteByte (&cl->netchan.message, level);
|
||||
MSG_WriteString (&cl->netchan.message, string);
|
||||
if( level < cl->messagelevel) continue;
|
||||
if( cl->state != cs_spawned ) continue;
|
||||
MSG_WriteByte( &cl->netchan.message, svc_print );
|
||||
MSG_WriteByte( &cl->netchan.message, level );
|
||||
MSG_WriteString( &cl->netchan.message, string );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,10 +196,10 @@ 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->netchan.message, sv.multicast.data, sv.multicast.cursize, filename, fileline);
|
||||
else _SZ_Write (&client->datagram, sv.multicast.data, sv.multicast.cursize, filename, fileline);
|
||||
if (reliable) _MSG_WriteData (&client->netchan.message, sv.multicast.data, sv.multicast.cursize, filename, fileline);
|
||||
else _MSG_WriteData (&client->datagram, sv.multicast.data, sv.multicast.cursize, filename, fileline);
|
||||
}
|
||||
SZ_Clear (&sv.multicast);
|
||||
MSG_Clear( &sv.multicast );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -412,14 +379,14 @@ FRAME UPDATES
|
|||
SV_SendClientDatagram
|
||||
=======================
|
||||
*/
|
||||
bool SV_SendClientDatagram (sv_client_t *client)
|
||||
bool SV_SendClientDatagram( sv_client_t *client )
|
||||
{
|
||||
byte msg_buf[MAX_MSGLEN];
|
||||
sizebuf_t msg;
|
||||
|
||||
SV_BuildClientFrame (client);
|
||||
SV_BuildClientFrame( client );
|
||||
|
||||
SZ_Init (&msg, msg_buf, sizeof(msg_buf));
|
||||
MSG_Init( &msg, msg_buf, sizeof(msg_buf));
|
||||
|
||||
// send over all the relevant entity_state_t
|
||||
// and the player_state_t
|
||||
|
@ -432,20 +399,22 @@ bool SV_SendClientDatagram (sv_client_t *client)
|
|||
if (client->datagram.overflowed)
|
||||
Msg ("WARNING: datagram overflowed for %s\n", client->name);
|
||||
else
|
||||
SZ_Write (&msg, client->datagram.data, client->datagram.cursize);
|
||||
SZ_Clear (&client->datagram);
|
||||
MSG_WriteData (&msg, client->datagram.data, client->datagram.cursize);
|
||||
MSG_Clear( &client->datagram );
|
||||
|
||||
if (msg.overflowed)
|
||||
{ // must have room left for the packet header
|
||||
Msg ("WARNING: msg overflowed for %s\n", client->name);
|
||||
SZ_Clear (&msg);
|
||||
MSG_Clear( &msg );
|
||||
}
|
||||
|
||||
// send the datagram
|
||||
Netchan_Transmit (&client->netchan, msg.cursize, msg.data);
|
||||
|
||||
// record the size for rate estimation
|
||||
client->message_size[sv.framenum % RATE_MESSAGES] = msg.cursize;
|
||||
// record information about the message
|
||||
client->frames[client->netchan.outgoing_sequence & UPDATE_MASK].msg_size = msg.cursize;
|
||||
client->frames[client->netchan.outgoing_sequence & UPDATE_MASK].msg_sent = svs.realtime;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -458,29 +427,26 @@ Returns true if the client is over its current
|
|||
bandwidth estimation and should not be sent another packet
|
||||
=======================
|
||||
*/
|
||||
bool SV_RateDrop (sv_client_t *c)
|
||||
bool SV_RateDrop( sv_client_t *cl )
|
||||
{
|
||||
int total;
|
||||
int i;
|
||||
int i, total = 0;
|
||||
|
||||
// never drop over the loopback
|
||||
if (c->netchan.remote_address.type == NA_LOOPBACK)
|
||||
if( NET_IsLocalAddress( cl->netchan.remote_address ))
|
||||
return false;
|
||||
|
||||
if( NET_IsLANAddress( cl->netchan.remote_address ))
|
||||
return false;
|
||||
|
||||
total = 0;
|
||||
for( i = 0; i < UPDATE_BACKUP; i++ )
|
||||
total += cl->frames[i].msg_size;
|
||||
|
||||
for (i = 0 ; i < RATE_MESSAGES ; i++)
|
||||
if( total > cl->rate )
|
||||
{
|
||||
total += c->message_size[i];
|
||||
}
|
||||
|
||||
if (total > c->rate)
|
||||
{
|
||||
c->surpressCount++;
|
||||
c->message_size[sv.framenum % RATE_MESSAGES] = 0;
|
||||
cl->surpressCount++;
|
||||
cl->frames[cl->netchan.outgoing_sequence & UPDATE_MASK].msg_size = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -507,8 +473,8 @@ void SV_SendClientMessages (void)
|
|||
// drop the client
|
||||
if (c->netchan.message.overflowed)
|
||||
{
|
||||
SZ_Clear (&c->netchan.message);
|
||||
SZ_Clear (&c->datagram);
|
||||
MSG_Clear( &c->netchan.message );
|
||||
MSG_Clear( &c->datagram );
|
||||
SV_BroadcastPrintf (PRINT_CONSOLE, "%s overflowed\n", c->name);
|
||||
SV_DropClient (c);
|
||||
}
|
||||
|
|
|
@ -16,53 +16,6 @@ int PM_pointcontents( vec3_t point )
|
|||
return SV_PointContents( point, pm_passent );
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
PutClientInServer
|
||||
|
||||
Called when a player connects to a server or respawns in
|
||||
a deathmatch.
|
||||
============
|
||||
*/
|
||||
void SV_PutClientInServer (edict_t *ent)
|
||||
{
|
||||
int index;
|
||||
sv_client_t *client;
|
||||
int i;
|
||||
|
||||
index = PRVM_NUM_FOR_EDICT( ent ) - 1;
|
||||
client = ent->priv.sv->client;
|
||||
|
||||
prog->globals.sv->time = sv.time;
|
||||
prog->globals.sv->pev = PRVM_EDICT_TO_PROG( ent );
|
||||
|
||||
ent->priv.sv->free = false;
|
||||
(int)ent->progs.sv->flags &= ~FL_DEADMONSTER;
|
||||
|
||||
if( !sv.loadgame )
|
||||
{
|
||||
// fisrt entering
|
||||
PRVM_ExecuteProgram( prog->globals.sv->PutClientInServer, "QC function PutClientInServer is missing\n" );
|
||||
ent->progs.sv->v_angle[ROLL] = 0; // cut off any camera rolling
|
||||
ent->progs.sv->origin[2] += 1; // make sure off ground
|
||||
VectorCopy( ent->progs.sv->origin, ent->progs.sv->old_origin );
|
||||
}
|
||||
|
||||
// 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));
|
||||
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]);
|
||||
|
||||
SV_LinkEdict( ent ); // m_pmatrix calculated here, so we need call this before pe->CreatePlayer
|
||||
ent->priv.sv->physbody = pe->CreatePlayer( ent->priv.sv, SV_GetModelPtr( ent ), ent->progs.sv->m_pmatrix );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
SV_TouchTriggers
|
||||
|
@ -94,7 +47,7 @@ void SV_TouchTriggers (edict_t *ent)
|
|||
prog->globals.sv->time = sv.time;
|
||||
if( hit->progs.sv->touch )
|
||||
{
|
||||
PRVM_ExecuteProgram (hit->progs.sv->touch, "QC function pev->touch is missing\n");
|
||||
PRVM_ExecuteProgram (hit->progs.sv->touch, "pev->touch");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,7 +288,7 @@ void SV_RunFrame( void )
|
|||
prog->globals.sv->other = PRVM_EDICT_TO_PROG(prog->edicts);
|
||||
prog->globals.sv->time = sv.time;
|
||||
prog->globals.sv->frametime = sv.frametime;
|
||||
PRVM_ExecuteProgram (prog->globals.sv->StartFrame, "QC function StartFrame is missing");
|
||||
PRVM_ExecuteProgram (prog->globals.sv->StartFrame, "StartFrame");
|
||||
|
||||
for (i = 1; i < prog->num_edicts; i++ )
|
||||
{
|
||||
|
@ -355,7 +308,7 @@ void SV_RunFrame( void )
|
|||
prog->globals.sv->pev = PRVM_EDICT_TO_PROG(prog->edicts);
|
||||
prog->globals.sv->other = PRVM_EDICT_TO_PROG(prog->edicts);
|
||||
prog->globals.sv->time = sv.time;
|
||||
PRVM_ExecuteProgram (prog->globals.sv->EndFrame, "QC function EndFrame is missing");
|
||||
PRVM_ExecuteProgram (prog->globals.sv->EndFrame, "EndFrame");
|
||||
|
||||
// decrement prog->num_edicts if the highest number entities died
|
||||
for ( ;PRVM_EDICT_NUM(prog->num_edicts - 1)->priv.sv->free; prog->num_edicts-- );
|
||||
|
@ -370,7 +323,7 @@ bool SV_ClientConnect (edict_t *ent, char *userinfo)
|
|||
MsgDev(D_NOTE, "SV_ClientConnect()\n");
|
||||
prog->globals.sv->time = sv.time;
|
||||
prog->globals.sv->pev = PRVM_EDICT_TO_PROG(ent);
|
||||
PRVM_ExecuteProgram (prog->globals.sv->ClientConnect, "QC function ClientConnect is missing");
|
||||
PRVM_ExecuteProgram (prog->globals.sv->ClientConnect, "ClientConnect");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -455,7 +408,7 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd)
|
|||
// call standard client pre-think
|
||||
prog->globals.sv->time = sv.time;
|
||||
prog->globals.sv->pev = PRVM_EDICT_TO_PROG(ent);
|
||||
PRVM_ExecuteProgram (prog->globals.sv->PlayerPreThink, "QC function PlayerPreThink is missing");
|
||||
PRVM_ExecuteProgram (prog->globals.sv->PlayerPreThink, "PlayerPreThink");
|
||||
|
||||
VectorCopy(ent->progs.sv->origin, oldorigin);
|
||||
VectorCopy(ent->progs.sv->velocity, oldvelocity);
|
||||
|
@ -535,7 +488,7 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd)
|
|||
prog->globals.sv->time = sv.time;
|
||||
if( other->progs.sv->touch )
|
||||
{
|
||||
PRVM_ExecuteProgram (other->progs.sv->touch, "QC function pev->touch is missing\n");
|
||||
PRVM_ExecuteProgram (other->progs.sv->touch, "pev->touch");
|
||||
}
|
||||
}
|
||||
PRVM_POP_GLOBALS;
|
||||
|
@ -543,7 +496,7 @@ void ClientThink (edict_t *ent, usercmd_t *ucmd)
|
|||
// call standard player post-think
|
||||
prog->globals.sv->time = sv.time;
|
||||
prog->globals.sv->pev = PRVM_EDICT_TO_PROG(ent);
|
||||
PRVM_ExecuteProgram (prog->globals.sv->PlayerPostThink, "QC function PlayerPostThink is missing");
|
||||
PRVM_ExecuteProgram (prog->globals.sv->PlayerPostThink, "PlayerPostThink");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,539 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
// sv_user.c -- server code for moving users
|
||||
|
||||
#include "common.h"
|
||||
#include "server.h"
|
||||
|
||||
edict_t *sv_player;
|
||||
|
||||
/*
|
||||
============================================================
|
||||
|
||||
USER STRINGCMD EXECUTION
|
||||
|
||||
sv_client and sv_player will be valid.
|
||||
============================================================
|
||||
*/
|
||||
/*
|
||||
================
|
||||
SV_New_f
|
||||
|
||||
Sends the first message from the server to a connected client.
|
||||
This will be sent on the initial connection and upon each server load.
|
||||
================
|
||||
*/
|
||||
void SV_New_f (void)
|
||||
{
|
||||
int playernum;
|
||||
edict_t *ent;
|
||||
|
||||
if (sv_client->state != cs_connected)
|
||||
{
|
||||
Msg ("New not valid -- already spawned\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// send the serverdata
|
||||
MSG_WriteByte (&sv_client->netchan.message, svc_serverdata);
|
||||
MSG_WriteLong (&sv_client->netchan.message, PROTOCOL_VERSION);
|
||||
MSG_WriteLong (&sv_client->netchan.message, svs.spawncount);
|
||||
|
||||
if(sv.state == ss_cinematic) playernum = -1;
|
||||
else playernum = sv_client - svs.clients;
|
||||
MSG_WriteShort (&sv_client->netchan.message, playernum );
|
||||
|
||||
// send full levelname
|
||||
MSG_WriteString (&sv_client->netchan.message, sv.configstrings[CS_NAME]);
|
||||
|
||||
// game server
|
||||
if (sv.state == ss_active)
|
||||
{
|
||||
// set up the entity for the client
|
||||
ent = PRVM_EDICT_NUM(playernum + 1);
|
||||
ent->priv.sv->serialnumber = playernum + 1;
|
||||
sv_client->edict = ent;
|
||||
memset (&sv_client->lastcmd, 0, sizeof(sv_client->lastcmd));
|
||||
|
||||
// begin fetching configstrings
|
||||
MSG_WriteByte (&sv_client->netchan.message, svc_stufftext);
|
||||
MSG_WriteString (&sv_client->netchan.message, va("cmd configstrings %i 0\n",svs.spawncount) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_Configstrings_f
|
||||
==================
|
||||
*/
|
||||
void SV_Configstrings_f (void)
|
||||
{
|
||||
int start;
|
||||
|
||||
if (sv_client->state != cs_connected)
|
||||
{
|
||||
Msg ("configstrings not valid -- already spawned\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// handle the case of a level changing while a client was connecting
|
||||
if ( atoi(Cmd_Argv(1)) != svs.spawncount )
|
||||
{
|
||||
Msg ("SV_Configstrings_f from different level\n");
|
||||
SV_New_f ();
|
||||
return;
|
||||
}
|
||||
|
||||
start = atoi(Cmd_Argv(2));
|
||||
|
||||
// write a packet full of data
|
||||
while ( sv_client->netchan.message.cursize < MAX_MSGLEN/2 && start < MAX_CONFIGSTRINGS)
|
||||
{
|
||||
if (sv.configstrings[start][0])
|
||||
{
|
||||
MSG_WriteByte (&sv_client->netchan.message, svc_configstring);
|
||||
MSG_WriteShort (&sv_client->netchan.message, start);
|
||||
MSG_WriteString (&sv_client->netchan.message, sv.configstrings[start]);
|
||||
}
|
||||
start++;
|
||||
}
|
||||
|
||||
// send next command
|
||||
|
||||
if (start == MAX_CONFIGSTRINGS)
|
||||
{
|
||||
MSG_WriteByte (&sv_client->netchan.message, svc_stufftext);
|
||||
MSG_WriteString (&sv_client->netchan.message, va("cmd baselines %i 0\n",svs.spawncount) );
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_WriteByte (&sv_client->netchan.message, svc_stufftext);
|
||||
MSG_WriteString (&sv_client->netchan.message, va("cmd configstrings %i %i\n",svs.spawncount, start) );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_Baselines_f
|
||||
==================
|
||||
*/
|
||||
void SV_Baselines_f (void)
|
||||
{
|
||||
int start;
|
||||
entity_state_t nullstate;
|
||||
entity_state_t *base;
|
||||
|
||||
if (sv_client->state != cs_connected)
|
||||
{
|
||||
Msg ("baselines not valid -- already spawned\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// handle the case of a level changing while a client was connecting
|
||||
if ( atoi(Cmd_Argv(1)) != svs.spawncount )
|
||||
{
|
||||
Msg ("SV_Baselines_f from different level\n");
|
||||
SV_New_f ();
|
||||
return;
|
||||
}
|
||||
|
||||
start = atoi(Cmd_Argv(2));
|
||||
|
||||
memset (&nullstate, 0, sizeof(nullstate));
|
||||
|
||||
// write a packet full of data
|
||||
|
||||
while ( sv_client->netchan.message.cursize < MAX_MSGLEN/2 && start < MAX_EDICTS)
|
||||
{
|
||||
base = &sv.baselines[start];
|
||||
if (base->modelindex || base->soundindex || base->effects)
|
||||
{
|
||||
MSG_WriteByte (&sv_client->netchan.message, svc_spawnbaseline);
|
||||
MSG_WriteDeltaEntity (&nullstate, base, &sv_client->netchan.message, true, true);
|
||||
}
|
||||
start++;
|
||||
}
|
||||
|
||||
// send next command
|
||||
|
||||
if (start == MAX_EDICTS)
|
||||
{
|
||||
MSG_WriteByte (&sv_client->netchan.message, svc_stufftext);
|
||||
MSG_WriteString (&sv_client->netchan.message, va("precache %i\n", svs.spawncount) );
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_WriteByte (&sv_client->netchan.message, svc_stufftext);
|
||||
MSG_WriteString (&sv_client->netchan.message, va("cmd baselines %i %i\n",svs.spawncount, start) );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_Begin_f
|
||||
==================
|
||||
*/
|
||||
void SV_Begin_f (void)
|
||||
{
|
||||
// handle the case of a level changing while a client was connecting
|
||||
if( atoi(Cmd_Argv(1)) != svs.spawncount )
|
||||
{
|
||||
Msg ("SV_Begin_f from different level\n");
|
||||
SV_New_f ();
|
||||
return;
|
||||
}
|
||||
|
||||
sv_client->state = cs_spawned;
|
||||
|
||||
// call the game begin function
|
||||
SV_ClientBegin(sv_player);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_NextDownload_f
|
||||
==================
|
||||
*/
|
||||
void SV_NextDownload_f (void)
|
||||
{
|
||||
int r;
|
||||
int percent;
|
||||
int size;
|
||||
|
||||
if (!sv_client->download)
|
||||
return;
|
||||
|
||||
r = sv_client->downloadsize - sv_client->downloadcount;
|
||||
if (r > 1024)
|
||||
r = 1024;
|
||||
|
||||
MSG_WriteByte (&sv_client->netchan.message, svc_download);
|
||||
MSG_WriteShort (&sv_client->netchan.message, r);
|
||||
|
||||
sv_client->downloadcount += r;
|
||||
size = sv_client->downloadsize;
|
||||
if (!size)
|
||||
size = 1;
|
||||
percent = sv_client->downloadcount*100/size;
|
||||
MSG_WriteByte (&sv_client->netchan.message, percent);
|
||||
SZ_Write (&sv_client->netchan.message,
|
||||
sv_client->download + sv_client->downloadcount - r, r);
|
||||
|
||||
if (sv_client->downloadcount != sv_client->downloadsize)
|
||||
return;
|
||||
|
||||
sv_client->download = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_BeginDownload_f
|
||||
==================
|
||||
*/
|
||||
void SV_BeginDownload_f(void)
|
||||
{
|
||||
char *name;
|
||||
extern cvar_t *allow_download;
|
||||
extern cvar_t *allow_download_players;
|
||||
extern cvar_t *allow_download_models;
|
||||
extern cvar_t *allow_download_sounds;
|
||||
extern cvar_t *allow_download_maps;
|
||||
int offset = 0;
|
||||
|
||||
name = Cmd_Argv(1);
|
||||
|
||||
if (Cmd_Argc() > 2)
|
||||
offset = atoi(Cmd_Argv(2)); // downloaded offset
|
||||
|
||||
// hacked by zoid to allow more conrol over download
|
||||
// first off, no .. or global allow check
|
||||
if (strstr (name, "..") || !allow_download->value
|
||||
// leading dot is no good
|
||||
|| *name == '.'
|
||||
// leading slash bad as well, must be in subdir
|
||||
|| *name == '/'
|
||||
// next up, skin check
|
||||
|| (strncmp(name, "players/", 6) == 0 && !allow_download_players->value)
|
||||
// now models
|
||||
|| (strncmp(name, "models/", 6) == 0 && !allow_download_models->value)
|
||||
// now sounds
|
||||
|| (strncmp(name, "sound/", 6) == 0 && !allow_download_sounds->value)
|
||||
// now maps (note special case for maps, must not be in pak)
|
||||
|| (strncmp(name, "maps/", 6) == 0 && !allow_download_maps->value)
|
||||
// MUST be in a subdirectory
|
||||
|| !strstr (name, "/") )
|
||||
{ // don't allow anything with .. path
|
||||
MSG_WriteByte (&sv_client->netchan.message, svc_download);
|
||||
MSG_WriteShort (&sv_client->netchan.message, -1);
|
||||
MSG_WriteByte (&sv_client->netchan.message, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
sv_client->download = FS_LoadFile (name, &sv_client->downloadsize);
|
||||
sv_client->downloadcount = offset;
|
||||
|
||||
if (offset > sv_client->downloadsize)
|
||||
sv_client->downloadcount = sv_client->downloadsize;
|
||||
|
||||
if (!sv_client->download)
|
||||
{
|
||||
MsgDev( D_ERROR, "SV_BeginDownload_f: couldn't download %s to %s\n", name, sv_client->name);
|
||||
if (sv_client->download)
|
||||
{
|
||||
sv_client->download = NULL;
|
||||
}
|
||||
|
||||
MSG_WriteByte (&sv_client->netchan.message, svc_download);
|
||||
MSG_WriteShort (&sv_client->netchan.message, -1);
|
||||
MSG_WriteByte (&sv_client->netchan.message, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
SV_NextDownload_f ();
|
||||
MsgDev (D_INFO, "Downloading %s to %s\n", name, sv_client->name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
SV_Disconnect_f
|
||||
|
||||
The client is going to disconnect, so remove the connection immediately
|
||||
=================
|
||||
*/
|
||||
void SV_Disconnect_f (void)
|
||||
{
|
||||
// SV_EndRedirect ();
|
||||
SV_DropClient (sv_client);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_ShowServerinfo_f
|
||||
|
||||
Dumps the serverinfo info string
|
||||
==================
|
||||
*/
|
||||
void SV_ShowServerinfo_f (void)
|
||||
{
|
||||
Info_Print (Cvar_Serverinfo());
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
void (*func) (void);
|
||||
} ucmd_t;
|
||||
|
||||
ucmd_t ucmds[] =
|
||||
{
|
||||
// auto issued
|
||||
{"new", SV_New_f},
|
||||
{"configstrings", SV_Configstrings_f},
|
||||
{"baselines", SV_Baselines_f},
|
||||
{"begin", SV_Begin_f},
|
||||
{"disconnect", SV_Disconnect_f},
|
||||
{"info", SV_ShowServerinfo_f},
|
||||
{"download", SV_BeginDownload_f},
|
||||
{"nextdl", SV_NextDownload_f},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_ExecuteUserCommand
|
||||
==================
|
||||
*/
|
||||
void SV_ExecuteUserCommand (char *s)
|
||||
{
|
||||
ucmd_t *u;
|
||||
|
||||
Cmd_TokenizeString(s);
|
||||
sv_player = sv_client->edict;
|
||||
|
||||
for (u = ucmds; u->name; u++)
|
||||
{
|
||||
if (!strcmp (Cmd_Argv(0), u->name) )
|
||||
{
|
||||
u->func();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!u->name && sv.state == ss_active)
|
||||
{
|
||||
// custom client commands
|
||||
prog->globals.sv->pev = PRVM_EDICT_TO_PROG(sv_player);
|
||||
prog->globals.sv->time = sv.time;
|
||||
prog->globals.sv->frametime = sv.frametime;
|
||||
PRVM_ExecuteProgram (prog->globals.sv->ClientCommand, "QC function ClientCommand is missing");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
USER CMD EXECUTION
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
void SV_ClientThink (sv_client_t *cl, usercmd_t *cmd)
|
||||
{
|
||||
cl->commandMsec -= cmd->msec;
|
||||
|
||||
if (cl->commandMsec < 0 && sv_enforcetime->value )
|
||||
{
|
||||
MsgDev( D_ERROR, "SV_ClientThink: commandMsec underflow from %s\n", cl->name);
|
||||
return;
|
||||
}
|
||||
ClientThink (cl->edict, cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
SV_ExecuteClientMessage
|
||||
|
||||
The current net_message is parsed for the given client
|
||||
===================
|
||||
*/
|
||||
#define MAX_STRINGCMDS 8
|
||||
|
||||
void SV_ExecuteClientMessage (sv_client_t *cl)
|
||||
{
|
||||
int c;
|
||||
char *s;
|
||||
|
||||
usercmd_t nullcmd;
|
||||
usercmd_t oldest, oldcmd, newcmd;
|
||||
int net_drop;
|
||||
int stringCmdCount;
|
||||
int checksum, calculatedChecksum;
|
||||
int checksumIndex;
|
||||
bool move_issued;
|
||||
int lastframe;
|
||||
|
||||
sv_client = cl;
|
||||
sv_player = sv_client->edict;
|
||||
|
||||
// only allow one move command
|
||||
move_issued = false;
|
||||
stringCmdCount = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (net_message.readcount > net_message.cursize)
|
||||
{
|
||||
MsgDev( D_ERROR, "SV_ReadClientMessage: bad read\n");
|
||||
SV_DropClient (cl);
|
||||
return;
|
||||
}
|
||||
|
||||
c = MSG_ReadByte (&net_message);
|
||||
if (c == -1) break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
default:
|
||||
MsgDev( D_ERROR, "SV_ReadClientMessage: unknown command char\n");
|
||||
SV_DropClient (cl);
|
||||
return;
|
||||
|
||||
case clc_nop:
|
||||
break;
|
||||
|
||||
case clc_userinfo:
|
||||
strncpy (cl->userinfo, MSG_ReadString (&net_message), sizeof(cl->userinfo)-1);
|
||||
SV_UserinfoChanged (cl);
|
||||
break;
|
||||
|
||||
case clc_move:
|
||||
if (move_issued) return; // someone is trying to cheat...
|
||||
|
||||
move_issued = true;
|
||||
checksumIndex = net_message.readcount;
|
||||
checksum = MSG_ReadByte (&net_message);
|
||||
lastframe = MSG_ReadLong (&net_message);
|
||||
if (lastframe != cl->lastframe)
|
||||
{
|
||||
cl->lastframe = lastframe;
|
||||
if (cl->lastframe > 0)
|
||||
{
|
||||
cl->frame_latency[cl->lastframe&(LATENCY_COUNTS-1)] = svs.realtime - cl->frames[cl->lastframe & UPDATE_MASK].senttime;
|
||||
}
|
||||
}
|
||||
|
||||
memset (&nullcmd, 0, sizeof(nullcmd));
|
||||
MSG_ReadDeltaUsercmd (&net_message, &nullcmd, &oldest);
|
||||
MSG_ReadDeltaUsercmd (&net_message, &oldest, &oldcmd);
|
||||
MSG_ReadDeltaUsercmd (&net_message, &oldcmd, &newcmd);
|
||||
|
||||
if ( cl->state != cs_spawned )
|
||||
{
|
||||
cl->lastframe = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
// if the checksum fails, ignore the rest of the packet
|
||||
calculatedChecksum = CRC_Sequence(net_message.data + checksumIndex + 1, net_message.readcount - checksumIndex - 1, cl->netchan.incoming_sequence);
|
||||
|
||||
if (calculatedChecksum != checksum)
|
||||
{
|
||||
MsgDev( D_ERROR, "SV_ExecuteClientMessage: failed command checksum for %s (%d != %d)/%d\n", cl->name, calculatedChecksum, checksum, cl->netchan.incoming_sequence);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sv_paused->value)
|
||||
{
|
||||
net_drop = cl->netchan.dropped;
|
||||
if (net_drop < 20)
|
||||
{
|
||||
while (net_drop > 2)
|
||||
{
|
||||
SV_ClientThink (cl, &cl->lastcmd);
|
||||
net_drop--;
|
||||
}
|
||||
if (net_drop > 1) SV_ClientThink (cl, &oldest);
|
||||
if (net_drop > 0) SV_ClientThink (cl, &oldcmd);
|
||||
}
|
||||
SV_ClientThink (cl, &newcmd);
|
||||
}
|
||||
cl->lastcmd = newcmd;
|
||||
break;
|
||||
|
||||
case clc_stringcmd:
|
||||
s = MSG_ReadString (&net_message);
|
||||
|
||||
// malicious users may try using too many string commands
|
||||
if (++stringCmdCount < MAX_STRINGCMDS) SV_ExecuteUserCommand (s);
|
||||
if (cl->state == cs_zombie) return; // disconnect command
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1375,6 +1375,7 @@ void FS_ResetGameInfo( void )
|
|||
com_strcpy(GI.key, "demo" );
|
||||
com_strcpy(GI.basedir, gs_basedir );
|
||||
com_strcpy(GI.gamedir, gs_basedir );
|
||||
com_strcpy(GI.username, Sys_GetCurrentUser());
|
||||
GI.version = XASH_VERSION;
|
||||
GI.viewmode = 1;
|
||||
GI.gamemode = 1;
|
||||
|
|
|
@ -422,6 +422,7 @@ void Sys_CreateInstance( void )
|
|||
Sys.Free = Host->Free;
|
||||
Sys.CPrint = Host->CPrint;
|
||||
Sys.Cmd = Host->Cmd;
|
||||
Sys.MSG_Init = Host->MSG_Init;
|
||||
break;
|
||||
case HOST_CREDITS:
|
||||
Sys_Break( show_credits );
|
||||
|
@ -775,6 +776,25 @@ char *Sys_GetClipboardData( void )
|
|||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_GetCurrentUser
|
||||
|
||||
returns username for current profile
|
||||
================
|
||||
*/
|
||||
char *Sys_GetCurrentUser( void )
|
||||
{
|
||||
static string s_userName;
|
||||
dword size = sizeof( s_userName );
|
||||
|
||||
if( !GetUserName( s_userName, &size ))
|
||||
com_strcpy( s_userName, "player" );
|
||||
if( !s_userName[0] )
|
||||
com_strcpy( s_userName, "player" );
|
||||
|
||||
return s_userName;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
|
@ -1261,7 +1281,10 @@ sys_event_t Sys_GetEvent( void )
|
|||
MSG msg;
|
||||
sys_event_t ev;
|
||||
char *s;
|
||||
|
||||
sizebuf_t netmsg;
|
||||
netadr_t adr;
|
||||
static bool msg_init = false;
|
||||
|
||||
// return if we have data
|
||||
if( event_head > event_tail )
|
||||
{
|
||||
|
@ -1294,6 +1317,32 @@ sys_event_t Sys_GetEvent( void )
|
|||
com_strncpy( b, s, len - 1 );
|
||||
Sys_QueEvent( 0, SE_CONSOLE, 0, 0, len, b );
|
||||
}
|
||||
|
||||
// check for network packets
|
||||
if( Sys.MSG_Init )
|
||||
{
|
||||
msg_init = true;
|
||||
Sys.MSG_Init( &netmsg, Sys.packet_received, sizeof( Sys.packet_received ));
|
||||
if( NET_GetPacket( &adr, &netmsg ))
|
||||
{
|
||||
netadr_t *buf;
|
||||
int len;
|
||||
|
||||
// copy out to a seperate buffer for qeueing
|
||||
// the readcount stepahead is for SOCKS support
|
||||
len = sizeof(netadr_t) + netmsg.cursize - netmsg.readcount;
|
||||
buf = Malloc( len );
|
||||
*buf = adr;
|
||||
Mem_Copy( buf + 1, &netmsg.data[netmsg.readcount], netmsg.cursize - netmsg.readcount );
|
||||
Sys_QueEvent( 0, SE_PACKET, 0, 0, len, buf );
|
||||
}
|
||||
}
|
||||
else if( !msg_init )
|
||||
{
|
||||
MsgDev( D_NOTE, "Sys_GetEvent: network support disabled\n" );
|
||||
msg_init = true;
|
||||
}
|
||||
|
||||
// return if we have data
|
||||
if( event_head > event_tail )
|
||||
{
|
||||
|
|
|
@ -73,6 +73,7 @@ typedef struct system_s
|
|||
void ( *Free ) ( void ); // close host
|
||||
void ( *Cmd ) ( void ); // cmd forward to server
|
||||
void (*CPrint)( const char *msg ); // console print
|
||||
void (*MSG_Init)( sizebuf_t *buf, byte *data, size_t length );
|
||||
} system_t;
|
||||
|
||||
typedef struct cvar_s
|
||||
|
@ -119,6 +120,7 @@ void Sys_LookupInstance( void );
|
|||
double Sys_DoubleTime( void );
|
||||
dword Sys_Milliseconds( void );
|
||||
char *Sys_GetClipboardData( void );
|
||||
char *Sys_GetCurrentUser( void );
|
||||
void Sys_Sleep( int msec );
|
||||
void Sys_Init( void );
|
||||
void Sys_Exit( void );
|
||||
|
|
|
@ -300,8 +300,6 @@ a internal virtual machine like as QuakeC, but it has more extensions
|
|||
#define VPROGSHEADER32 (('2'<<24)+('3'<<16)+('D'<<8)+'I') // little-endian "ID32"
|
||||
#define LINENUMSHEADER (('F'<<24)+('O'<<16)+('N'<<8)+'L') // little-endian "LNOF"
|
||||
|
||||
#define MAX_EDICTS 4096 // must change protocol to increase more
|
||||
|
||||
#define PRVM_OP_STATE 1
|
||||
#define PRVM_FE_CHAIN 4
|
||||
#define PRVM_FE_CLASSNAME 8
|
||||
|
|
|
@ -51,4 +51,25 @@ static const char *xash_credits[] =
|
|||
0
|
||||
};
|
||||
|
||||
// internal huffman tree (from Q3)
|
||||
static const int huff_tree[256] =
|
||||
{
|
||||
250315, 41193, 6292, 7106, 3730, 3750, 6110, 23283, 33317, 6950, 7838, 9714, 9257, 17259, 3949, 1778,
|
||||
8288, 1604, 1590, 1663, 1100, 1213, 1238, 1134, 1749, 1059, 1246, 1149, 1273, 4486, 2805, 3472, 21819,
|
||||
1159, 1670, 1066, 1043, 1012, 1053, 1070, 1726, 888, 1180, 850, 960, 780, 1752, 3296, 10630, 4514, 5881,
|
||||
2685, 4650, 3837, 2093, 1867, 2584, 1949, 1972, 940, 1134, 1788, 1670, 1206, 5719, 6128, 7222, 6654,
|
||||
3710, 3795, 1492, 1524, 2215, 1140, 1355, 971, 2180, 1248, 1328, 1195, 1770, 1078, 1264, 1266, 1168,
|
||||
965, 1155, 1186, 1347, 1228, 1529, 1600, 2617, 2048, 2546, 3275, 2410, 3585, 2504, 2800, 2675, 6146,
|
||||
3663, 2840, 14253, 3164, 2221, 1687, 3208, 2739, 3512, 4796, 4091, 3515, 5288, 4016, 7937, 6031, 5360,
|
||||
3924, 4892, 3743, 4566, 4807, 5852, 6400, 6225, 8291, 23243, 7838, 7073, 8935, 5437, 4483, 3641, 5256,
|
||||
5312, 5328, 5370, 3492, 2458, 1694, 1821, 2121, 1916, 1149, 1516, 1367, 1236, 1029, 1258, 1104, 1245,
|
||||
1006, 1149, 1025, 1241, 952, 1287, 997, 1713, 1009, 1187, 879, 1099, 929, 1078, 951, 1656, 930, 1153,
|
||||
1030, 1262, 1062, 1214, 1060, 1621, 930, 1106, 912, 1034, 892, 1158, 990, 1175, 850, 1121, 903, 1087,
|
||||
920, 1144, 1056, 3462, 2240, 4397, 12136, 7758, 1345, 1307, 3278, 1950, 886, 1023, 1112, 1077, 1042,
|
||||
1061, 1071, 1484, 1001, 1096, 915, 1052, 995, 1070, 876, 1111, 851, 1059, 805, 1112, 923, 1103, 817,
|
||||
1899, 1872, 976, 841, 1127, 956, 1159, 950, 7791, 954, 1289, 933, 1127, 3207, 1020, 927, 1355, 768,
|
||||
1040, 745, 952, 805, 1073, 740, 1013, 805, 1008, 796, 996, 1057, 11457, 13504,
|
||||
};
|
||||
|
||||
|
||||
#endif//BUILTIN_H
|
|
@ -213,69 +213,6 @@ typedef struct
|
|||
|
||||
} refdef_t;
|
||||
|
||||
// viewmodel state
|
||||
typedef struct vmodel_state_s
|
||||
{
|
||||
int index; // client modelindex
|
||||
vec3_t angles; // can be some different with viewangles
|
||||
vec3_t offset; // center offset
|
||||
int sequence; // studio animation sequence
|
||||
float frame; // studio frame
|
||||
int body; // weapon body
|
||||
int skin; // weapon skin
|
||||
} vmodel_state_t;
|
||||
|
||||
// thirdperson model state
|
||||
typedef struct pmodel_state_s
|
||||
{
|
||||
int index; // client modelindex
|
||||
int sequence; // studio animation sequence
|
||||
float frame; // studio frame
|
||||
} pmodel_state_t;
|
||||
|
||||
// player_state_t communication
|
||||
typedef struct player_state_s
|
||||
{
|
||||
int bobcycle; // for view bobbing and footstep generation
|
||||
float bobtime;
|
||||
byte pm_type; // player movetype
|
||||
byte pm_flags; // ducked, jump_held, etc
|
||||
byte pm_time; // each unit = 8 ms
|
||||
|
||||
int origin[3];
|
||||
int velocity[3];
|
||||
vec3_t delta_angles; // add to command angles to get view direction
|
||||
short gravity; // gravity value
|
||||
short speed; // maxspeed
|
||||
edict_t *groundentity; // current ground entity
|
||||
int viewheight; // height over ground
|
||||
int effects; // copied to entity_state_t->effects
|
||||
int weapon; // copied to entity_state_t->weapon
|
||||
vec3_t viewangles; // for fixed views
|
||||
vec3_t viewoffset; // add to pmovestate->origin
|
||||
vec3_t kick_angles; // add to view direction to get render angles
|
||||
vec3_t oldviewangles; // for lerping viewmodel position
|
||||
vec4_t blend; // rgba full screen effect
|
||||
short stats[MAX_STATS];
|
||||
float fov; // horizontal field of view
|
||||
|
||||
// player model and viewmodel
|
||||
vmodel_state_t vmodel;
|
||||
pmodel_state_t pmodel;
|
||||
|
||||
} player_state_t;
|
||||
|
||||
// user_cmd_t communication
|
||||
typedef struct usercmd_s
|
||||
{
|
||||
byte msec;
|
||||
byte buttons;
|
||||
short angles[3];
|
||||
byte impulse; // remove?
|
||||
byte lightlevel; // light level the player is standing on
|
||||
short forwardmove, sidemove, upmove;
|
||||
} usercmd_t;
|
||||
|
||||
typedef struct pmove_s
|
||||
{
|
||||
player_state_t ps; // state (in / out)
|
||||
|
@ -315,6 +252,7 @@ typedef struct launch_exp_s
|
|||
void ( *Free ) ( void ); // close host
|
||||
void ( *Cmd ) ( void ); // forward cmd to server
|
||||
void (*CPrint) ( const char *msg ); // host print
|
||||
void (*MSG_Init)( sizebuf_t *buf, byte *data, size_t len ); // MSG network buffer
|
||||
} launch_exp_t;
|
||||
|
||||
/*
|
||||
|
@ -524,7 +462,7 @@ typedef struct vprogs_exp_s
|
|||
void (*Warning)( const char *fmt, ... );
|
||||
void (*Error)( const char *fmt, ... );
|
||||
|
||||
void (*ExecuteProgram)( func_t fnum, const char *errormessage );
|
||||
void (*ExecuteProgram)( func_t fnum, const char *name, const char *file, const int line );
|
||||
void (*Crash)( void ); // crash virtual machine
|
||||
|
||||
prvm_prog_t *prog; // virtual machine current state
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
|
||||
#define USE_COORD_FRAC
|
||||
|
||||
#define MAXEDICT_BITS 12 // 4096 entity per one map
|
||||
#define MAX_EDICTS (1<<MAXEDICT_BITS) // must change protocol to increase more
|
||||
#define MAX_DATAGRAM 1400 // datagram size
|
||||
#define MAX_MSGLEN 1600 // max length of network message
|
||||
|
||||
// network precision coords factor
|
||||
|
@ -21,7 +24,7 @@
|
|||
#define SV_ANGLE_FRAC (360.0f / 1.0f )
|
||||
#define CL_ANGLE_FRAC (1.0f / 360.0f )
|
||||
|
||||
typedef enum { NA_NONE, NA_LOOPBACK, NA_BROADCAST, NA_IP, NA_IPX, NA_BROADCAST_IPX } netadrtype_t;
|
||||
typedef enum { NA_BAD, NA_LOOPBACK, NA_BROADCAST, NA_IP, NA_IPX, NA_BROADCAST_IPX } netadrtype_t;
|
||||
typedef enum { NS_CLIENT, NS_SERVER } netsrc_t;
|
||||
|
||||
typedef struct
|
||||
|
@ -35,6 +38,7 @@ typedef struct
|
|||
typedef struct sizebuf_s
|
||||
{
|
||||
bool overflowed; // set to true if the buffer size failed
|
||||
bool huffman; // using huffman compression
|
||||
|
||||
byte *data;
|
||||
int maxsize;
|
||||
|
@ -44,5 +48,182 @@ typedef struct sizebuf_s
|
|||
int bit; // for bitwise reads and writes
|
||||
} sizebuf_t;
|
||||
|
||||
// communication state description
|
||||
typedef struct net_field_s
|
||||
{
|
||||
char *name;
|
||||
int offset;
|
||||
int bits;
|
||||
} net_field_t;
|
||||
|
||||
// entity_state_t communication
|
||||
typedef struct entity_state_s
|
||||
{
|
||||
uint number; // edict index
|
||||
|
||||
vec3_t origin;
|
||||
vec3_t angles;
|
||||
vec3_t old_origin; // for lerping animation
|
||||
int modelindex;
|
||||
int soundindex;
|
||||
int weaponmodel;
|
||||
|
||||
int skin; // skin for studiomodels
|
||||
float frame; // % playback position in animation sequences (0..512)
|
||||
int body; // sub-model selection for studiomodels
|
||||
int sequence; // animation sequence (0 - 255)
|
||||
uint effects; // PGM - we're filling it, so it needs to be unsigned
|
||||
int renderfx;
|
||||
int solid; // for client side prediction, 8*(bits 0-4) is x/y radius
|
||||
// 8*(bits 5-9) is z down distance, 8(bits10-15) is z up
|
||||
// gi.linkentity sets this properly
|
||||
float alpha; // alpha value
|
||||
float animtime; // auto-animating time
|
||||
|
||||
} entity_state_t;
|
||||
|
||||
// viewmodel state
|
||||
typedef struct vmodel_state_s
|
||||
{
|
||||
int index; // client modelindex
|
||||
vec3_t angles; // can be some different with viewangles
|
||||
vec3_t offset; // center offset
|
||||
int sequence; // studio animation sequence
|
||||
float frame; // studio frame
|
||||
int body; // weapon body
|
||||
int skin; // weapon skin
|
||||
} vmodel_state_t;
|
||||
|
||||
// thirdperson model state
|
||||
typedef struct pmodel_state_s
|
||||
{
|
||||
int index; // client modelindex
|
||||
int sequence; // studio animation sequence
|
||||
float frame; // studio frame
|
||||
} pmodel_state_t;
|
||||
|
||||
// player_state_t communication
|
||||
typedef struct player_state_s
|
||||
{
|
||||
int bobcycle; // for view bobbing and footstep generation
|
||||
float bobtime;
|
||||
int pm_type; // player movetype
|
||||
int pm_flags; // ducked, jump_held, etc
|
||||
int pm_time; // each unit = 8 ms
|
||||
|
||||
int origin[3];
|
||||
int velocity[3];
|
||||
vec3_t delta_angles; // add to command angles to get view direction
|
||||
int gravity; // gravity value
|
||||
int speed; // maxspeed
|
||||
edict_t *groundentity; // current ground entity
|
||||
int viewheight; // height over ground
|
||||
int effects; // copied to entity_state_t->effects
|
||||
vec3_t viewangles; // for fixed views
|
||||
vec3_t viewoffset; // add to pmovestate->origin
|
||||
vec3_t kick_angles; // add to view direction to get render angles
|
||||
vec3_t oldviewangles; // for lerping viewmodel position
|
||||
vec4_t blend; // rgba full screen effect
|
||||
int stats[32]; // integer limit
|
||||
float fov; // horizontal field of view
|
||||
|
||||
// player model and viewmodel
|
||||
vmodel_state_t vmodel;
|
||||
pmodel_state_t pmodel;
|
||||
|
||||
} player_state_t;
|
||||
|
||||
// usercmd_t communication
|
||||
typedef struct usercmd_s
|
||||
{
|
||||
byte msec;
|
||||
short angles[3];
|
||||
short forwardmove;
|
||||
short sidemove;
|
||||
short upmove;
|
||||
byte buttons;
|
||||
byte impulse;
|
||||
byte lightlevel;
|
||||
|
||||
} usercmd_t;
|
||||
|
||||
// 0 bits invoke to sending half or full float ( 13 or 31 bit )
|
||||
#define ENT_FIELD(x) #x,(int)&((entity_state_t*)0)->x
|
||||
#define PS_FIELD(x) #x,(int)&((player_state_t*)0)->x
|
||||
|
||||
static net_field_t ent_fields[] =
|
||||
{
|
||||
{ ENT_FIELD(number), MAXEDICT_BITS }, // 4096 ents
|
||||
{ ENT_FIELD(origin[0]), 0 },
|
||||
{ ENT_FIELD(origin[1]), 0 },
|
||||
{ ENT_FIELD(origin[2]), 0 },
|
||||
{ ENT_FIELD(angles[0]), 0 },
|
||||
{ ENT_FIELD(angles[1]), 0 },
|
||||
{ ENT_FIELD(angles[2]), 0 },
|
||||
{ ENT_FIELD(old_origin[0]), 0 },
|
||||
{ ENT_FIELD(old_origin[1]), 0 },
|
||||
{ ENT_FIELD(old_origin[2]), 0 },
|
||||
{ ENT_FIELD(modelindex), MAXEDICT_BITS }, // 4096 models
|
||||
{ ENT_FIELD(soundindex), 10 }, // 512 sounds ( OpenAL software limit is 255 )
|
||||
{ ENT_FIELD(weaponmodel), MAXEDICT_BITS }, // 4096 models
|
||||
{ ENT_FIELD(skin), 8 }, // 255 skins
|
||||
{ ENT_FIELD(frame), 0 }, // interpolate value
|
||||
{ ENT_FIELD(body), 8 }, // 255 bodies
|
||||
{ ENT_FIELD(sequence), 10 }, // 1024 sequences
|
||||
{ ENT_FIELD(effects), 32 }, // effect flags
|
||||
{ ENT_FIELD(renderfx), 32 }, // renderfx flags
|
||||
{ ENT_FIELD(solid), 24 }, // encoded mins/maxs
|
||||
{ ENT_FIELD(alpha), 0 }, // alpha value (FIXME: send a byte ? )
|
||||
{ ENT_FIELD(animtime), 0 }, // auto-animating time
|
||||
};
|
||||
|
||||
static net_field_t ps_fields[] =
|
||||
{
|
||||
{ PS_FIELD(pm_type), 4 }, // 16 player movetypes allowed
|
||||
{ PS_FIELD(pm_flags), 16 }, // 16 movetype flags allowed
|
||||
{ PS_FIELD(pm_time), 8 }, // each unit 8 msec
|
||||
{ PS_FIELD(origin[0]), 32 },
|
||||
{ PS_FIELD(origin[1]), 32 },
|
||||
{ PS_FIELD(origin[2]), 32 },
|
||||
{ PS_FIELD(velocity[0]), 32 },
|
||||
{ PS_FIELD(velocity[1]), 32 },
|
||||
{ PS_FIELD(velocity[2]), 32 },
|
||||
{ PS_FIELD(delta_angles[0]), 0 },
|
||||
{ PS_FIELD(delta_angles[1]), 0 },
|
||||
{ PS_FIELD(delta_angles[2]), 0 },
|
||||
{ PS_FIELD(gravity), 16 }, // may be 12 bits ?
|
||||
{ PS_FIELD(speed), 16 },
|
||||
{ PS_FIELD(viewheight), -8 }, // why hegative ?
|
||||
{ PS_FIELD(effects), 32 }, // copied to entity_state_t->effects
|
||||
{ PS_FIELD(viewangles[0]), 0 }, // for fixed views
|
||||
{ PS_FIELD(viewangles[1]), 0 },
|
||||
{ PS_FIELD(viewangles[2]), 0 },
|
||||
{ PS_FIELD(viewoffset[0]), 0 }, // get rid of this
|
||||
{ PS_FIELD(viewoffset[1]), 0 },
|
||||
{ PS_FIELD(viewoffset[2]), 0 },
|
||||
{ PS_FIELD(kick_angles[0]), 0 },
|
||||
{ PS_FIELD(kick_angles[1]), 0 },
|
||||
{ PS_FIELD(kick_angles[2]), 0 },
|
||||
{ PS_FIELD(blend[0]), 0 }, // FIXME: calc on client, don't send over the net
|
||||
{ PS_FIELD(blend[1]), 0 },
|
||||
{ PS_FIELD(blend[2]), 0 },
|
||||
{ PS_FIELD(blend[3]), 0 },
|
||||
{ PS_FIELD(fov), 0 }, // FIXME: send with userinfo ?
|
||||
{ PS_FIELD(vmodel.index), MAXEDICT_BITS }, // 4096 models
|
||||
{ PS_FIELD(vmodel.angles[0]), 0 }, // can be some different with viewangles
|
||||
{ PS_FIELD(vmodel.angles[1]), 0 },
|
||||
{ PS_FIELD(vmodel.angles[2]), 0 },
|
||||
{ PS_FIELD(vmodel.offset[0]), 0 }, // center offset
|
||||
{ PS_FIELD(vmodel.offset[1]), 0 },
|
||||
{ PS_FIELD(vmodel.offset[2]), 0 },
|
||||
{ PS_FIELD(vmodel.sequence), 10 }, // 1024 sequences
|
||||
{ PS_FIELD(vmodel.frame), 0 }, // interpolate value
|
||||
{ PS_FIELD(vmodel.body), 8 }, // 255 bodies
|
||||
{ PS_FIELD(vmodel.skin), 8 }, // 255 skins
|
||||
{ PS_FIELD(pmodel.index), MAXEDICT_BITS }, // 4096 models
|
||||
{ PS_FIELD(pmodel.sequence), 10 }, // 1024 sequences
|
||||
{ PS_FIELD(vmodel.frame), 0 }, // interpolate value
|
||||
};
|
||||
|
||||
|
||||
#endif//PROTOCOL_H
|
|
@ -1150,7 +1150,8 @@ typedef struct gameinfo_s
|
|||
string gamedir;
|
||||
string startmap;
|
||||
string title;
|
||||
float version; // engine or mod version
|
||||
string username; // OS current user
|
||||
float version; // engine or mod version
|
||||
|
||||
int viewmode;
|
||||
int gamemode;
|
||||
|
|
6
todo.log
6
todo.log
|
@ -34,8 +34,10 @@ fopen
|
|||
11. Исправить текстуры для p_model OK
|
||||
12. вернуть старый netchan OK
|
||||
13. вынести поддержку сети в launch.dll OK
|
||||
14. включить систему системных эвентов
|
||||
15. переписать код message
|
||||
14. включить систему системных эвентов OK
|
||||
15. перенести код от 11.07.08 OK
|
||||
16. переписать код message
|
||||
17. Исправить сохранялки
|
||||
|
||||
Физика игрока:
|
||||
1. Убрать отскоки от стен
|
||||
|
|
|
@ -1129,7 +1129,7 @@ void PRVM_ED_LoadFromFile (const char *data)
|
|||
if(vm.prog->pev && vm.prog->flag & PRVM_FE_CLASSNAME)
|
||||
{
|
||||
string_t handle = *(string_t*)&((byte*)ent->progs.vp)[PRVM_ED_FindFieldOffset("classname")];
|
||||
if (!handle)
|
||||
if( !handle )
|
||||
{
|
||||
if(prvm_developer >= D_NOTE)
|
||||
{
|
||||
|
@ -1143,7 +1143,7 @@ void PRVM_ED_LoadFromFile (const char *data)
|
|||
// look for the spawn function
|
||||
func = PRVM_ED_FindFunction (PRVM_GetString(handle));
|
||||
|
||||
if (!func)
|
||||
if( !func )
|
||||
{
|
||||
if(prvm_developer >= D_NOTE)
|
||||
{
|
||||
|
@ -1156,7 +1156,7 @@ void PRVM_ED_LoadFromFile (const char *data)
|
|||
|
||||
// pev = ent
|
||||
PRVM_G_INT(vm.prog->pev->ofs) = PRVM_EDICT_TO_PROG(ent);
|
||||
PRVM_ExecuteProgram (func - vm.prog->functions, "" );
|
||||
PRVM_ExecuteProgram( func - vm.prog->functions, "", __FILE__, __LINE__ );
|
||||
}
|
||||
|
||||
spawned++;
|
||||
|
|
|
@ -531,7 +531,7 @@ extern cvar_t *prvm_statementprofiling;
|
|||
extern int PRVM_ED_FindFieldOffset (const char *field);
|
||||
extern ddef_t* PRVM_ED_FindGlobal(const char *name);
|
||||
|
||||
void PRVM_ExecuteProgram( func_t fnum, const char *errormessage )
|
||||
void PRVM_ExecuteProgram( func_t fnum, const char *name, const char *file, const int line )
|
||||
{
|
||||
dstatement_t *st, *startst;
|
||||
mfunction_t *f, *newf;
|
||||
|
@ -544,7 +544,7 @@ void PRVM_ExecuteProgram( func_t fnum, const char *errormessage )
|
|||
{
|
||||
if( vm.prog->pev && PRVM_G_INT(vm.prog->pev->ofs) )
|
||||
PRVM_ED_Print(PRVM_PROG_TO_EDICT(PRVM_G_INT(vm.prog->pev->ofs)));
|
||||
PRVM_ERROR ("PRVM_ExecuteProgram: %s", errormessage);
|
||||
PRVM_ERROR( "PRVM_ExecuteProgram: QC function %s is missing( called at %s:%i)\n", name, file, line );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -573,10 +573,10 @@ chooseexecprogram:
|
|||
{
|
||||
st++;
|
||||
|
||||
if (vm.prog->trace) PRVM_PrintStatement(st);
|
||||
if (prvm_statementprofiling->value) vm.prog->statement_profile[st - vm.prog->statements]++;
|
||||
if( vm.prog->trace ) PRVM_PrintStatement(st);
|
||||
if( prvm_statementprofiling->value ) vm.prog->statement_profile[st - vm.prog->statements]++;
|
||||
|
||||
switch (st->op)
|
||||
switch( st->op )
|
||||
{
|
||||
case OP_ADD_F:
|
||||
OPC->_float = OPA->_float + OPB->_float;
|
||||
|
@ -1404,7 +1404,7 @@ chooseexecprogram:
|
|||
default:
|
||||
vm.prog->xfunction->profile += (st - startst);
|
||||
vm.prog->xstatement = st - vm.prog->statements;
|
||||
PRVM_ERROR ("Bad opcode %i in %s", st->op, PRVM_NAME);
|
||||
PRVM_ERROR( "Bad opcode %i in %s (called at %s:%i)\n", st->op, PRVM_NAME, file, line );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -328,7 +328,7 @@ void PRVM_Globals_f( void );
|
|||
void PRVM_Global_f( void );
|
||||
void PRVM_Fields_f( void );
|
||||
|
||||
void PRVM_ExecuteProgram (func_t fnum, const char *errormessage);
|
||||
void PRVM_ExecuteProgram( func_t fnum, const char *name, const char *file, const int line );
|
||||
|
||||
#define PRVM_Alloc(buffersize) _PRVM_Alloc(buffersize, __FILE__, __LINE__)
|
||||
#define PRVM_Free(buffer) _PRVM_Free(buffer, __FILE__, __LINE__)
|
||||
|
|
|
@ -13,14 +13,14 @@
|
|||
#include "stdref.h"
|
||||
#include "basefiles.h"
|
||||
#include "dllapi.h"
|
||||
#include "mathlib.h"
|
||||
|
||||
#include "s_openal.h"
|
||||
|
||||
extern stdlib_api_t com;
|
||||
extern vsound_imp_t si;
|
||||
extern byte *sndpool;
|
||||
|
||||
#include "mathlib.h"
|
||||
|
||||
enum
|
||||
{
|
||||
CHAN_FIRSTPLAY,
|
||||
|
|
Reference in New Issue