13 Jul 2008

This commit is contained in:
g-cont 2008-07-13 00:00:00 +04:00 committed by Alibek Omarov
parent dbe530e5f0
commit 3c0e835e60
49 changed files with 3216 additions and 3093 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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