Apply 4150 update
This commit is contained in:
parent
a539384a76
commit
1e7f9d00c3
40 changed files with 1976 additions and 511 deletions
|
@ -40,7 +40,7 @@ GNU General Public License for more details.
|
||||||
#define PARM_TEX_MIPCOUNT 15 // count of mipmaps (0 - autogenerated, 1 - disabled of mipmapping)
|
#define PARM_TEX_MIPCOUNT 15 // count of mipmaps (0 - autogenerated, 1 - disabled of mipmapping)
|
||||||
#define PARM_BSP2_SUPPORTED 16 // tell custom renderer what engine is support BSP2 in this build
|
#define PARM_BSP2_SUPPORTED 16 // tell custom renderer what engine is support BSP2 in this build
|
||||||
#define PARM_SKY_SPHERE 17 // sky is quake sphere ?
|
#define PARM_SKY_SPHERE 17 // sky is quake sphere ?
|
||||||
//reserved
|
#define PARAM_GAMEPAUSED 18 // game is paused
|
||||||
#define PARM_MAP_HAS_DELUXE 19 // map has deluxedata
|
#define PARM_MAP_HAS_DELUXE 19 // map has deluxedata
|
||||||
#define PARM_MAX_ENTITIES 20
|
#define PARM_MAX_ENTITIES 20
|
||||||
#define PARM_WIDESCREEN 21
|
#define PARM_WIDESCREEN 21
|
||||||
|
|
242
engine/client/cl_debug.c
Normal file
242
engine/client/cl_debug.c
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
/*
|
||||||
|
cl_debug.c - server message debugging
|
||||||
|
Copyright (C) 2018 Uncle Mike
|
||||||
|
|
||||||
|
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 3 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "net_encode.h"
|
||||||
|
#include "particledef.h"
|
||||||
|
#include "gl_local.h"
|
||||||
|
#include "cl_tent.h"
|
||||||
|
#include "shake.h"
|
||||||
|
#include "hltv.h"
|
||||||
|
#include "input.h"
|
||||||
|
|
||||||
|
#define MSG_COUNT 32 // last 32 messages parsed
|
||||||
|
#define MSG_MASK (MSG_COUNT - 1)
|
||||||
|
|
||||||
|
const char *svc_strings[svc_lastmsg+1] =
|
||||||
|
{
|
||||||
|
"svc_bad",
|
||||||
|
"svc_nop",
|
||||||
|
"svc_disconnect",
|
||||||
|
"svc_event",
|
||||||
|
"svc_changing",
|
||||||
|
"svc_setview",
|
||||||
|
"svc_sound",
|
||||||
|
"svc_time",
|
||||||
|
"svc_print",
|
||||||
|
"svc_stufftext",
|
||||||
|
"svc_setangle",
|
||||||
|
"svc_serverdata",
|
||||||
|
"svc_lightstyle",
|
||||||
|
"svc_updateuserinfo",
|
||||||
|
"svc_deltatable",
|
||||||
|
"svc_clientdata",
|
||||||
|
"svc_resource",
|
||||||
|
"svc_pings",
|
||||||
|
"svc_particle",
|
||||||
|
"svc_restoresound",
|
||||||
|
"svc_spawnstatic",
|
||||||
|
"svc_event_reliable",
|
||||||
|
"svc_spawnbaseline",
|
||||||
|
"svc_temp_entity",
|
||||||
|
"svc_setpause",
|
||||||
|
"svc_signonnum",
|
||||||
|
"svc_centerprint",
|
||||||
|
"svc_unused27",
|
||||||
|
"svc_unused28",
|
||||||
|
"svc_unused29",
|
||||||
|
"svc_intermission",
|
||||||
|
"svc_finale",
|
||||||
|
"svc_cdtrack",
|
||||||
|
"svc_restore",
|
||||||
|
"svc_cutscene",
|
||||||
|
"svc_weaponanim",
|
||||||
|
"svc_bspdecal",
|
||||||
|
"svc_roomtype",
|
||||||
|
"svc_addangle",
|
||||||
|
"svc_usermessage",
|
||||||
|
"svc_packetentities",
|
||||||
|
"svc_deltapacketentities",
|
||||||
|
"svc_choke",
|
||||||
|
"svc_resourcelist",
|
||||||
|
"svc_deltamovevars",
|
||||||
|
"svc_resourcerequest",
|
||||||
|
"svc_customization",
|
||||||
|
"svc_crosshairangle",
|
||||||
|
"svc_soundfade",
|
||||||
|
"svc_filetxferfailed",
|
||||||
|
"svc_hltv",
|
||||||
|
"svc_director",
|
||||||
|
"svc_voiceinit",
|
||||||
|
"svc_voicedata",
|
||||||
|
"svc_unused54",
|
||||||
|
"svc_unused55",
|
||||||
|
"svc_resourcelocation",
|
||||||
|
"svc_querycvarvalue",
|
||||||
|
"svc_querycvarvalue2",
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int command;
|
||||||
|
int starting_offset;
|
||||||
|
int frame_number;
|
||||||
|
} oldcmd_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
oldcmd_t oldcmd[MSG_COUNT];
|
||||||
|
int currentcmd;
|
||||||
|
qboolean parsing;
|
||||||
|
} msg_debug_t;
|
||||||
|
|
||||||
|
static msg_debug_t cls_message_debug;
|
||||||
|
|
||||||
|
const char *CL_MsgInfo( int cmd )
|
||||||
|
{
|
||||||
|
static string sz;
|
||||||
|
|
||||||
|
Q_strcpy( sz, "???" );
|
||||||
|
|
||||||
|
if( cmd >= 0 && cmd <= svc_lastmsg )
|
||||||
|
{
|
||||||
|
// get engine message name
|
||||||
|
Q_strncpy( sz, svc_strings[cmd], sizeof( sz ));
|
||||||
|
}
|
||||||
|
else if( cmd > svc_lastmsg && cmd <= ( svc_lastmsg + MAX_USER_MESSAGES ))
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for( i = 0; i < MAX_USER_MESSAGES; i++ )
|
||||||
|
{
|
||||||
|
if( clgame.msg[i].number == cmd )
|
||||||
|
{
|
||||||
|
Q_strncpy( sz, clgame.msg[i].name, sizeof( sz ));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================
|
||||||
|
CL_Parse_Debug
|
||||||
|
|
||||||
|
enable message debugging
|
||||||
|
=====================
|
||||||
|
*/
|
||||||
|
void CL_Parse_Debug( qboolean enable )
|
||||||
|
{
|
||||||
|
cls_message_debug.parsing = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================
|
||||||
|
CL_Parse_RecordCommand
|
||||||
|
|
||||||
|
record new message params into debug buffer
|
||||||
|
=====================
|
||||||
|
*/
|
||||||
|
void CL_Parse_RecordCommand( int cmd, int startoffset )
|
||||||
|
{
|
||||||
|
int slot;
|
||||||
|
|
||||||
|
if( cmd == svc_nop ) return;
|
||||||
|
|
||||||
|
slot = ( cls_message_debug.currentcmd++ & MSG_MASK );
|
||||||
|
cls_message_debug.oldcmd[slot].command = cmd;
|
||||||
|
cls_message_debug.oldcmd[slot].starting_offset = startoffset;
|
||||||
|
cls_message_debug.oldcmd[slot].frame_number = host.framecount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================
|
||||||
|
CL_ResetFrame
|
||||||
|
=====================
|
||||||
|
*/
|
||||||
|
void CL_ResetFrame( frame_t *frame )
|
||||||
|
{
|
||||||
|
memset( &frame->graphdata, 0, sizeof( netbandwidthgraph_t ));
|
||||||
|
frame->receivedtime = host.realtime;
|
||||||
|
frame->valid = true;
|
||||||
|
frame->choked = false;
|
||||||
|
frame->latency = 0.0;
|
||||||
|
frame->time = cl.mtime[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================
|
||||||
|
CL_WriteErrorMessage
|
||||||
|
|
||||||
|
write net_message into buffer.dat for debugging
|
||||||
|
=====================
|
||||||
|
*/
|
||||||
|
static void CL_WriteErrorMessage( int current_count, sizebuf_t *msg )
|
||||||
|
{
|
||||||
|
const char *buffer_file = "buffer.dat";
|
||||||
|
file_t *fp;
|
||||||
|
|
||||||
|
fp = FS_Open( buffer_file, "wb", false );
|
||||||
|
if( !fp ) return;
|
||||||
|
|
||||||
|
FS_Write( fp, &cls.starting_count, sizeof( int ));
|
||||||
|
FS_Write( fp, ¤t_count, sizeof( int ));
|
||||||
|
FS_Write( fp, MSG_GetData( msg ), MSG_GetMaxBytes( msg ));
|
||||||
|
FS_Close( fp );
|
||||||
|
|
||||||
|
Con_Printf( "Wrote erroneous message to %s\n", buffer_file );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================
|
||||||
|
CL_WriteMessageHistory
|
||||||
|
|
||||||
|
list last 32 messages for debugging net troubleshooting
|
||||||
|
=====================
|
||||||
|
*/
|
||||||
|
void CL_WriteMessageHistory( void )
|
||||||
|
{
|
||||||
|
oldcmd_t *old, *failcommand;
|
||||||
|
sizebuf_t *msg = &net_message;
|
||||||
|
int i, thecmd;
|
||||||
|
|
||||||
|
if( !cls.initialized || cls.state == ca_disconnected )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( !cls_message_debug.parsing )
|
||||||
|
return;
|
||||||
|
|
||||||
|
Con_Printf( "Last %i messages parsed.\n", MSG_COUNT );
|
||||||
|
|
||||||
|
// finish here
|
||||||
|
thecmd = cls_message_debug.currentcmd - 1;
|
||||||
|
thecmd -= ( MSG_COUNT - 1 ); // back up to here
|
||||||
|
|
||||||
|
for( i = 0; i < MSG_COUNT - 1; i++ )
|
||||||
|
{
|
||||||
|
thecmd &= MSG_MASK;
|
||||||
|
old = &cls_message_debug.oldcmd[thecmd];
|
||||||
|
Con_Printf( "%i %04i %s\n", old->frame_number, old->starting_offset, CL_MsgInfo( old->command ));
|
||||||
|
thecmd++;
|
||||||
|
}
|
||||||
|
|
||||||
|
failcommand = &cls_message_debug.oldcmd[thecmd];
|
||||||
|
Con_Printf( "BAD: %3i:%s\n", MSG_GetNumBytesRead( msg ) - 1, CL_MsgInfo( failcommand->command ));
|
||||||
|
if( host_developer.value >= DEV_EXTENDED )
|
||||||
|
CL_WriteErrorMessage( MSG_GetNumBytesRead( msg ) - 1, msg );
|
||||||
|
cls_message_debug.parsing = false;
|
||||||
|
}
|
|
@ -626,6 +626,74 @@ void CL_ReadDemoSequence( qboolean discard )
|
||||||
cls.netchan.last_reliable_sequence = last_reliable_sequence;
|
cls.netchan.last_reliable_sequence = last_reliable_sequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
CL_DemoStartPlayback
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void CL_DemoStartPlayback( int mode )
|
||||||
|
{
|
||||||
|
if( cls.changedemo )
|
||||||
|
{
|
||||||
|
S_StopAllSounds( true );
|
||||||
|
SCR_BeginLoadingPlaque( false );
|
||||||
|
|
||||||
|
CL_ClearState ();
|
||||||
|
CL_InitEdicts (); // re-arrange edicts
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// NOTE: at this point demo is still valid
|
||||||
|
CL_Disconnect();
|
||||||
|
Host_ShutdownServer();
|
||||||
|
|
||||||
|
Con_FastClose();
|
||||||
|
UI_SetActiveMenu( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
cls.demoplayback = mode;
|
||||||
|
cls.state = ca_connected;
|
||||||
|
cl.background = (cls.demonum != -1) ? true : false;
|
||||||
|
cls.spectator = false;
|
||||||
|
cls.signon = 0;
|
||||||
|
|
||||||
|
demo.starttime = CL_GetDemoPlaybackClock(); // for determining whether to read another message
|
||||||
|
|
||||||
|
Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize );
|
||||||
|
|
||||||
|
memset( demo.cmds, 0, sizeof( demo.cmds ));
|
||||||
|
demo.angle_position = 1;
|
||||||
|
demo.framecount = 0;
|
||||||
|
cls.lastoutgoingcommand = -1;
|
||||||
|
cls.nextcmdtime = host.realtime;
|
||||||
|
cl.last_command_ack = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
CL_PlayDemoQuake
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void CL_PlayDemoQuake( const char *demoname )
|
||||||
|
{
|
||||||
|
int c, neg = false;
|
||||||
|
|
||||||
|
cls.demofile = FS_Open( demoname, "rb", true );
|
||||||
|
Q_strncpy( cls.demoname, demoname, sizeof( cls.demoname ));
|
||||||
|
Q_strncpy( gameui.globals->demoname, demoname, sizeof( gameui.globals->demoname ));
|
||||||
|
demo.header.host_fps = host_maxfps->value;
|
||||||
|
cls.forcetrack = 0;
|
||||||
|
|
||||||
|
while(( c = FS_Getc( cls.demofile )) != '\n' )
|
||||||
|
{
|
||||||
|
if( c == '-' ) neg = true;
|
||||||
|
else cls.forcetrack = cls.forcetrack * 10 + (c - '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
if( neg ) cls.forcetrack = -cls.forcetrack;
|
||||||
|
CL_DemoStartPlayback( DEMO_QUAKE1 );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
CL_DemoAborted
|
CL_DemoAborted
|
||||||
|
@ -735,6 +803,94 @@ qboolean CL_ReadRawNetworkData( byte *buffer, size_t *length )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
CL_DemoReadMessageQuake
|
||||||
|
|
||||||
|
reads demo data and write it to client
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
qboolean CL_DemoReadMessageQuake( byte *buffer, size_t *length )
|
||||||
|
{
|
||||||
|
int msglen = 0;
|
||||||
|
demoangle_t *a;
|
||||||
|
|
||||||
|
*length = 0; // assume we fail
|
||||||
|
|
||||||
|
// decide if it is time to grab the next message
|
||||||
|
if( cls.signon == SIGNONS ) // allways grab until fully connected
|
||||||
|
{
|
||||||
|
if( cls.timedemo )
|
||||||
|
{
|
||||||
|
if( host.framecount == cls.td_lastframe )
|
||||||
|
return false; // already read this frame's message
|
||||||
|
|
||||||
|
cls.td_lastframe = host.framecount;
|
||||||
|
|
||||||
|
// if this is the second frame, grab the real td_starttime
|
||||||
|
// so the bogus time on the first frame doesn't count
|
||||||
|
if( host.framecount == cls.td_startframe + 1 )
|
||||||
|
cls.td_starttime = host.realtime;
|
||||||
|
}
|
||||||
|
else if( cl.time <= cl.mtime[0] )
|
||||||
|
{
|
||||||
|
// don't need another message yet
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the next message
|
||||||
|
FS_Read( cls.demofile, &msglen, sizeof( int ));
|
||||||
|
FS_Read( cls.demofile, &cl.viewangles[0], sizeof( float ));
|
||||||
|
FS_Read( cls.demofile, &cl.viewangles[1], sizeof( float ));
|
||||||
|
FS_Read( cls.demofile, &cl.viewangles[2], sizeof( float ));
|
||||||
|
cls.netchan.incoming_sequence++;
|
||||||
|
|
||||||
|
// make sure what interp info contain angles from different frames
|
||||||
|
// or lerping will stop working
|
||||||
|
if( demo.lasttime != demo.timestamp )
|
||||||
|
{
|
||||||
|
// select entry into circular buffer
|
||||||
|
demo.angle_position = (demo.angle_position + 1) & ANGLE_MASK;
|
||||||
|
a = &demo.cmds[demo.angle_position];
|
||||||
|
|
||||||
|
// record update
|
||||||
|
a->starttime = demo.timestamp;
|
||||||
|
VectorCopy( cl.viewangles, a->viewangles );
|
||||||
|
demo.lasttime = demo.timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( msglen < 0 )
|
||||||
|
{
|
||||||
|
MsgDev( D_ERROR, "Demo message length < 0\n" );
|
||||||
|
CL_DemoCompleted();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( msglen > MAX_INIT_MSG )
|
||||||
|
{
|
||||||
|
MsgDev( D_ERROR, "Demo message %i > %i\n", msglen, MAX_INIT_MSG );
|
||||||
|
CL_DemoCompleted();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( msglen > 0 )
|
||||||
|
{
|
||||||
|
if( FS_Read( cls.demofile, buffer, msglen ) != msglen )
|
||||||
|
{
|
||||||
|
MsgDev( D_ERROR, "Error reading demo message data\n" );
|
||||||
|
CL_DemoCompleted();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*length = msglen;
|
||||||
|
|
||||||
|
if( cls.state != ca_active )
|
||||||
|
Cbuf_Execute();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
CL_DemoReadMessage
|
CL_DemoReadMessage
|
||||||
|
@ -765,6 +921,9 @@ qboolean CL_DemoReadMessage( byte *buffer, size_t *length )
|
||||||
return false; // paused
|
return false; // paused
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( cls.demoplayback == DEMO_QUAKE1 )
|
||||||
|
return CL_DemoReadMessageQuake( buffer, length );
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
qboolean bSkipMessage = false;
|
qboolean bSkipMessage = false;
|
||||||
|
@ -933,7 +1092,8 @@ void CL_DemoInterpolateAngles( void )
|
||||||
QuaternionSlerp( q2, q1, frac, q );
|
QuaternionSlerp( q2, q1, frac, q );
|
||||||
QuaternionAngle( q, cl.viewangles );
|
QuaternionAngle( q, cl.viewangles );
|
||||||
}
|
}
|
||||||
else VectorCopy( cl.cmd->viewangles, cl.viewangles );
|
else if( cls.demoplayback != DEMO_QUAKE1 )
|
||||||
|
VectorCopy( cl.cmd->viewangles, cl.viewangles );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -976,6 +1136,7 @@ void CL_StopPlayback( void )
|
||||||
cls.demofile = NULL;
|
cls.demofile = NULL;
|
||||||
|
|
||||||
cls.olddemonum = Q_max( -1, cls.demonum - 1 );
|
cls.olddemonum = Q_max( -1, cls.demonum - 1 );
|
||||||
|
if( demo.directory.entries != NULL )
|
||||||
Mem_Free( demo.directory.entries );
|
Mem_Free( demo.directory.entries );
|
||||||
cls.td_lastframe = host.framecount;
|
cls.td_lastframe = host.framecount;
|
||||||
demo.directory.numentries = 0;
|
demo.directory.numentries = 0;
|
||||||
|
@ -1110,6 +1271,35 @@ qboolean CL_NextDemo( void )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
CL_CheckStartupDemos
|
||||||
|
|
||||||
|
queue demos loop after movie playing
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
void CL_CheckStartupDemos( void )
|
||||||
|
{
|
||||||
|
if( !cls.demos_pending )
|
||||||
|
return; // no demos in loop
|
||||||
|
|
||||||
|
if( cls.movienum != -1 )
|
||||||
|
return; // wait until movies finished
|
||||||
|
|
||||||
|
if( GameState->nextstate != STATE_RUNFRAME || cls.demoplayback )
|
||||||
|
{
|
||||||
|
// commandline override
|
||||||
|
cls.demos_pending = false;
|
||||||
|
cls.demonum = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// run demos loop in background mode
|
||||||
|
Cvar_SetValue( "v_dark", 1.0f );
|
||||||
|
cls.demonum = 0;
|
||||||
|
CL_NextDemo ();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
CL_DemoGetName
|
CL_DemoGetName
|
||||||
|
@ -1230,8 +1420,9 @@ playdemo <demoname>
|
||||||
*/
|
*/
|
||||||
void CL_PlayDemo_f( void )
|
void CL_PlayDemo_f( void )
|
||||||
{
|
{
|
||||||
string filename;
|
char filename1[MAX_QPATH];
|
||||||
string demoname;
|
char filename2[MAX_QPATH];
|
||||||
|
char demoname[MAX_QPATH];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if( Cmd_Argc() != 2 )
|
if( Cmd_Argc() != 2 )
|
||||||
|
@ -1251,17 +1442,24 @@ void CL_PlayDemo_f( void )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_strncpy( demoname, Cmd_Argv( 1 ), sizeof( demoname ) - 1 );
|
Q_strncpy( demoname, Cmd_Argv( 1 ), sizeof( demoname ));
|
||||||
Q_snprintf( filename, sizeof( filename ), "demos/%s.dem", demoname );
|
COM_StripExtension( demoname );
|
||||||
|
Q_snprintf( filename1, sizeof( filename1 ), "%s.dem", demoname );
|
||||||
|
Q_snprintf( filename2, sizeof( filename2 ), "demos/%s.dem", demoname );
|
||||||
|
|
||||||
if( !FS_FileExists( filename, true ))
|
if( FS_FileExists( filename1, true ))
|
||||||
{
|
{
|
||||||
MsgDev( D_ERROR, "couldn't open %s\n", filename );
|
CL_PlayDemoQuake( filename1 );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if( !FS_FileExists( filename2, true ))
|
||||||
|
{
|
||||||
|
MsgDev( D_ERROR, "couldn't open %s\n", filename2 );
|
||||||
CL_DemoAborted();
|
CL_DemoAborted();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cls.demofile = FS_Open( filename, "rb", true );
|
cls.demofile = FS_Open( filename2, "rb", true );
|
||||||
Q_strncpy( cls.demoname, demoname, sizeof( cls.demoname ));
|
Q_strncpy( cls.demoname, demoname, sizeof( cls.demoname ));
|
||||||
Q_strncpy( gameui.globals->demoname, demoname, sizeof( gameui.globals->demoname ));
|
Q_strncpy( gameui.globals->demoname, demoname, sizeof( gameui.globals->demoname ));
|
||||||
|
|
||||||
|
@ -1270,7 +1468,7 @@ void CL_PlayDemo_f( void )
|
||||||
|
|
||||||
if( demo.header.id != IDEMOHEADER )
|
if( demo.header.id != IDEMOHEADER )
|
||||||
{
|
{
|
||||||
MsgDev( D_ERROR, "%s is not a demo file\n", filename );
|
MsgDev( D_ERROR, "%s is not a demo file\n", demoname );
|
||||||
CL_DemoAborted();
|
CL_DemoAborted();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1297,24 +1495,6 @@ void CL_PlayDemo_f( void )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( cls.changedemo )
|
|
||||||
{
|
|
||||||
S_StopAllSounds( true );
|
|
||||||
SCR_BeginLoadingPlaque( false );
|
|
||||||
|
|
||||||
CL_ClearState ();
|
|
||||||
CL_InitEdicts (); // re-arrange edicts
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// NOTE: at this point demo is still valid
|
|
||||||
CL_Disconnect();
|
|
||||||
Host_ShutdownServer();
|
|
||||||
|
|
||||||
Con_FastClose();
|
|
||||||
UI_SetActiveMenu( false );
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate demo entries
|
// allocate demo entries
|
||||||
demo.directory.entries = Mem_Malloc( cls.mempool, sizeof( demoentry_t ) * demo.directory.numentries );
|
demo.directory.entries = Mem_Malloc( cls.mempool, sizeof( demoentry_t ) * demo.directory.numentries );
|
||||||
|
|
||||||
|
@ -1328,22 +1508,7 @@ void CL_PlayDemo_f( void )
|
||||||
|
|
||||||
FS_Seek( cls.demofile, demo.entry->offset, SEEK_SET );
|
FS_Seek( cls.demofile, demo.entry->offset, SEEK_SET );
|
||||||
|
|
||||||
cls.demoplayback = true;
|
CL_DemoStartPlayback( DEMO_XASH3D );
|
||||||
cls.state = ca_connected;
|
|
||||||
cl.background = (cls.demonum != -1) ? true : false;
|
|
||||||
cls.spectator = false;
|
|
||||||
cls.signon = 0;
|
|
||||||
|
|
||||||
demo.starttime = CL_GetDemoPlaybackClock(); // for determining whether to read another message
|
|
||||||
|
|
||||||
Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize );
|
|
||||||
|
|
||||||
memset( demo.cmds, 0, sizeof( demo.cmds ));
|
|
||||||
demo.angle_position = 1;
|
|
||||||
demo.framecount = 0;
|
|
||||||
cls.lastoutgoingcommand = -1;
|
|
||||||
cls.nextcmdtime = host.realtime;
|
|
||||||
cl.last_command_ack = -1;
|
|
||||||
|
|
||||||
// g-cont. is this need?
|
// g-cont. is this need?
|
||||||
Q_strncpy( cls.servername, demoname, sizeof( cls.servername ));
|
Q_strncpy( cls.servername, demoname, sizeof( cls.servername ));
|
||||||
|
@ -1402,15 +1567,7 @@ void CL_StartDemos_f( void )
|
||||||
|
|
||||||
for( i = 1; i < c + 1; i++ )
|
for( i = 1; i < c + 1; i++ )
|
||||||
Q_strncpy( cls.demos[i-1], Cmd_Argv( i ), sizeof( cls.demos[0] ));
|
Q_strncpy( cls.demos[i-1], Cmd_Argv( i ), sizeof( cls.demos[0] ));
|
||||||
|
cls.demos_pending = true;
|
||||||
if( !SV_Active() && !cls.demoplayback )
|
|
||||||
{
|
|
||||||
// run demos loop in background mode
|
|
||||||
Cvar_SetValue( "v_dark", 1.0f );
|
|
||||||
cls.demonum = 0;
|
|
||||||
CL_NextDemo ();
|
|
||||||
}
|
|
||||||
else cls.demonum = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -603,13 +603,13 @@ void CL_FlushEntityPacket( sizebuf_t *msg )
|
||||||
// read it all, but ignore it
|
// read it all, but ignore it
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
newnum = MSG_ReadUBitLong( msg, MAX_VISIBLE_PACKET_BITS );
|
newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
|
||||||
if( newnum == LAST_EDICT ) break; // done
|
if( newnum == LAST_EDICT ) break; // done
|
||||||
|
|
||||||
if( MSG_CheckOverflow( msg ))
|
if( MSG_CheckOverflow( msg ))
|
||||||
Host_Error( "CL_FlushEntityPacket: overflow\n" );
|
Host_Error( "CL_FlushEntityPacket: overflow\n" );
|
||||||
|
|
||||||
MSG_ReadDeltaEntity( msg, &from, &to, newnum, CL_IsPlayerIndex( newnum ), cl.mtime[0] );
|
MSG_ReadDeltaEntity( msg, &from, &to, newnum, CL_IsPlayerIndex( newnum ) ? DELTA_PLAYER : DELTA_ENTITY, cl.mtime[0] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -626,17 +626,18 @@ void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_state_t
|
||||||
entity_state_t *state;
|
entity_state_t *state;
|
||||||
qboolean newent = (old) ? false : true;
|
qboolean newent = (old) ? false : true;
|
||||||
int pack = frame->num_entities;
|
int pack = frame->num_entities;
|
||||||
qboolean player = CL_IsPlayerIndex( newnum );
|
int delta_type = DELTA_ENTITY;
|
||||||
qboolean alive = true;
|
qboolean alive = true;
|
||||||
|
|
||||||
// alloc next slot to store update
|
// alloc next slot to store update
|
||||||
state = &cls.packet_entities[cls.next_client_entities % cls.num_client_entities];
|
state = &cls.packet_entities[cls.next_client_entities % cls.num_client_entities];
|
||||||
|
if( CL_IsPlayerIndex( newnum )) delta_type = DELTA_PLAYER;
|
||||||
|
|
||||||
if(( newnum < 0 ) || ( newnum >= clgame.maxEntities ))
|
if(( newnum < 0 ) || ( newnum >= clgame.maxEntities ))
|
||||||
{
|
{
|
||||||
MsgDev( D_ERROR, "CL_DeltaEntity: invalid newnum: %d\n", newnum );
|
MsgDev( D_ERROR, "CL_DeltaEntity: invalid newnum: %d\n", newnum );
|
||||||
if( has_update )
|
if( has_update )
|
||||||
MSG_ReadDeltaEntity( msg, old, state, newnum, player, cl.mtime[0] );
|
MSG_ReadDeltaEntity( msg, old, state, newnum, delta_type, cl.mtime[0] );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,7 +646,7 @@ void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_state_t
|
||||||
if( newent ) old = &ent->baseline;
|
if( newent ) old = &ent->baseline;
|
||||||
|
|
||||||
if( has_update )
|
if( has_update )
|
||||||
alive = MSG_ReadDeltaEntity( msg, old, state, newnum, player, cl.mtime[0] );
|
alive = MSG_ReadDeltaEntity( msg, old, state, newnum, delta_type, cl.mtime[0] );
|
||||||
else memcpy( state, old, sizeof( entity_state_t ));
|
else memcpy( state, old, sizeof( entity_state_t ));
|
||||||
|
|
||||||
if( !alive )
|
if( !alive )
|
||||||
|
@ -1074,7 +1075,7 @@ void CL_LinkPacketEntities( frame_t *frame )
|
||||||
if( ent->curstate.rendermode == kRenderNormal )
|
if( ent->curstate.rendermode == kRenderNormal )
|
||||||
{
|
{
|
||||||
// auto 'solid' faces
|
// auto 'solid' faces
|
||||||
if( FBitSet( ent->model->flags, MODEL_TRANSPARENT ) && FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
if( FBitSet( ent->model->flags, MODEL_TRANSPARENT ) && CL_IsQuakeCompatible( ))
|
||||||
{
|
{
|
||||||
ent->curstate.rendermode = kRenderTransAlpha;
|
ent->curstate.rendermode = kRenderTransAlpha;
|
||||||
ent->curstate.renderamt = 255;
|
ent->curstate.renderamt = 255;
|
||||||
|
|
|
@ -146,6 +146,19 @@ qboolean CL_IsBackgroundMap( void )
|
||||||
return ( cl.background && !cls.demoplayback );
|
return ( cl.background && !cls.demoplayback );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qboolean CL_IsQuakeCompatible( void )
|
||||||
|
{
|
||||||
|
// feature set
|
||||||
|
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// quake demo playing
|
||||||
|
if( cls.demoplayback == DEMO_QUAKE1 )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
char *CL_Userinfo( void )
|
char *CL_Userinfo( void )
|
||||||
{
|
{
|
||||||
return cls.userinfo;
|
return cls.userinfo;
|
||||||
|
@ -242,14 +255,31 @@ static float CL_LerpPoint( void )
|
||||||
if( f == 0.0f || cls.timedemo )
|
if( f == 0.0f || cls.timedemo )
|
||||||
{
|
{
|
||||||
cl.time = cl.mtime[0];
|
cl.time = cl.mtime[0];
|
||||||
|
|
||||||
// g-cont. probably this is redundant
|
|
||||||
if( cls.demoplayback )
|
|
||||||
cl.oldtime = cl.mtime[0] - cl_clientframetime();
|
|
||||||
|
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( f > 0.1f )
|
||||||
|
{
|
||||||
|
// dropped packet, or start of demo
|
||||||
|
cl.mtime[1] = cl.mtime[0] - 0.1f;
|
||||||
|
f = 0.1f;
|
||||||
|
}
|
||||||
|
#if 1
|
||||||
|
frac = (cl.time - cl.mtime[1]) / f;
|
||||||
|
|
||||||
|
if( frac < 0.0f )
|
||||||
|
{
|
||||||
|
if( frac < -0.01 )
|
||||||
|
cl.time = cl.mtime[1];
|
||||||
|
frac = 0.0f;
|
||||||
|
}
|
||||||
|
else if( frac > 1.0f )
|
||||||
|
{
|
||||||
|
if( frac > 1.01 )
|
||||||
|
cl.time = cl.mtime[0];
|
||||||
|
frac = 1.0f;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if( cl_interp->value > 0.001f )
|
if( cl_interp->value > 0.001f )
|
||||||
{
|
{
|
||||||
// manual lerp value (goldsrc mode)
|
// manual lerp value (goldsrc mode)
|
||||||
|
@ -260,7 +290,7 @@ static float CL_LerpPoint( void )
|
||||||
// automatic lerp (classic mode)
|
// automatic lerp (classic mode)
|
||||||
frac = ( cl.time - cl.mtime[1] ) / f;
|
frac = ( cl.time - cl.mtime[1] ) / f;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return frac;
|
return frac;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2001,7 +2031,10 @@ void CL_ReadNetMessage( void )
|
||||||
if( !cls.demoplayback && !Netchan_Process( &cls.netchan, &net_message ))
|
if( !cls.demoplayback && !Netchan_Process( &cls.netchan, &net_message ))
|
||||||
continue; // wasn't accepted for some reason
|
continue; // wasn't accepted for some reason
|
||||||
|
|
||||||
CL_ParseServerMessage( &net_message, true );
|
// run special handler for quake demos
|
||||||
|
if( cls.demoplayback == DEMO_QUAKE1 )
|
||||||
|
CL_ParseQuakeMessage( &net_message, true );
|
||||||
|
else CL_ParseServerMessage( &net_message, true );
|
||||||
cl.send_reply = true;
|
cl.send_reply = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2044,7 +2077,7 @@ void CL_ReadPackets( void )
|
||||||
// decide the simulation time
|
// decide the simulation time
|
||||||
cl.oldtime = cl.time;
|
cl.oldtime = cl.time;
|
||||||
|
|
||||||
if( !cls.demoplayback && !cl.paused )
|
if( cls.demoplayback != DEMO_XASH3D && !cl.paused )
|
||||||
cl.time += host.frametime;
|
cl.time += host.frametime;
|
||||||
|
|
||||||
// demo time
|
// demo time
|
||||||
|
|
|
@ -23,200 +23,8 @@ GNU General Public License for more details.
|
||||||
#include "hltv.h"
|
#include "hltv.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
|
||||||
#define MSG_COUNT 32 // last 32 messages parsed
|
|
||||||
#define MSG_MASK (MSG_COUNT - 1)
|
|
||||||
|
|
||||||
int CL_UPDATE_BACKUP = SINGLEPLAYER_BACKUP;
|
int CL_UPDATE_BACKUP = SINGLEPLAYER_BACKUP;
|
||||||
|
|
||||||
const char *svc_strings[svc_lastmsg+1] =
|
|
||||||
{
|
|
||||||
"svc_bad",
|
|
||||||
"svc_nop",
|
|
||||||
"svc_disconnect",
|
|
||||||
"svc_event",
|
|
||||||
"svc_changing",
|
|
||||||
"svc_setview",
|
|
||||||
"svc_sound",
|
|
||||||
"svc_time",
|
|
||||||
"svc_print",
|
|
||||||
"svc_stufftext",
|
|
||||||
"svc_setangle",
|
|
||||||
"svc_serverdata",
|
|
||||||
"svc_lightstyle",
|
|
||||||
"svc_updateuserinfo",
|
|
||||||
"svc_deltatable",
|
|
||||||
"svc_clientdata",
|
|
||||||
"svc_resource",
|
|
||||||
"svc_pings",
|
|
||||||
"svc_particle",
|
|
||||||
"svc_restoresound",
|
|
||||||
"svc_spawnstatic",
|
|
||||||
"svc_event_reliable",
|
|
||||||
"svc_spawnbaseline",
|
|
||||||
"svc_temp_entity",
|
|
||||||
"svc_setpause",
|
|
||||||
"svc_signonnum",
|
|
||||||
"svc_centerprint",
|
|
||||||
"svc_unused27",
|
|
||||||
"svc_unused28",
|
|
||||||
"svc_unused29",
|
|
||||||
"svc_intermission",
|
|
||||||
"svc_finale",
|
|
||||||
"svc_cdtrack",
|
|
||||||
"svc_restore",
|
|
||||||
"svc_cutscene",
|
|
||||||
"svc_weaponanim",
|
|
||||||
"svc_bspdecal",
|
|
||||||
"svc_roomtype",
|
|
||||||
"svc_addangle",
|
|
||||||
"svc_usermessage",
|
|
||||||
"svc_packetentities",
|
|
||||||
"svc_deltapacketentities",
|
|
||||||
"svc_choke",
|
|
||||||
"svc_resourcelist",
|
|
||||||
"svc_deltamovevars",
|
|
||||||
"svc_resourcerequest",
|
|
||||||
"svc_customization",
|
|
||||||
"svc_crosshairangle",
|
|
||||||
"svc_soundfade",
|
|
||||||
"svc_filetxferfailed",
|
|
||||||
"svc_hltv",
|
|
||||||
"svc_director",
|
|
||||||
"svc_voiceinit",
|
|
||||||
"svc_voicedata",
|
|
||||||
"svc_unused54",
|
|
||||||
"svc_unused55",
|
|
||||||
"svc_resourcelocation",
|
|
||||||
"svc_querycvarvalue",
|
|
||||||
"svc_querycvarvalue2",
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int command;
|
|
||||||
int starting_offset;
|
|
||||||
int frame_number;
|
|
||||||
} oldcmd_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
oldcmd_t oldcmd[MSG_COUNT];
|
|
||||||
int currentcmd;
|
|
||||||
qboolean parsing;
|
|
||||||
} msg_debug_t;
|
|
||||||
|
|
||||||
static msg_debug_t cls_message_debug;
|
|
||||||
static int starting_count;
|
|
||||||
|
|
||||||
const char *CL_MsgInfo( int cmd )
|
|
||||||
{
|
|
||||||
static string sz;
|
|
||||||
|
|
||||||
Q_strcpy( sz, "???" );
|
|
||||||
|
|
||||||
if( cmd >= 0 && cmd <= svc_lastmsg )
|
|
||||||
{
|
|
||||||
// get engine message name
|
|
||||||
Q_strncpy( sz, svc_strings[cmd], sizeof( sz ));
|
|
||||||
}
|
|
||||||
else if( cmd > svc_lastmsg && cmd <= ( svc_lastmsg + MAX_USER_MESSAGES ))
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for( i = 0; i < MAX_USER_MESSAGES; i++ )
|
|
||||||
{
|
|
||||||
if( clgame.msg[i].number == cmd )
|
|
||||||
{
|
|
||||||
Q_strncpy( sz, clgame.msg[i].name, sizeof( sz ));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=====================
|
|
||||||
CL_Parse_RecordCommand
|
|
||||||
|
|
||||||
record new message params into debug buffer
|
|
||||||
=====================
|
|
||||||
*/
|
|
||||||
void CL_Parse_RecordCommand( int cmd, int startoffset )
|
|
||||||
{
|
|
||||||
int slot;
|
|
||||||
|
|
||||||
if( cmd == svc_nop ) return;
|
|
||||||
|
|
||||||
slot = ( cls_message_debug.currentcmd++ & MSG_MASK );
|
|
||||||
cls_message_debug.oldcmd[slot].command = cmd;
|
|
||||||
cls_message_debug.oldcmd[slot].starting_offset = startoffset;
|
|
||||||
cls_message_debug.oldcmd[slot].frame_number = host.framecount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=====================
|
|
||||||
CL_WriteErrorMessage
|
|
||||||
|
|
||||||
write net_message into buffer.dat for debugging
|
|
||||||
=====================
|
|
||||||
*/
|
|
||||||
void CL_WriteErrorMessage( int current_count, sizebuf_t *msg )
|
|
||||||
{
|
|
||||||
const char *buffer_file = "buffer.dat";
|
|
||||||
file_t *fp;
|
|
||||||
|
|
||||||
fp = FS_Open( buffer_file, "wb", false );
|
|
||||||
if( !fp ) return;
|
|
||||||
|
|
||||||
FS_Write( fp, &starting_count, sizeof( int ));
|
|
||||||
FS_Write( fp, ¤t_count, sizeof( int ));
|
|
||||||
FS_Write( fp, MSG_GetData( msg ), MSG_GetMaxBytes( msg ));
|
|
||||||
FS_Close( fp );
|
|
||||||
|
|
||||||
Con_Printf( "Wrote erroneous message to %s\n", buffer_file );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=====================
|
|
||||||
CL_WriteMessageHistory
|
|
||||||
|
|
||||||
list last 32 messages for debugging net troubleshooting
|
|
||||||
=====================
|
|
||||||
*/
|
|
||||||
void CL_WriteMessageHistory( void )
|
|
||||||
{
|
|
||||||
oldcmd_t *old, *failcommand;
|
|
||||||
sizebuf_t *msg = &net_message;
|
|
||||||
int i, thecmd;
|
|
||||||
|
|
||||||
if( !cls.initialized || cls.state == ca_disconnected )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( !cls_message_debug.parsing )
|
|
||||||
return;
|
|
||||||
|
|
||||||
Con_Printf( "Last %i messages parsed.\n", MSG_COUNT );
|
|
||||||
|
|
||||||
// finish here
|
|
||||||
thecmd = cls_message_debug.currentcmd - 1;
|
|
||||||
thecmd -= ( MSG_COUNT - 1 ); // back up to here
|
|
||||||
|
|
||||||
for( i = 0; i < MSG_COUNT - 1; i++ )
|
|
||||||
{
|
|
||||||
thecmd &= MSG_MASK;
|
|
||||||
old = &cls_message_debug.oldcmd[thecmd];
|
|
||||||
Con_Printf( "%i %04i %s\n", old->frame_number, old->starting_offset, CL_MsgInfo( old->command ));
|
|
||||||
thecmd++;
|
|
||||||
}
|
|
||||||
|
|
||||||
failcommand = &cls_message_debug.oldcmd[thecmd];
|
|
||||||
Con_Printf( "BAD: %3i:%s\n", MSG_GetNumBytesRead( msg ) - 1, CL_MsgInfo( failcommand->command ));
|
|
||||||
if( host_developer.value >= DEV_EXTENDED )
|
|
||||||
CL_WriteErrorMessage( MSG_GetNumBytesRead( msg ) - 1, msg );
|
|
||||||
cls_message_debug.parsing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===============
|
===============
|
||||||
CL_UserMsgStub
|
CL_UserMsgStub
|
||||||
|
@ -387,6 +195,9 @@ void CL_ParseServerTime( sizebuf_t *msg )
|
||||||
cl.mtime[1] = cl.mtime[0];
|
cl.mtime[1] = cl.mtime[0];
|
||||||
cl.mtime[0] = MSG_ReadFloat( msg );
|
cl.mtime[0] = MSG_ReadFloat( msg );
|
||||||
|
|
||||||
|
if( cls.demoplayback == DEMO_QUAKE1 )
|
||||||
|
return; // don't mess the time
|
||||||
|
|
||||||
if( cl.maxclients == 1 )
|
if( cl.maxclients == 1 )
|
||||||
cl.time = cl.mtime[0];
|
cl.time = cl.mtime[0];
|
||||||
|
|
||||||
|
@ -502,46 +313,27 @@ static client entity
|
||||||
*/
|
*/
|
||||||
void CL_ParseStaticEntity( sizebuf_t *msg )
|
void CL_ParseStaticEntity( sizebuf_t *msg )
|
||||||
{
|
{
|
||||||
entity_state_t state;
|
int i, newnum;
|
||||||
|
entity_state_t from, to;
|
||||||
cl_entity_t *ent;
|
cl_entity_t *ent;
|
||||||
int i;
|
|
||||||
|
|
||||||
memset( &state, 0, sizeof( state ));
|
memset( &from, 0, sizeof( from ));
|
||||||
|
newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
|
||||||
state.modelindex = MSG_ReadShort( msg );
|
MSG_ReadDeltaEntity( msg, &from, &to, 0, DELTA_STATIC, cl.mtime[0] );
|
||||||
state.sequence = MSG_ReadWord( msg );
|
|
||||||
state.frame = MSG_ReadWord( msg ) * (1.0f / 128.0f);
|
|
||||||
state.colormap = MSG_ReadWord( msg );
|
|
||||||
state.skin = MSG_ReadByte( msg );
|
|
||||||
state.body = MSG_ReadByte( msg );
|
|
||||||
state.scale = MSG_ReadCoord( msg );
|
|
||||||
MSG_ReadVec3Coord( msg, state.origin );
|
|
||||||
MSG_ReadVec3Angles( msg, state.angles );
|
|
||||||
state.rendermode = MSG_ReadByte( msg );
|
|
||||||
|
|
||||||
if( state.rendermode != kRenderNormal )
|
|
||||||
{
|
|
||||||
state.renderamt = MSG_ReadByte( msg );
|
|
||||||
state.rendercolor.r = MSG_ReadByte( msg );
|
|
||||||
state.rendercolor.g = MSG_ReadByte( msg );
|
|
||||||
state.rendercolor.b = MSG_ReadByte( msg );
|
|
||||||
state.renderfx = MSG_ReadByte( msg );
|
|
||||||
}
|
|
||||||
|
|
||||||
i = clgame.numStatics;
|
i = clgame.numStatics;
|
||||||
if( i >= MAX_STATIC_ENTITIES )
|
if( i >= MAX_STATIC_ENTITIES )
|
||||||
{
|
{
|
||||||
MsgDev( D_ERROR, "CL_ParseStaticEntity: static entities limit exceeded!\n" );
|
Con_Printf( S_ERROR, "MAX_STATIC_ENTITIES limit exceeded!\n" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ent = &clgame.static_entities[i];
|
ent = &clgame.static_entities[i];
|
||||||
clgame.numStatics++;
|
clgame.numStatics++;
|
||||||
|
|
||||||
ent->index = 0; // ???
|
// all states are same
|
||||||
ent->baseline = state;
|
ent->baseline = ent->curstate = ent->prevstate = to;
|
||||||
ent->curstate = state;
|
ent->index = 0; // static entities doesn't has the numbers
|
||||||
ent->prevstate = state;
|
|
||||||
|
|
||||||
// statics may be respawned in game e.g. for demo recording
|
// statics may be respawned in game e.g. for demo recording
|
||||||
if( cls.state == ca_connected || cls.state == ca_validate )
|
if( cls.state == ca_connected || cls.state == ca_validate )
|
||||||
|
@ -550,14 +342,14 @@ void CL_ParseStaticEntity( sizebuf_t *msg )
|
||||||
// setup the new static entity
|
// setup the new static entity
|
||||||
VectorCopy( ent->curstate.origin, ent->origin );
|
VectorCopy( ent->curstate.origin, ent->origin );
|
||||||
VectorCopy( ent->curstate.angles, ent->angles );
|
VectorCopy( ent->curstate.angles, ent->angles );
|
||||||
ent->model = CL_ModelHandle( state.modelindex );
|
ent->model = CL_ModelHandle( to.modelindex );
|
||||||
ent->curstate.framerate = 1.0f;
|
ent->curstate.framerate = 1.0f;
|
||||||
CL_ResetLatchedVars( ent, true );
|
CL_ResetLatchedVars( ent, true );
|
||||||
|
|
||||||
if( ent->curstate.rendermode == kRenderNormal && ent->model != NULL )
|
if( ent->curstate.rendermode == kRenderNormal && ent->model != NULL )
|
||||||
{
|
{
|
||||||
// auto 'solid' faces
|
// auto 'solid' faces
|
||||||
if( FBitSet( ent->model->flags, MODEL_TRANSPARENT ) && FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
if( FBitSet( ent->model->flags, MODEL_TRANSPARENT ) && CL_IsQuakeCompatible( ))
|
||||||
{
|
{
|
||||||
ent->curstate.rendermode = kRenderTransAlpha;
|
ent->curstate.rendermode = kRenderTransAlpha;
|
||||||
ent->curstate.renderamt = 255;
|
ent->curstate.renderamt = 255;
|
||||||
|
@ -2181,21 +1973,6 @@ void CL_ParseUserMessage( sizebuf_t *msg, int svc_num )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
=====================
|
|
||||||
CL_ResetFrame
|
|
||||||
=====================
|
|
||||||
*/
|
|
||||||
void CL_ResetFrame( frame_t *frame )
|
|
||||||
{
|
|
||||||
memset( &frame->graphdata, 0, sizeof( netbandwidthgraph_t ));
|
|
||||||
frame->receivedtime = host.realtime;
|
|
||||||
frame->valid = true;
|
|
||||||
frame->choked = false;
|
|
||||||
frame->latency = 0.0;
|
|
||||||
frame->time = cl.mtime[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=====================================================================
|
=====================================================================
|
||||||
|
|
||||||
|
@ -2216,8 +1993,8 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
|
||||||
int cmd, param1, param2;
|
int cmd, param1, param2;
|
||||||
int old_background;
|
int old_background;
|
||||||
|
|
||||||
cls_message_debug.parsing = true; // begin parsing
|
cls.starting_count = MSG_GetNumBytesRead( msg ); // updates each frame
|
||||||
starting_count = MSG_GetNumBytesRead( msg ); // updates each frame
|
CL_Parse_Debug( true ); // begin parsing
|
||||||
|
|
||||||
if( normal_message )
|
if( normal_message )
|
||||||
{
|
{
|
||||||
|
@ -2251,6 +2028,8 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
|
||||||
|
|
||||||
cmd = MSG_ReadServerCmd( msg );
|
cmd = MSG_ReadServerCmd( msg );
|
||||||
|
|
||||||
|
// Msg( "%s\n", CL_MsgInfo( cmd ));
|
||||||
|
|
||||||
// record command for debugging spew on parse problem
|
// record command for debugging spew on parse problem
|
||||||
CL_Parse_RecordCommand( cmd, bufStart );
|
CL_Parse_RecordCommand( cmd, bufStart );
|
||||||
|
|
||||||
|
@ -2278,7 +2057,7 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
|
||||||
cls.changelevel = true;
|
cls.changelevel = true;
|
||||||
S_StopAllSounds( true );
|
S_StopAllSounds( true );
|
||||||
|
|
||||||
MsgDev( D_INFO, "Server changing, reconnecting\n" );
|
Con_Printf( "Server changing, reconnecting\n" );
|
||||||
|
|
||||||
if( cls.demoplayback )
|
if( cls.demoplayback )
|
||||||
{
|
{
|
||||||
|
@ -2289,7 +2068,7 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
|
||||||
CL_ClearState ();
|
CL_ClearState ();
|
||||||
CL_InitEdicts (); // re-arrange edicts
|
CL_InitEdicts (); // re-arrange edicts
|
||||||
}
|
}
|
||||||
else MsgDev( D_INFO, "Server disconnected, reconnecting\n" );
|
else Con_Printf( "Server disconnected, reconnecting\n" );
|
||||||
|
|
||||||
if( cls.demoplayback )
|
if( cls.demoplayback )
|
||||||
{
|
{
|
||||||
|
@ -2299,7 +2078,8 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// g-cont. local client skip the challenge
|
// g-cont. local client skip the challenge
|
||||||
if( SV_Active()) cls.state = ca_disconnected;
|
if( SV_Active( ))
|
||||||
|
cls.state = ca_disconnected;
|
||||||
else cls.state = ca_connecting;
|
else cls.state = ca_connecting;
|
||||||
cl.background = old_background;
|
cl.background = old_background;
|
||||||
cls.connect_time = MAX_HEARTBEAT;
|
cls.connect_time = MAX_HEARTBEAT;
|
||||||
|
@ -2477,8 +2257,8 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cl.frames[cl.parsecountmod].graphdata.msgbytes += MSG_GetNumBytesRead( msg ) - starting_count;
|
cl.frames[cl.parsecountmod].graphdata.msgbytes += MSG_GetNumBytesRead( msg ) - cls.starting_count;
|
||||||
cls_message_debug.parsing = false; // done
|
CL_Parse_Debug( false ); // done
|
||||||
|
|
||||||
// we don't know if it is ok to save a demo message until
|
// we don't know if it is ok to save a demo message until
|
||||||
// after we have parsed the frame
|
// after we have parsed the frame
|
||||||
|
@ -2486,11 +2266,11 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
|
||||||
{
|
{
|
||||||
if( cls.demorecording && !cls.demowaiting )
|
if( cls.demorecording && !cls.demowaiting )
|
||||||
{
|
{
|
||||||
CL_WriteDemoMessage( false, starting_count, msg );
|
CL_WriteDemoMessage( false, cls.starting_count, msg );
|
||||||
}
|
}
|
||||||
else if( cls.state != ca_active )
|
else if( cls.state != ca_active )
|
||||||
{
|
{
|
||||||
CL_WriteDemoMessage( true, starting_count, msg );
|
CL_WriteDemoMessage( true, cls.starting_count, msg );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -115,6 +115,10 @@ qboolean CL_IsPredicted( void )
|
||||||
{
|
{
|
||||||
if( cl_nopred->value || cl.intermission )
|
if( cl_nopred->value || cl.intermission )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// never predict the quake demos
|
||||||
|
if( cls.demoplayback == DEMO_QUAKE1 )
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1007
engine/client/cl_qparse.c
Normal file
1007
engine/client/cl_qparse.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -721,6 +721,7 @@ void SCR_Init( void )
|
||||||
// register our commands
|
// register our commands
|
||||||
Cmd_AddCommand( "timerefresh", SCR_TimeRefresh_f, "turn quickly and print rendering statistcs" );
|
Cmd_AddCommand( "timerefresh", SCR_TimeRefresh_f, "turn quickly and print rendering statistcs" );
|
||||||
Cmd_AddCommand( "skyname", CL_SetSky_f, "set new skybox by basename" );
|
Cmd_AddCommand( "skyname", CL_SetSky_f, "set new skybox by basename" );
|
||||||
|
Cmd_AddCommand( "loadsky", CL_SetSky_f, "set new skybox by basename" );
|
||||||
Cmd_AddCommand( "viewpos", SCR_Viewpos_f, "prints current player origin" );
|
Cmd_AddCommand( "viewpos", SCR_Viewpos_f, "prints current player origin" );
|
||||||
Cmd_AddCommand( "sizeup", SCR_SizeUp_f, "screen size up to 10 points" );
|
Cmd_AddCommand( "sizeup", SCR_SizeUp_f, "screen size up to 10 points" );
|
||||||
Cmd_AddCommand( "sizedown", SCR_SizeDown_f, "screen size down to 10 points" );
|
Cmd_AddCommand( "sizedown", SCR_SizeDown_f, "screen size down to 10 points" );
|
||||||
|
|
|
@ -151,7 +151,7 @@ void CL_AddClientResources( void )
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// don't request resources from localhost or in quake-compatibility mode
|
// don't request resources from localhost or in quake-compatibility mode
|
||||||
if( cl.maxclients <= 1 || FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
if( cl.maxclients <= 1 || CL_IsQuakeCompatible( ))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// check sprites first
|
// check sprites first
|
||||||
|
@ -2808,7 +2808,7 @@ void CL_AddEntityEffects( cl_entity_t *ent )
|
||||||
|
|
||||||
if( FBitSet( ent->curstate.effects, EF_DIMLIGHT ))
|
if( FBitSet( ent->curstate.effects, EF_DIMLIGHT ))
|
||||||
{
|
{
|
||||||
if( ent->player && !FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
if( ent->player && !CL_IsQuakeCompatible( ))
|
||||||
{
|
{
|
||||||
CL_UpdateFlashlight( ent );
|
CL_UpdateFlashlight( ent );
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ qboolean SCR_NextMovie( void )
|
||||||
{
|
{
|
||||||
S_StopAllSounds( true );
|
S_StopAllSounds( true );
|
||||||
SCR_StopCinematic();
|
SCR_StopCinematic();
|
||||||
|
CL_CheckStartupDemos();
|
||||||
return false; // don't play movies
|
return false; // don't play movies
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +57,7 @@ qboolean SCR_NextMovie( void )
|
||||||
S_StopAllSounds( true );
|
S_StopAllSounds( true );
|
||||||
SCR_StopCinematic();
|
SCR_StopCinematic();
|
||||||
cls.movienum = -1;
|
cls.movienum = -1;
|
||||||
|
CL_CheckStartupDemos();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,6 +92,7 @@ void SCR_CheckStartupVids( void )
|
||||||
{
|
{
|
||||||
// don't run movies where we in developer-mode
|
// don't run movies where we in developer-mode
|
||||||
cls.movienum = -1;
|
cls.movienum = -1;
|
||||||
|
CL_CheckStartupDemos();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,13 @@ GNU General Public License for more details.
|
||||||
|
|
||||||
typedef int sound_t;
|
typedef int sound_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DEMO_INACTIVE = 0,
|
||||||
|
DEMO_XASH3D,
|
||||||
|
DEMO_QUAKE1
|
||||||
|
} demo_mode;
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
typedef struct netbandwithgraph_s
|
typedef struct netbandwithgraph_s
|
||||||
{
|
{
|
||||||
|
@ -593,6 +600,7 @@ typedef struct
|
||||||
|
|
||||||
float packet_loss;
|
float packet_loss;
|
||||||
double packet_loss_recalc_time;
|
double packet_loss_recalc_time;
|
||||||
|
int starting_count; // message num readed bits
|
||||||
|
|
||||||
float nextcmdtime; // when can we send the next command packet?
|
float nextcmdtime; // when can we send the next command packet?
|
||||||
int lastoutgoingcommand; // sequence number of last outgoing command
|
int lastoutgoingcommand; // sequence number of last outgoing command
|
||||||
|
@ -601,6 +609,7 @@ typedef struct
|
||||||
int td_lastframe; // to meter out one message a frame
|
int td_lastframe; // to meter out one message a frame
|
||||||
int td_startframe; // host_framecount at start
|
int td_startframe; // host_framecount at start
|
||||||
double td_starttime; // realtime at second frame of timedemo
|
double td_starttime; // realtime at second frame of timedemo
|
||||||
|
int forcetrack; // -1 = use normal cd track
|
||||||
|
|
||||||
// game images
|
// game images
|
||||||
int pauseIcon; // draw 'paused' when game in-pause
|
int pauseIcon; // draw 'paused' when game in-pause
|
||||||
|
@ -630,7 +639,8 @@ typedef struct
|
||||||
// demo loop control
|
// demo loop control
|
||||||
int demonum; // -1 = don't play demos
|
int demonum; // -1 = don't play demos
|
||||||
int olddemonum; // restore playing
|
int olddemonum; // restore playing
|
||||||
string demos[MAX_DEMOS]; // when not playing
|
char demos[MAX_DEMOS][MAX_QPATH]; // when not playing
|
||||||
|
qboolean demos_pending;
|
||||||
|
|
||||||
// movie playlist
|
// movie playlist
|
||||||
int movienum;
|
int movienum;
|
||||||
|
@ -738,6 +748,15 @@ void CL_RemoveFromResourceList( resource_t *pResource );
|
||||||
void CL_MoveToOnHandList( resource_t *pResource );
|
void CL_MoveToOnHandList( resource_t *pResource );
|
||||||
void CL_ClearResourceLists( void );
|
void CL_ClearResourceLists( void );
|
||||||
|
|
||||||
|
//
|
||||||
|
// cl_debug.c
|
||||||
|
//
|
||||||
|
void CL_Parse_Debug( qboolean enable );
|
||||||
|
void CL_Parse_RecordCommand( int cmd, int startoffset );
|
||||||
|
void CL_ResetFrame( frame_t *frame );
|
||||||
|
void CL_WriteMessageHistory( void );
|
||||||
|
const char *CL_MsgInfo( int cmd );
|
||||||
|
|
||||||
//
|
//
|
||||||
// cl_main.c
|
// cl_main.c
|
||||||
//
|
//
|
||||||
|
@ -765,8 +784,10 @@ void CL_WriteDemoMessage( qboolean startup, int start, sizebuf_t *msg );
|
||||||
void CL_WriteDemoUserMessage( const byte *buffer, size_t size );
|
void CL_WriteDemoUserMessage( const byte *buffer, size_t size );
|
||||||
qboolean CL_DemoReadMessage( byte *buffer, size_t *length );
|
qboolean CL_DemoReadMessage( byte *buffer, size_t *length );
|
||||||
void CL_DemoInterpolateAngles( void );
|
void CL_DemoInterpolateAngles( void );
|
||||||
|
void CL_CheckStartupDemos( void );
|
||||||
void CL_WriteDemoJumpTime( void );
|
void CL_WriteDemoJumpTime( void );
|
||||||
void CL_CloseDemoHeader( void );
|
void CL_CloseDemoHeader( void );
|
||||||
|
void CL_DemoCompleted( void );
|
||||||
void CL_StopPlayback( void );
|
void CL_StopPlayback( void );
|
||||||
void CL_StopRecord( void );
|
void CL_StopRecord( void );
|
||||||
void CL_PlayDemo_f( void );
|
void CL_PlayDemo_f( void );
|
||||||
|
@ -776,7 +797,6 @@ void CL_Demos_f( void );
|
||||||
void CL_DeleteDemo_f( void );
|
void CL_DeleteDemo_f( void );
|
||||||
void CL_Record_f( void );
|
void CL_Record_f( void );
|
||||||
void CL_Stop_f( void );
|
void CL_Stop_f( void );
|
||||||
void CL_FreeDemo( void );
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// cl_events.c
|
// cl_events.c
|
||||||
|
@ -847,6 +867,8 @@ void CL_StartResourceDownloading( const char *pszMessage, qboolean bCustom );
|
||||||
qboolean CL_DispatchUserMessage( const char *pszName, int iSize, void *pbuf );
|
qboolean CL_DispatchUserMessage( const char *pszName, int iSize, void *pbuf );
|
||||||
qboolean CL_RequestMissingResources( void );
|
qboolean CL_RequestMissingResources( void );
|
||||||
void CL_RegisterResources ( sizebuf_t *msg );
|
void CL_RegisterResources ( sizebuf_t *msg );
|
||||||
|
void CL_ParseViewEntity( sizebuf_t *msg );
|
||||||
|
void CL_ParseServerTime( sizebuf_t *msg );
|
||||||
|
|
||||||
//
|
//
|
||||||
// cl_scrn.c
|
// cl_scrn.c
|
||||||
|
@ -908,6 +930,11 @@ void CL_PushPMStates( void );
|
||||||
void CL_PopPMStates( void );
|
void CL_PopPMStates( void );
|
||||||
void CL_SetUpPlayerPrediction( int dopred, int bIncludeLocalClient );
|
void CL_SetUpPlayerPrediction( int dopred, int bIncludeLocalClient );
|
||||||
|
|
||||||
|
//
|
||||||
|
// cl_qparse.c
|
||||||
|
//
|
||||||
|
void CL_ParseQuakeMessage( sizebuf_t *msg, qboolean normal_message );
|
||||||
|
|
||||||
//
|
//
|
||||||
// cl_studio.c
|
// cl_studio.c
|
||||||
//
|
//
|
||||||
|
@ -922,7 +949,7 @@ void CL_ResetLatchedVars( cl_entity_t *ent, qboolean full_reset );
|
||||||
qboolean CL_GetEntitySpatialization( struct channel_s *ch );
|
qboolean CL_GetEntitySpatialization( struct channel_s *ch );
|
||||||
qboolean CL_GetMovieSpatialization( struct rawchan_s *ch );
|
qboolean CL_GetMovieSpatialization( struct rawchan_s *ch );
|
||||||
void CL_ComputePlayerOrigin( cl_entity_t *clent );
|
void CL_ComputePlayerOrigin( cl_entity_t *clent );
|
||||||
void CL_UpdateEntityFields( cl_entity_t *ent );
|
void CL_ProcessPacket( frame_t *frame );
|
||||||
void CL_MoveThirdpersonCamera( void );
|
void CL_MoveThirdpersonCamera( void );
|
||||||
qboolean CL_IsPlayerIndex( int idx );
|
qboolean CL_IsPlayerIndex( int idx );
|
||||||
void CL_SetIdealPitch( void );
|
void CL_SetIdealPitch( void );
|
||||||
|
|
|
@ -43,6 +43,25 @@ qboolean R_SpeedsMessage( char *out, size_t size )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============
|
||||||
|
R_Speeds_Printf
|
||||||
|
|
||||||
|
helper to print into r_speeds message
|
||||||
|
==============
|
||||||
|
*/
|
||||||
|
void R_Speeds_Printf( const char *msg, ... )
|
||||||
|
{
|
||||||
|
va_list argptr;
|
||||||
|
char text[2048];
|
||||||
|
|
||||||
|
va_start( argptr, msg );
|
||||||
|
Q_vsprintf( text, msg, argptr );
|
||||||
|
va_end( argptr );
|
||||||
|
|
||||||
|
Q_strncat( r_speeds_msg, text, sizeof( r_speeds_msg ));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==============
|
==============
|
||||||
GL_BackendStartFrame
|
GL_BackendStartFrame
|
||||||
|
@ -60,9 +79,17 @@ GL_BackendEndFrame
|
||||||
*/
|
*/
|
||||||
void GL_BackendEndFrame( void )
|
void GL_BackendEndFrame( void )
|
||||||
{
|
{
|
||||||
|
mleaf_t *curleaf;
|
||||||
|
|
||||||
if( r_speeds->value <= 0 || !RI.drawWorld )
|
if( r_speeds->value <= 0 || !RI.drawWorld )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if( !RI.viewleaf )
|
||||||
|
curleaf = cl.worldmodel->leafs;
|
||||||
|
else curleaf = RI.viewleaf;
|
||||||
|
|
||||||
|
R_Speeds_Printf( "Renderer: ^1Engine^7\n\n" );
|
||||||
|
|
||||||
switch( (int)r_speeds->value )
|
switch( (int)r_speeds->value )
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -70,8 +97,8 @@ void GL_BackendEndFrame( void )
|
||||||
r_stats.c_world_polys, r_stats.c_alias_polys, r_stats.c_studio_polys, r_stats.c_sprite_polys );
|
r_stats.c_world_polys, r_stats.c_alias_polys, r_stats.c_studio_polys, r_stats.c_sprite_polys );
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "visible leafs:\n%3i leafs\ncurrent leaf %3i",
|
R_Speeds_Printf( "visible leafs:\n%3i leafs\ncurrent leaf %3i\n", r_stats.c_world_leafs, curleaf - cl.worldmodel->leafs );
|
||||||
r_stats.c_world_leafs, Mod_PointInLeaf( RI.pvsorigin, cl.worldmodel->nodes ) - cl.worldmodel->leafs );
|
R_Speeds_Printf( "ReciusiveWorldNode: %3lf secs\nDrawTextureChains %lf\n", r_stats.t_world_node, r_stats.t_world_draw );
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "%3i alias models drawn\n%3i studio models drawn\n%3i sprites drawn",
|
Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "%3i alias models drawn\n%3i studio models drawn\n%3i sprites drawn",
|
||||||
|
|
|
@ -883,7 +883,7 @@ byte *GL_ApplyFilter( const byte *source, int width, int height )
|
||||||
byte *out = (byte *)source;
|
byte *out = (byte *)source;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ) || glConfig.max_multisamples > 1 )
|
if( CL_IsQuakeCompatible() || glConfig.max_multisamples > 1 )
|
||||||
return in;
|
return in;
|
||||||
|
|
||||||
for( i = 0; source && i < width * height; i++, in += 4 )
|
for( i = 0; source && i < width * height; i++, in += 4 )
|
||||||
|
|
|
@ -229,6 +229,8 @@ typedef struct
|
||||||
uint c_particle_count;
|
uint c_particle_count;
|
||||||
|
|
||||||
uint c_client_ents; // entities that moved to client
|
uint c_client_ents; // entities that moved to client
|
||||||
|
double t_world_node;
|
||||||
|
double t_world_draw;
|
||||||
} ref_speeds_t;
|
} ref_speeds_t;
|
||||||
|
|
||||||
extern ref_speeds_t r_stats;
|
extern ref_speeds_t r_stats;
|
||||||
|
|
|
@ -81,7 +81,6 @@ R_SplitEntityOnNode
|
||||||
static void R_SplitEntityOnNode( mnode_t *node )
|
static void R_SplitEntityOnNode( mnode_t *node )
|
||||||
{
|
{
|
||||||
efrag_t *ef;
|
efrag_t *ef;
|
||||||
mplane_t *splitplane;
|
|
||||||
mleaf_t *leaf;
|
mleaf_t *leaf;
|
||||||
int sides;
|
int sides;
|
||||||
|
|
||||||
|
@ -100,7 +99,7 @@ static void R_SplitEntityOnNode( mnode_t *node )
|
||||||
ef = clgame.free_efrags;
|
ef = clgame.free_efrags;
|
||||||
if( !ef )
|
if( !ef )
|
||||||
{
|
{
|
||||||
MsgDev( D_ERROR, "too many efrags!\n" );
|
Con_Printf( S_ERROR "too many efrags!\n" );
|
||||||
return; // no free fragments...
|
return; // no free fragments...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,8 +119,7 @@ static void R_SplitEntityOnNode( mnode_t *node )
|
||||||
}
|
}
|
||||||
|
|
||||||
// NODE_MIXED
|
// NODE_MIXED
|
||||||
splitplane = node->plane;
|
sides = BOX_ON_PLANE_SIDE( r_emins, r_emaxs, node->plane );
|
||||||
sides = BOX_ON_PLANE_SIDE( r_emins, r_emaxs, splitplane );
|
|
||||||
|
|
||||||
if( sides == 3 )
|
if( sides == 3 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -658,7 +658,7 @@ static void R_CheckFog( void )
|
||||||
int i, cnt, count;
|
int i, cnt, count;
|
||||||
|
|
||||||
// quake global fog
|
// quake global fog
|
||||||
if( clgame.movevars.fog_settings != 0 && FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
if( clgame.movevars.fog_settings != 0 && CL_IsQuakeCompatible( ))
|
||||||
{
|
{
|
||||||
// quake-style global fog
|
// quake-style global fog
|
||||||
RI.fogColor[0] = ((clgame.movevars.fog_settings & 0xFF000000) >> 24) / 255.0f;
|
RI.fogColor[0] = ((clgame.movevars.fog_settings & 0xFF000000) >> 24) / 255.0f;
|
||||||
|
@ -1207,6 +1207,8 @@ static int GL_RenderGetParm( int parm, int arg )
|
||||||
return tr.lightmapTextures[arg];
|
return tr.lightmapTextures[arg];
|
||||||
case PARM_SKY_SPHERE:
|
case PARM_SKY_SPHERE:
|
||||||
return FBitSet( world.flags, FWORLD_SKYSPHERE ) && !FBitSet( world.flags, FWORLD_CUSTOM_SKYBOX );
|
return FBitSet( world.flags, FWORLD_SKYSPHERE ) && !FBitSet( world.flags, FWORLD_CUSTOM_SKYBOX );
|
||||||
|
case PARAM_GAMEPAUSED:
|
||||||
|
return cl.paused;
|
||||||
case PARM_WIDESCREEN:
|
case PARM_WIDESCREEN:
|
||||||
return glState.wideScreen;
|
return glState.wideScreen;
|
||||||
case PARM_FULLSCREEN:
|
case PARM_FULLSCREEN:
|
||||||
|
|
|
@ -465,9 +465,12 @@ void R_NewMap( void )
|
||||||
if( v_dark->value )
|
if( v_dark->value )
|
||||||
{
|
{
|
||||||
screenfade_t *sf = &clgame.fade;
|
screenfade_t *sf = &clgame.fade;
|
||||||
|
float fadetime = 5.0f;
|
||||||
client_textmessage_t *title;
|
client_textmessage_t *title;
|
||||||
|
|
||||||
title = CL_TextMessageGet( "GAMETITLE" );
|
title = CL_TextMessageGet( "GAMETITLE" );
|
||||||
|
if( CL_IsQuakeCompatible( ))
|
||||||
|
fadetime = 1.0f;
|
||||||
|
|
||||||
if( title )
|
if( title )
|
||||||
{
|
{
|
||||||
|
@ -475,7 +478,7 @@ void R_NewMap( void )
|
||||||
sf->fadeEnd = title->holdtime + title->fadeout;
|
sf->fadeEnd = title->holdtime + title->fadeout;
|
||||||
sf->fadeReset = title->fadeout;
|
sf->fadeReset = title->fadeout;
|
||||||
}
|
}
|
||||||
else sf->fadeEnd = sf->fadeReset = 5.0f;
|
else sf->fadeEnd = sf->fadeReset = fadetime;
|
||||||
|
|
||||||
sf->fadeFlags = FFADE_IN;
|
sf->fadeFlags = FFADE_IN;
|
||||||
sf->fader = sf->fadeg = sf->fadeb = 0;
|
sf->fader = sf->fadeg = sf->fadeb = 0;
|
||||||
|
|
|
@ -1232,7 +1232,7 @@ void R_DrawTextureChains( void )
|
||||||
if(( s->flags & SURF_DRAWTURB ) && clgame.movevars.wateralpha < 1.0f )
|
if(( s->flags & SURF_DRAWTURB ) && clgame.movevars.wateralpha < 1.0f )
|
||||||
continue; // draw translucent water later
|
continue; // draw translucent water later
|
||||||
|
|
||||||
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ) && FBitSet( s->flags, SURF_TRANSPARENT ))
|
if( CL_IsQuakeCompatible() && FBitSet( s->flags, SURF_TRANSPARENT ))
|
||||||
{
|
{
|
||||||
draw_alpha_surfaces = true;
|
draw_alpha_surfaces = true;
|
||||||
continue; // draw transparent surfaces later
|
continue; // draw transparent surfaces later
|
||||||
|
@ -1412,7 +1412,7 @@ void R_SetRenderMode( cl_entity_t *e )
|
||||||
case kRenderTransAlpha:
|
case kRenderTransAlpha:
|
||||||
pglEnable( GL_ALPHA_TEST );
|
pglEnable( GL_ALPHA_TEST );
|
||||||
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||||
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
if( CL_IsQuakeCompatible( ))
|
||||||
{
|
{
|
||||||
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||||
pglColor4f( 1.0f, 1.0f, 1.0f, tr.blend );
|
pglColor4f( 1.0f, 1.0f, 1.0f, tr.blend );
|
||||||
|
@ -1482,7 +1482,7 @@ void R_DrawBrushModel( cl_entity_t *e )
|
||||||
if( rotated ) R_RotateForEntity( e );
|
if( rotated ) R_RotateForEntity( e );
|
||||||
else R_TranslateForEntity( e );
|
else R_TranslateForEntity( e );
|
||||||
|
|
||||||
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ) && FBitSet( clmodel->flags, MODEL_TRANSPARENT ))
|
if( CL_IsQuakeCompatible() && FBitSet( clmodel->flags, MODEL_TRANSPARENT ))
|
||||||
e->curstate.rendermode = kRenderTransAlpha;
|
e->curstate.rendermode = kRenderTransAlpha;
|
||||||
|
|
||||||
e->visframe = tr.realframecount; // visible
|
e->visframe = tr.realframecount; // visible
|
||||||
|
@ -1515,7 +1515,7 @@ void R_DrawBrushModel( cl_entity_t *e )
|
||||||
|
|
||||||
for( i = 0; i < clmodel->nummodelsurfaces; i++, psurf++ )
|
for( i = 0; i < clmodel->nummodelsurfaces; i++, psurf++ )
|
||||||
{
|
{
|
||||||
if( FBitSet( psurf->flags, SURF_DRAWTURB ) && !FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
if( FBitSet( psurf->flags, SURF_DRAWTURB ) && !CL_IsQuakeCompatible( ))
|
||||||
{
|
{
|
||||||
if( psurf->plane->type != PLANE_Z && !FBitSet( e->curstate.effects, EF_WATERSIDES ))
|
if( psurf->plane->type != PLANE_Z && !FBitSet( e->curstate.effects, EF_WATERSIDES ))
|
||||||
continue;
|
continue;
|
||||||
|
@ -1591,14 +1591,14 @@ void R_RecursiveWorldNode( mnode_t *node, uint clipflags )
|
||||||
mleaf_t *pleaf;
|
mleaf_t *pleaf;
|
||||||
int c, side;
|
int c, side;
|
||||||
float dot;
|
float dot;
|
||||||
|
loc0:
|
||||||
if( node->contents == CONTENTS_SOLID )
|
if( node->contents == CONTENTS_SOLID )
|
||||||
return; // hit a solid leaf
|
return; // hit a solid leaf
|
||||||
|
|
||||||
if( node->visframe != tr.visframecount )
|
if( node->visframe != tr.visframecount )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( clipflags && !r_nocull->value )
|
if( clipflags && !CVAR_TO_BOOL( r_nocull ))
|
||||||
{
|
{
|
||||||
for( i = 0; i < 6; i++ )
|
for( i = 0; i < 6; i++ )
|
||||||
{
|
{
|
||||||
|
@ -1667,7 +1667,8 @@ void R_RecursiveWorldNode( mnode_t *node, uint clipflags )
|
||||||
}
|
}
|
||||||
|
|
||||||
// recurse down the back side
|
// recurse down the back side
|
||||||
R_RecursiveWorldNode( node->children[!side], clipflags );
|
node = node->children[!side];
|
||||||
|
goto loc0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1864,6 +1865,8 @@ R_DrawWorld
|
||||||
*/
|
*/
|
||||||
void R_DrawWorld( void )
|
void R_DrawWorld( void )
|
||||||
{
|
{
|
||||||
|
double start, end;
|
||||||
|
|
||||||
// paranoia issues: when gl_renderer is "0" we need have something valid for currententity
|
// paranoia issues: when gl_renderer is "0" we need have something valid for currententity
|
||||||
// to prevent crashing until HeadShield drawing.
|
// to prevent crashing until HeadShield drawing.
|
||||||
RI.currententity = clgame.entities;
|
RI.currententity = clgame.entities;
|
||||||
|
@ -1884,10 +1887,15 @@ void R_DrawWorld( void )
|
||||||
|
|
||||||
R_ClearSkyBox ();
|
R_ClearSkyBox ();
|
||||||
|
|
||||||
|
start = Sys_DoubleTime();
|
||||||
if( RI.drawOrtho )
|
if( RI.drawOrtho )
|
||||||
R_DrawWorldTopView( cl.worldmodel->nodes, RI.frustum.clipFlags );
|
R_DrawWorldTopView( cl.worldmodel->nodes, RI.frustum.clipFlags );
|
||||||
else R_RecursiveWorldNode( cl.worldmodel->nodes, RI.frustum.clipFlags );
|
else R_RecursiveWorldNode( cl.worldmodel->nodes, RI.frustum.clipFlags );
|
||||||
|
end = Sys_DoubleTime();
|
||||||
|
|
||||||
|
r_stats.t_world_node = end - start;
|
||||||
|
|
||||||
|
start = Sys_DoubleTime();
|
||||||
R_DrawTextureChains();
|
R_DrawTextureChains();
|
||||||
|
|
||||||
if( !CL_IsDevOverviewMode( ))
|
if( !CL_IsDevOverviewMode( ))
|
||||||
|
@ -1902,6 +1910,9 @@ void R_DrawWorld( void )
|
||||||
R_DrawSkyBox();
|
R_DrawSkyBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
end = Sys_DoubleTime();
|
||||||
|
|
||||||
|
r_stats.t_world_draw = end - start;
|
||||||
tr.num_draw_decals = 0;
|
tr.num_draw_decals = 0;
|
||||||
skychain = NULL;
|
skychain = NULL;
|
||||||
|
|
||||||
|
|
|
@ -844,8 +844,8 @@ void R_StudioCalcBoneAdj( float dadt, float *adj, const byte *pcontroller1, cons
|
||||||
{
|
{
|
||||||
if( abs( pcontroller1[i] - pcontroller2[i] ) > 128 )
|
if( abs( pcontroller1[i] - pcontroller2[i] ) > 128 )
|
||||||
{
|
{
|
||||||
int a = (pcontroller1[j] + 128) % 256;
|
int a = (pcontroller1[i] + 128) % 256;
|
||||||
int b = (pcontroller2[j] + 128) % 256;
|
int b = (pcontroller2[i] + 128) % 256;
|
||||||
value = (( a * dadt ) + ( b * ( 1.0f - dadt )) - 128) * (360.0f / 256.0f) + pbonecontroller[j].start;
|
value = (( a * dadt ) + ( b * ( 1.0f - dadt )) - 128) * (360.0f / 256.0f) + pbonecontroller[j].start;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -26,6 +26,8 @@ GNU General Public License for more details.
|
||||||
#define WINDOW_STYLE (WS_OVERLAPPED|WS_BORDER|WS_SYSMENU|WS_CAPTION|WS_VISIBLE)
|
#define WINDOW_STYLE (WS_OVERLAPPED|WS_BORDER|WS_SYSMENU|WS_CAPTION|WS_VISIBLE)
|
||||||
#define WINDOW_EX_STYLE (0)
|
#define WINDOW_EX_STYLE (0)
|
||||||
#define WINDOW_NAME "Xash3D Window" // Half-Life
|
#define WINDOW_NAME "Xash3D Window" // Half-Life
|
||||||
|
#define FCONTEXT_CORE_PROFILE BIT( 0 )
|
||||||
|
#define FCONTEXT_DEBUG_ARB BIT( 1 )
|
||||||
|
|
||||||
convar_t *gl_extensions;
|
convar_t *gl_extensions;
|
||||||
convar_t *gl_texture_anisotropy;
|
convar_t *gl_texture_anisotropy;
|
||||||
|
@ -82,7 +84,7 @@ glwstate_t glw_state;
|
||||||
static HWND hWndFake;
|
static HWND hWndFake;
|
||||||
static HDC hDCFake;
|
static HDC hDCFake;
|
||||||
static HGLRC hGLRCFake;
|
static HGLRC hGLRCFake;
|
||||||
static qboolean debug_context;
|
static int context_flags;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
@ -531,8 +533,10 @@ static void GL_SetDefaultState( void )
|
||||||
GL_SetDefaultTexState ();
|
GL_SetDefaultTexState ();
|
||||||
|
|
||||||
if( Sys_CheckParm( "-gldebug" ))
|
if( Sys_CheckParm( "-gldebug" ))
|
||||||
debug_context = true;
|
SetBits( context_flags, FCONTEXT_DEBUG_ARB );
|
||||||
else debug_context = false;
|
|
||||||
|
if( Sys_CheckParm( "-glcore" ))
|
||||||
|
SetBits( context_flags, FCONTEXT_CORE_PROFILE );
|
||||||
|
|
||||||
// init draw stack
|
// init draw stack
|
||||||
tr.draw_list = &tr.draw_stack[0];
|
tr.draw_list = &tr.draw_stack[0];
|
||||||
|
@ -573,6 +577,8 @@ GL_CreateContext
|
||||||
qboolean GL_CreateContext( void )
|
qboolean GL_CreateContext( void )
|
||||||
{
|
{
|
||||||
HGLRC hBaseRC;
|
HGLRC hBaseRC;
|
||||||
|
int profile_mask;
|
||||||
|
int arb_flags;
|
||||||
|
|
||||||
glw_state.extended = false;
|
glw_state.extended = false;
|
||||||
|
|
||||||
|
@ -582,19 +588,27 @@ qboolean GL_CreateContext( void )
|
||||||
if(!( pwglMakeCurrent( glw_state.hDC, glw_state.hGLRC )))
|
if(!( pwglMakeCurrent( glw_state.hDC, glw_state.hGLRC )))
|
||||||
return GL_DeleteContext();
|
return GL_DeleteContext();
|
||||||
|
|
||||||
if( !debug_context ) // debug bit kill the perfomance
|
if( !context_flags ) // debug bit kill the perfomance
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
pwglCreateContextAttribsARB = GL_GetProcAddress( "wglCreateContextAttribsARB" );
|
pwglCreateContextAttribsARB = GL_GetProcAddress( "wglCreateContextAttribsARB" );
|
||||||
|
|
||||||
if( debug_context && pwglCreateContextAttribsARB != NULL )
|
if( FBitSet( context_flags, FCONTEXT_CORE_PROFILE ))
|
||||||
|
profile_mask = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||||
|
else profile_mask = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
||||||
|
|
||||||
|
if( FBitSet( context_flags, FCONTEXT_DEBUG_ARB ))
|
||||||
|
arb_flags = WGL_CONTEXT_DEBUG_BIT_ARB;
|
||||||
|
else arb_flags = 0;
|
||||||
|
|
||||||
|
if( pwglCreateContextAttribsARB != NULL )
|
||||||
{
|
{
|
||||||
int attribs[] =
|
int attribs[] =
|
||||||
{
|
{
|
||||||
WGL_CONTEXT_MAJOR_VERSION_ARB, 2,
|
WGL_CONTEXT_MAJOR_VERSION_ARB, 2,
|
||||||
WGL_CONTEXT_MINOR_VERSION_ARB, 0,
|
WGL_CONTEXT_MINOR_VERSION_ARB, 0,
|
||||||
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB,
|
WGL_CONTEXT_FLAGS_ARB, arb_flags,
|
||||||
// WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
WGL_CONTEXT_PROFILE_MASK_ARB, profile_mask,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1441,7 +1455,7 @@ qboolean R_Init_OpenGL( void )
|
||||||
if( !opengl_dll.link )
|
if( !opengl_dll.link )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if( debug_context || CVAR_TO_BOOL( gl_wgl_msaa_samples ))
|
if( context_flags || CVAR_TO_BOOL( gl_wgl_msaa_samples ))
|
||||||
GL_CheckExtension( "OpenGL Internal ProcAddress", wglproc_funcs, NULL, GL_WGL_PROCADDRESS );
|
GL_CheckExtension( "OpenGL Internal ProcAddress", wglproc_funcs, NULL, GL_WGL_PROCADDRESS );
|
||||||
|
|
||||||
return VID_SetMode();
|
return VID_SetMode();
|
||||||
|
@ -1583,7 +1597,7 @@ void GL_InitCommands( void )
|
||||||
r_dynamic = Cvar_Get( "r_dynamic", "1", FCVAR_ARCHIVE, "allow dynamic lighting (dlights, lightstyles)" );
|
r_dynamic = Cvar_Get( "r_dynamic", "1", FCVAR_ARCHIVE, "allow dynamic lighting (dlights, lightstyles)" );
|
||||||
r_traceglow = Cvar_Get( "r_traceglow", "1", FCVAR_ARCHIVE, "cull flares behind models" );
|
r_traceglow = Cvar_Get( "r_traceglow", "1", FCVAR_ARCHIVE, "cull flares behind models" );
|
||||||
r_lightmap = Cvar_Get( "r_lightmap", "0", FCVAR_CHEAT, "lightmap debugging tool" );
|
r_lightmap = Cvar_Get( "r_lightmap", "0", FCVAR_CHEAT, "lightmap debugging tool" );
|
||||||
r_drawentities = Cvar_Get( "r_drawentities", "1", FCVAR_CHEAT, "render entities" );
|
r_drawentities = Cvar_Get( "r_drawentities", "1", FCVAR_CHEAT|FCVAR_ARCHIVE, "render entities" );
|
||||||
r_decals = Cvar_Get( "r_decals", "4096", FCVAR_ARCHIVE, "sets the maximum number of decals" );
|
r_decals = Cvar_Get( "r_decals", "4096", FCVAR_ARCHIVE, "sets the maximum number of decals" );
|
||||||
window_xpos = Cvar_Get( "_window_xpos", "130", FCVAR_RENDERINFO, "window position by horizontal" );
|
window_xpos = Cvar_Get( "_window_xpos", "130", FCVAR_RENDERINFO, "window position by horizontal" );
|
||||||
window_ypos = Cvar_Get( "_window_ypos", "48", FCVAR_RENDERINFO, "window position by vertical" );
|
window_ypos = Cvar_Get( "_window_ypos", "48", FCVAR_RENDERINFO, "window position by vertical" );
|
||||||
|
@ -1680,7 +1694,7 @@ void GL_InitExtensions( void )
|
||||||
else glConfig.hardware_type = GLHW_GENERIC;
|
else glConfig.hardware_type = GLHW_GENERIC;
|
||||||
|
|
||||||
// initalize until base opengl functions loaded (old-context)
|
// initalize until base opengl functions loaded (old-context)
|
||||||
if( !debug_context && !CVAR_TO_BOOL( gl_wgl_msaa_samples ))
|
if( !context_flags && !CVAR_TO_BOOL( gl_wgl_msaa_samples ))
|
||||||
GL_CheckExtension( "OpenGL Internal ProcAddress", wglproc_funcs, NULL, GL_WGL_PROCADDRESS );
|
GL_CheckExtension( "OpenGL Internal ProcAddress", wglproc_funcs, NULL, GL_WGL_PROCADDRESS );
|
||||||
|
|
||||||
// windows-specific extensions
|
// windows-specific extensions
|
||||||
|
|
|
@ -1298,7 +1298,7 @@ int S_GetCurrentDynamicSounds( soundlist_t *pout, int size )
|
||||||
|
|
||||||
looped = ( channels[i].use_loop && channels[i].sfx->cache->loopStart != -1 );
|
looped = ( channels[i].use_loop && channels[i].sfx->cache->loopStart != -1 );
|
||||||
|
|
||||||
if( channels[i].entchannel == CHAN_STATIC && looped && !FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
if( channels[i].entchannel == CHAN_STATIC && looped && !CL_IsQuakeCompatible())
|
||||||
continue; // never serialize static looped sounds. It will be restoring in game code
|
continue; // never serialize static looped sounds. It will be restoring in game code
|
||||||
|
|
||||||
if( channels[i].isSentence && channels[i].name[0] )
|
if( channels[i].isSentence && channels[i].name[0] )
|
||||||
|
@ -2014,6 +2014,23 @@ void S_Play_f( void )
|
||||||
S_StartLocalSound( Cmd_Argv( 1 ), VOL_NORM, false );
|
S_StartLocalSound( Cmd_Argv( 1 ), VOL_NORM, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void S_Play2_f( void )
|
||||||
|
{
|
||||||
|
int i = 1;
|
||||||
|
|
||||||
|
if( Cmd_Argc() == 1 )
|
||||||
|
{
|
||||||
|
Con_Printf( S_USAGE "play <soundfile>\n" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while( i < Cmd_Argc( ))
|
||||||
|
{
|
||||||
|
S_StartLocalSound( Cmd_Argv( i ), VOL_NORM, true );
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void S_PlayVol_f( void )
|
void S_PlayVol_f( void )
|
||||||
{
|
{
|
||||||
if( Cmd_Argc() == 1 )
|
if( Cmd_Argc() == 1 )
|
||||||
|
@ -2180,6 +2197,7 @@ qboolean S_Init( void )
|
||||||
s_phs = Cvar_Get( "s_phs", "0", FCVAR_ARCHIVE, "cull sounds by PHS" );
|
s_phs = Cvar_Get( "s_phs", "0", FCVAR_ARCHIVE, "cull sounds by PHS" );
|
||||||
|
|
||||||
Cmd_AddCommand( "play", S_Play_f, "playing a specified sound file" );
|
Cmd_AddCommand( "play", S_Play_f, "playing a specified sound file" );
|
||||||
|
Cmd_AddCommand( "play2", S_Play2_f, "playing a group of specified sound files" ); // nehahra stuff
|
||||||
Cmd_AddCommand( "playvol", S_PlayVol_f, "playing a specified sound file with specified volume" );
|
Cmd_AddCommand( "playvol", S_PlayVol_f, "playing a specified sound file with specified volume" );
|
||||||
Cmd_AddCommand( "stopsound", S_StopSound_f, "stop all sounds" );
|
Cmd_AddCommand( "stopsound", S_StopSound_f, "stop all sounds" );
|
||||||
Cmd_AddCommand( "music", S_Music_f, "starting a background track" );
|
Cmd_AddCommand( "music", S_Music_f, "starting a background track" );
|
||||||
|
|
|
@ -48,6 +48,6 @@ int Q_buildnum( void )
|
||||||
|
|
||||||
return b;
|
return b;
|
||||||
#else
|
#else
|
||||||
return 4143;
|
return 4150;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -935,6 +935,7 @@ qboolean CL_IsTimeDemo( void );
|
||||||
qboolean CL_IsPlaybackDemo( void );
|
qboolean CL_IsPlaybackDemo( void );
|
||||||
qboolean CL_IsBackgroundDemo( void );
|
qboolean CL_IsBackgroundDemo( void );
|
||||||
qboolean CL_IsBackgroundMap( void );
|
qboolean CL_IsBackgroundMap( void );
|
||||||
|
qboolean CL_IsQuakeCompatible( void );
|
||||||
qboolean SV_Initialized( void );
|
qboolean SV_Initialized( void );
|
||||||
qboolean CL_LoadProgs( const char *name );
|
qboolean CL_LoadProgs( const char *name );
|
||||||
qboolean SV_GetSaveComment( const char *savename, char *comment );
|
qboolean SV_GetSaveComment( const char *savename, char *comment );
|
||||||
|
|
|
@ -2333,10 +2333,9 @@ dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath )
|
||||||
COM_DefaultExtension( dllpath, ".dll" ); // apply ext if forget
|
COM_DefaultExtension( dllpath, ".dll" ); // apply ext if forget
|
||||||
search = FS_FindFile( dllpath, &index, false );
|
search = FS_FindFile( dllpath, &index, false );
|
||||||
|
|
||||||
if( !search )
|
if( !search && !directpath )
|
||||||
{
|
{
|
||||||
fs_ext_path = false;
|
fs_ext_path = false;
|
||||||
if( directpath ) return NULL; // direct paths fails here
|
|
||||||
|
|
||||||
// trying check also 'bin' folder for indirect paths
|
// trying check also 'bin' folder for indirect paths
|
||||||
Q_strncpy( dllpath, dllname, sizeof( dllpath ));
|
Q_strncpy( dllpath, dllname, sizeof( dllpath ));
|
||||||
|
@ -2344,7 +2343,8 @@ dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath )
|
||||||
if( !search ) return NULL; // unable to find
|
if( !search ) return NULL; // unable to find
|
||||||
}
|
}
|
||||||
|
|
||||||
// all done, create dll_user_t struct
|
// NOTE: for libraries we not fail even if search is NULL
|
||||||
|
// let the OS find library himself
|
||||||
hInst = Mem_Calloc( host.mempool, sizeof( dll_user_t ));
|
hInst = Mem_Calloc( host.mempool, sizeof( dll_user_t ));
|
||||||
|
|
||||||
// save dllname for debug purposes
|
// save dllname for debug purposes
|
||||||
|
@ -2355,15 +2355,16 @@ dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath )
|
||||||
|
|
||||||
hInst->encrypted = FS_CheckForCrypt( dllpath );
|
hInst->encrypted = FS_CheckForCrypt( dllpath );
|
||||||
|
|
||||||
if( index < 0 && !hInst->encrypted )
|
if( index < 0 && !hInst->encrypted && search )
|
||||||
{
|
{
|
||||||
Q_snprintf( hInst->fullPath, sizeof( hInst->fullPath ), "%s%s", search->filename, dllpath );
|
Q_snprintf( hInst->fullPath, sizeof( hInst->fullPath ), "%s%s", search->filename, dllpath );
|
||||||
hInst->custom_loader = false; // we can loading from disk and use normal debugging
|
hInst->custom_loader = false; // we can loading from disk and use normal debugging
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// NOTE: if search is NULL let the OS found library himself
|
||||||
Q_strncpy( hInst->fullPath, dllpath, sizeof( hInst->fullPath ));
|
Q_strncpy( hInst->fullPath, dllpath, sizeof( hInst->fullPath ));
|
||||||
hInst->custom_loader = true; // loading from pack or wad - for release, debug don't working
|
hInst->custom_loader = (search) ? true : false;
|
||||||
}
|
}
|
||||||
fs_ext_path = false; // always reset direct paths
|
fs_ext_path = false; // always reset direct paths
|
||||||
|
|
||||||
|
|
|
@ -226,6 +226,33 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===========
|
||||||
|
IN_RecalcCenter
|
||||||
|
|
||||||
|
Recalc the center of screen
|
||||||
|
===========
|
||||||
|
*/
|
||||||
|
void IN_RecalcCenter( qboolean setpos )
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
|
||||||
|
if( host.status != HOST_FRAME )
|
||||||
|
return;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
host.window_center_x = (window_rect.right + window_rect.left) / 2;
|
||||||
|
host.window_center_y = (window_rect.top + window_rect.bottom) / 2;
|
||||||
|
if( setpos ) SetCursorPos( host.window_center_x, host.window_center_y );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===========
|
===========
|
||||||
IN_ActivateMouse
|
IN_ActivateMouse
|
||||||
|
@ -235,7 +262,6 @@ Called when the window gains focus or changes in some way
|
||||||
*/
|
*/
|
||||||
void IN_ActivateMouse( qboolean force )
|
void IN_ActivateMouse( qboolean force )
|
||||||
{
|
{
|
||||||
int width, height;
|
|
||||||
static int oldstate;
|
static int oldstate;
|
||||||
|
|
||||||
if( !in_mouseinitialized )
|
if( !in_mouseinitialized )
|
||||||
|
@ -281,18 +307,7 @@ void IN_ActivateMouse( qboolean force )
|
||||||
clgame.dllFuncs.IN_ActivateMouse();
|
clgame.dllFuncs.IN_ActivateMouse();
|
||||||
}
|
}
|
||||||
|
|
||||||
width = GetSystemMetrics( SM_CXSCREEN );
|
IN_RecalcCenter( true );
|
||||||
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;
|
|
||||||
|
|
||||||
host.window_center_x = (window_rect.right + window_rect.left) / 2;
|
|
||||||
host.window_center_y = (window_rect.top + window_rect.bottom) / 2;
|
|
||||||
SetCursorPos( host.window_center_x, host.window_center_y );
|
|
||||||
|
|
||||||
SetCapture( host.hWnd );
|
SetCapture( host.hWnd );
|
||||||
ClipCursor( &window_rect );
|
ClipCursor( &window_rect );
|
||||||
|
@ -498,6 +513,7 @@ LONG IN_WndProc( HWND hWnd, UINT uMsg, UINT wParam, LONG lParam )
|
||||||
S_Activate( fActivate, host.hWnd );
|
S_Activate( fActivate, host.hWnd );
|
||||||
IN_ActivateMouse( fActivate );
|
IN_ActivateMouse( fActivate );
|
||||||
Key_ClearStates();
|
Key_ClearStates();
|
||||||
|
IN_RecalcCenter( false );
|
||||||
|
|
||||||
if( host.status == HOST_FRAME )
|
if( host.status == HOST_FRAME )
|
||||||
{
|
{
|
||||||
|
|
|
@ -1472,6 +1472,12 @@ static void Mod_LoadSubmodels( dbspmodel_t *bmod )
|
||||||
{
|
{
|
||||||
for( j = 0; j < 3; j++ )
|
for( j = 0; j < 3; j++ )
|
||||||
{
|
{
|
||||||
|
// reset empty bounds to prevent error
|
||||||
|
if( in->mins[j] == 999999.0f )
|
||||||
|
in->mins[j] = 0.0f;
|
||||||
|
if( in->maxs[j] == -999999.0f)
|
||||||
|
in->maxs[j] = 0.0f;
|
||||||
|
|
||||||
// spread the mins / maxs by a unit
|
// spread the mins / maxs by a unit
|
||||||
out->mins[j] = in->mins[j] - 1.0f;
|
out->mins[j] = in->mins[j] - 1.0f;
|
||||||
out->maxs[j] = in->maxs[j] + 1.0f;
|
out->maxs[j] = in->maxs[j] + 1.0f;
|
||||||
|
@ -2188,7 +2194,7 @@ static void Mod_LoadSurfaces( dbspmodel_t *bmod )
|
||||||
if(( tex->name[0] == '*' && Q_stricmp( tex->name, "*default" )) || tex->name[0] == '!' )
|
if(( tex->name[0] == '*' && Q_stricmp( tex->name, "*default" )) || tex->name[0] == '!' )
|
||||||
SetBits( out->flags, SURF_DRAWTURB|SURF_DRAWTILED );
|
SetBits( out->flags, SURF_DRAWTURB|SURF_DRAWTILED );
|
||||||
|
|
||||||
if( !FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
if( !CL_IsQuakeCompatible( ))
|
||||||
{
|
{
|
||||||
if( !Q_strncmp( tex->name, "water", 5 ) || !Q_strnicmp( tex->name, "laser", 5 ))
|
if( !Q_strncmp( tex->name, "water", 5 ) || !Q_strnicmp( tex->name, "laser", 5 ))
|
||||||
SetBits( out->flags, SURF_DRAWTURB|SURF_DRAWTILED );
|
SetBits( out->flags, SURF_DRAWTURB|SURF_DRAWTILED );
|
||||||
|
|
|
@ -284,7 +284,7 @@ void MSG_WriteCoord( sizebuf_t *sb, float val )
|
||||||
{
|
{
|
||||||
// g-cont. we loose precision here but keep old size of coord variable!
|
// g-cont. we loose precision here but keep old size of coord variable!
|
||||||
if( FBitSet( host.features, ENGINE_WRITE_LARGE_COORD ))
|
if( FBitSet( host.features, ENGINE_WRITE_LARGE_COORD ))
|
||||||
MSG_WriteShort( sb, (int)( val * 2.0f ));
|
MSG_WriteShort( sb, Q_rint( val ));
|
||||||
else MSG_WriteShort( sb, (int)( val * 8.0f ));
|
else MSG_WriteShort( sb, (int)( val * 8.0f ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,7 +598,7 @@ float MSG_ReadCoord( sizebuf_t *sb )
|
||||||
{
|
{
|
||||||
// g-cont. we loose precision here but keep old size of coord variable!
|
// g-cont. we loose precision here but keep old size of coord variable!
|
||||||
if( FBitSet( host.features, ENGINE_WRITE_LARGE_COORD ))
|
if( FBitSet( host.features, ENGINE_WRITE_LARGE_COORD ))
|
||||||
return (float)(MSG_ReadShort( sb ) * ( 1.0f / 2.0f ));
|
return (float)(MSG_ReadShort( sb ));
|
||||||
return (float)(MSG_ReadShort( sb ) * ( 1.0f / 8.0f ));
|
return (float)(MSG_ReadShort( sb ) * ( 1.0f / 8.0f ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -804,7 +804,7 @@ void Delta_Init( void )
|
||||||
Delta_AddField( "movevars_t", "stepsize", DT_FLOAT|DT_SIGNED, 16, 16.0f, 1.0f );
|
Delta_AddField( "movevars_t", "stepsize", DT_FLOAT|DT_SIGNED, 16, 16.0f, 1.0f );
|
||||||
Delta_AddField( "movevars_t", "maxvelocity", DT_FLOAT|DT_SIGNED, 16, 8.0f, 1.0f );
|
Delta_AddField( "movevars_t", "maxvelocity", DT_FLOAT|DT_SIGNED, 16, 8.0f, 1.0f );
|
||||||
|
|
||||||
if( host.features & ENGINE_WRITE_LARGE_COORD )
|
if( FBitSet( host.features, ENGINE_WRITE_LARGE_COORD ))
|
||||||
Delta_AddField( "movevars_t", "zmax", DT_FLOAT|DT_SIGNED, 18, 1.0f, 1.0f );
|
Delta_AddField( "movevars_t", "zmax", DT_FLOAT|DT_SIGNED, 18, 1.0f, 1.0f );
|
||||||
else Delta_AddField( "movevars_t", "zmax", DT_FLOAT|DT_SIGNED, 16, 1.0f, 1.0f );
|
else Delta_AddField( "movevars_t", "zmax", DT_FLOAT|DT_SIGNED, 16, 1.0f, 1.0f );
|
||||||
|
|
||||||
|
@ -1703,7 +1703,7 @@ If force is not set, then nothing at all will be generated if the entity is
|
||||||
identical, under the assumption that the in-order delta code will catch it.
|
identical, under the assumption that the in-order delta code will catch it.
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, qboolean player, float timebase, int baseline )
|
void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, int delta_type, float timebase, int baseline )
|
||||||
{
|
{
|
||||||
delta_info_t *dt = NULL;
|
delta_info_t *dt = NULL;
|
||||||
delta_t *pField;
|
delta_t *pField;
|
||||||
|
@ -1757,7 +1757,7 @@ void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *
|
||||||
{
|
{
|
||||||
dt = Delta_FindStruct( "custom_entity_state_t" );
|
dt = Delta_FindStruct( "custom_entity_state_t" );
|
||||||
}
|
}
|
||||||
else if( player )
|
else if( delta_type == DELTA_PLAYER )
|
||||||
{
|
{
|
||||||
dt = Delta_FindStruct( "entity_state_player_t" );
|
dt = Delta_FindStruct( "entity_state_player_t" );
|
||||||
}
|
}
|
||||||
|
@ -1771,8 +1771,17 @@ void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *
|
||||||
pField = dt->pFields;
|
pField = dt->pFields;
|
||||||
Assert( pField != NULL );
|
Assert( pField != NULL );
|
||||||
|
|
||||||
|
if( delta_type == DELTA_STATIC )
|
||||||
|
{
|
||||||
|
// static entities won't to be custom encoded
|
||||||
|
for( i = 0; i < dt->numFields; i++ )
|
||||||
|
dt->pFields[i].bInactive = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// activate fields and call custom encode func
|
// activate fields and call custom encode func
|
||||||
Delta_CustomEncode( dt, from, to );
|
Delta_CustomEncode( dt, from, to );
|
||||||
|
}
|
||||||
|
|
||||||
// process fields
|
// process fields
|
||||||
for( i = 0; i < dt->numFields; i++, pField++ )
|
for( i = 0; i < dt->numFields; i++, pField++ )
|
||||||
|
@ -1796,7 +1805,7 @@ If the delta removes the entity, entity_state_t->number will be set to MAX_EDICT
|
||||||
Can go from either a baseline or a previous packet_entity
|
Can go from either a baseline or a previous packet_entity
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state_t *to, int number, qboolean player, float timebase )
|
qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state_t *to, int number, int delta_type, float timebase )
|
||||||
{
|
{
|
||||||
delta_info_t *dt = NULL;
|
delta_info_t *dt = NULL;
|
||||||
delta_t *pField;
|
delta_t *pField;
|
||||||
|
@ -1834,7 +1843,12 @@ qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state
|
||||||
|
|
||||||
if( baseline_offset != 0 )
|
if( baseline_offset != 0 )
|
||||||
{
|
{
|
||||||
if( baseline_offset > 0 )
|
if( delta_type == DELTA_STATIC )
|
||||||
|
{
|
||||||
|
int backup = Q_max( 0, clgame.numStatics - abs( baseline_offset ));
|
||||||
|
from = &clgame.static_entities[backup].baseline;
|
||||||
|
}
|
||||||
|
else if( baseline_offset > 0 )
|
||||||
{
|
{
|
||||||
int backup = cls.next_client_entities - baseline_offset;
|
int backup = cls.next_client_entities - baseline_offset;
|
||||||
from = &cls.packet_entities[backup % cls.num_client_entities];
|
from = &cls.packet_entities[backup % cls.num_client_entities];
|
||||||
|
@ -1858,7 +1872,7 @@ qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state
|
||||||
{
|
{
|
||||||
dt = Delta_FindStruct( "custom_entity_state_t" );
|
dt = Delta_FindStruct( "custom_entity_state_t" );
|
||||||
}
|
}
|
||||||
else if( player )
|
else if( delta_type == DELTA_PLAYER )
|
||||||
{
|
{
|
||||||
dt = Delta_FindStruct( "entity_state_player_t" );
|
dt = Delta_FindStruct( "entity_state_player_t" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,8 +40,16 @@ GNU General Public License for more details.
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
CUSTOM_NONE = 0,
|
CUSTOM_NONE = 0,
|
||||||
CUSTOM_SERVER_ENCODE, // keyword "gamedll"
|
CUSTOM_SERVER_ENCODE, // known as "gamedll"
|
||||||
CUSTOM_CLIENT_ENCODE, // keyword "client"
|
CUSTOM_CLIENT_ENCODE, // known as "client"
|
||||||
|
};
|
||||||
|
|
||||||
|
// don't change order!
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
DELTA_ENTITY = 0,
|
||||||
|
DELTA_PLAYER,
|
||||||
|
DELTA_STATIC,
|
||||||
};
|
};
|
||||||
|
|
||||||
// struct info (filled by engine)
|
// struct info (filled by engine)
|
||||||
|
@ -114,8 +122,8 @@ void MSG_WriteClientData( sizebuf_t *msg, struct clientdata_s *from, struct clie
|
||||||
void MSG_ReadClientData( sizebuf_t *msg, struct clientdata_s *from, struct clientdata_s *to, float timebase );
|
void MSG_ReadClientData( sizebuf_t *msg, struct clientdata_s *from, struct clientdata_s *to, float timebase );
|
||||||
void MSG_WriteWeaponData( sizebuf_t *msg, struct weapon_data_s *from, struct weapon_data_s *to, float timebase, int index );
|
void MSG_WriteWeaponData( sizebuf_t *msg, struct weapon_data_s *from, struct weapon_data_s *to, float timebase, int index );
|
||||||
void MSG_ReadWeaponData( sizebuf_t *msg, struct weapon_data_s *from, struct weapon_data_s *to, float timebase );
|
void MSG_ReadWeaponData( sizebuf_t *msg, struct weapon_data_s *from, struct weapon_data_s *to, float timebase );
|
||||||
void MSG_WriteDeltaEntity( struct entity_state_s *from, struct entity_state_s *to, sizebuf_t *msg, qboolean force, qboolean pl, float tbase, int bl );
|
void MSG_WriteDeltaEntity( struct entity_state_s *from, struct entity_state_s *to, sizebuf_t *msg, qboolean force, int type, float tbase, int ofs );
|
||||||
qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, struct entity_state_s *from, struct entity_state_s *to, int num, qboolean player, float timebase );
|
qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, struct entity_state_s *from, struct entity_state_s *to, int num, int type, float timebase );
|
||||||
int Delta_TestBaseline( struct entity_state_s *from, struct entity_state_s *to, qboolean player, float timebase );
|
int Delta_TestBaseline( struct entity_state_s *from, struct entity_state_s *to, qboolean player, float timebase );
|
||||||
|
|
||||||
#endif//NET_ENCODE_H
|
#endif//NET_ENCODE_H
|
|
@ -179,6 +179,67 @@ GNU General Public License for more details.
|
||||||
#define FRAGMENT_MAX_SIZE 64000 // maximal fragment size
|
#define FRAGMENT_MAX_SIZE 64000 // maximal fragment size
|
||||||
#define FRAGMENT_LOCAL_SIZE FRAGMENT_MAX_SIZE // local connection
|
#define FRAGMENT_LOCAL_SIZE FRAGMENT_MAX_SIZE // local connection
|
||||||
|
|
||||||
|
// Quake1 Protocol
|
||||||
|
#define PROTOCOL_VERSION_QUAKE 15
|
||||||
|
|
||||||
|
// listed only unmatched ops
|
||||||
|
#define svc_updatestat 3 // [byte] [long] (svc_event)
|
||||||
|
#define svc_version 4 // [long] server version (svc_changing)
|
||||||
|
#define svc_updatename 13 // [byte] [string] (svc_updateuserinfo)
|
||||||
|
#define svc_updatefrags 14 // [byte] [short] (svc_deltatable)
|
||||||
|
#define svc_stopsound 16 // <see code> (svc_resource)
|
||||||
|
#define svc_updatecolors 17 // [byte] [byte] (svc_pings)
|
||||||
|
#define svc_damage 19 // (svc_restoresound)
|
||||||
|
#define svc_spawnbinary 21 // (svc_event_reliable)
|
||||||
|
#define svc_killedmonster 27
|
||||||
|
#define svc_foundsecret 28
|
||||||
|
#define svc_spawnstaticsound 29 // [coord3] [byte] samp [byte] vol [byte] aten
|
||||||
|
#define svc_sellscreen 33 // (svc_restore)
|
||||||
|
// Nehahra added
|
||||||
|
#define svc_showlmp 35 // [string] slotname [string] lmpfilename [coord] x [coord] y
|
||||||
|
#define svc_hidelmp 36 // [string] slotname
|
||||||
|
#define svc_skybox 37 // [string] skyname
|
||||||
|
#define svc_skyboxsize 50 // [coord] size (default is 4096)
|
||||||
|
#define svc_fog 51 // [byte] enable <optional past this point, only included if enable is true>
|
||||||
|
// [float] density [byte] red [byte] green [byte] blue
|
||||||
|
|
||||||
|
// if the high bit of the servercmd is set, the low bits are fast update flags:
|
||||||
|
#define U_MOREBITS (1<<0)
|
||||||
|
#define U_ORIGIN1 (1<<1)
|
||||||
|
#define U_ORIGIN2 (1<<2)
|
||||||
|
#define U_ORIGIN3 (1<<3)
|
||||||
|
#define U_ANGLE2 (1<<4)
|
||||||
|
#define U_NOLERP (1<<5) // don't interpolate movement
|
||||||
|
#define U_FRAME (1<<6)
|
||||||
|
#define U_SIGNAL (1<<7) // just differentiates from other updates
|
||||||
|
|
||||||
|
// svc_update can pass all of the fast update bits, plus more
|
||||||
|
#define U_ANGLE1 (1<<8)
|
||||||
|
#define U_ANGLE3 (1<<9)
|
||||||
|
#define U_MODEL (1<<10)
|
||||||
|
#define U_COLORMAP (1<<11)
|
||||||
|
#define U_SKIN (1<<12)
|
||||||
|
#define U_EFFECTS (1<<13)
|
||||||
|
#define U_LONGENTITY (1<<14)
|
||||||
|
#define U_TRANS (1<<15) // nehahra
|
||||||
|
|
||||||
|
// clientdata flags
|
||||||
|
#define SU_VIEWHEIGHT (1<<0)
|
||||||
|
#define SU_IDEALPITCH (1<<1)
|
||||||
|
#define SU_PUNCH1 (1<<2)
|
||||||
|
#define SU_PUNCH2 (1<<3)
|
||||||
|
#define SU_PUNCH3 (1<<4)
|
||||||
|
#define SU_VELOCITY1 (1<<5)
|
||||||
|
#define SU_VELOCITY2 (1<<6)
|
||||||
|
#define SU_VELOCITY3 (1<<7)
|
||||||
|
//define SU_AIMENT (1<<8) AVAILABLE BIT
|
||||||
|
#define SU_ITEMS (1<<9)
|
||||||
|
#define SU_ONGROUND (1<<10) // no data follows, the bit is it
|
||||||
|
#define SU_INWATER (1<<11) // no data follows, the bit is it
|
||||||
|
#define SU_WEAPONFRAME (1<<12)
|
||||||
|
#define SU_ARMOR (1<<13)
|
||||||
|
#define SU_WEAPON (1<<14)
|
||||||
|
|
||||||
extern const char *svc_strings[svc_lastmsg+1];
|
extern const char *svc_strings[svc_lastmsg+1];
|
||||||
extern const char *clc_strings[clc_lastmsg+1];
|
extern const char *clc_strings[clc_lastmsg+1];
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ qboolean Sound_LoadMPG( const char *name, const byte *buffer, size_t filesize )
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
size_t bytesWrite = 0;
|
size_t bytesWrite = 0;
|
||||||
char out[OUTBUF_SIZE];
|
char out[OUTBUF_SIZE];
|
||||||
size_t outsize;
|
size_t outsize, padsize;
|
||||||
int ret;
|
int ret;
|
||||||
wavinfo_t sc;
|
wavinfo_t sc;
|
||||||
|
|
||||||
|
@ -91,6 +91,7 @@ qboolean Sound_LoadMPG( const char *name, const byte *buffer, size_t filesize )
|
||||||
sound.width = 2; // always 16-bit PCM
|
sound.width = 2; // always 16-bit PCM
|
||||||
sound.loopstart = -1;
|
sound.loopstart = -1;
|
||||||
sound.size = ( sound.channels * sound.rate * sound.width ) * ( sc.playtime / 1000 ); // in bytes
|
sound.size = ( sound.channels * sound.rate * sound.width ) * ( sc.playtime / 1000 ); // in bytes
|
||||||
|
padsize = sound.size % FRAME_SIZE;
|
||||||
pos += FRAME_SIZE; // evaluate pos
|
pos += FRAME_SIZE; // evaluate pos
|
||||||
|
|
||||||
if( !sound.size )
|
if( !sound.size )
|
||||||
|
@ -101,8 +102,9 @@ qboolean Sound_LoadMPG( const char *name, const byte *buffer, size_t filesize )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add sentinel make sure we not overrun
|
||||||
|
sound.wav = (byte *)Mem_Calloc( host.soundpool, sound.size + padsize );
|
||||||
sound.type = WF_PCMDATA;
|
sound.type = WF_PCMDATA;
|
||||||
sound.wav = (byte *)Mem_Malloc( host.soundpool, sound.size );
|
|
||||||
|
|
||||||
// decompress mpg into pcm wav format
|
// decompress mpg into pcm wav format
|
||||||
while( bytesWrite < sound.size )
|
while( bytesWrite < sound.size )
|
||||||
|
|
|
@ -113,24 +113,6 @@ typedef struct
|
||||||
file_t *file;
|
file_t *file;
|
||||||
} server_log_t;
|
} server_log_t;
|
||||||
|
|
||||||
// like as entity_state_t in Quake
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char model[MAX_QPATH]; // name of static-entity model for right precache
|
|
||||||
vec3_t origin;
|
|
||||||
vec3_t angles;
|
|
||||||
short sequence;
|
|
||||||
short frame;
|
|
||||||
short colormap;
|
|
||||||
byte skin; // can't set contents! only real skin!
|
|
||||||
byte body;
|
|
||||||
float scale;
|
|
||||||
byte rendermode;
|
|
||||||
byte renderamt;
|
|
||||||
color24 rendercolor;
|
|
||||||
byte renderfx;
|
|
||||||
} sv_static_entity_t;
|
|
||||||
|
|
||||||
typedef struct server_s
|
typedef struct server_s
|
||||||
{
|
{
|
||||||
sv_state_t state; // precache commands are only valid during load
|
sv_state_t state; // precache commands are only valid during load
|
||||||
|
@ -159,8 +141,6 @@ typedef struct server_s
|
||||||
char event_precache[MAX_EVENTS][MAX_QPATH];
|
char event_precache[MAX_EVENTS][MAX_QPATH];
|
||||||
byte model_precache_flags[MAX_MODELS];
|
byte model_precache_flags[MAX_MODELS];
|
||||||
model_t *models[MAX_MODELS];
|
model_t *models[MAX_MODELS];
|
||||||
|
|
||||||
sv_static_entity_t static_entities[MAX_STATIC_ENTITIES];
|
|
||||||
int num_static_entities;
|
int num_static_entities;
|
||||||
|
|
||||||
// run local lightstyles to let SV_LightPoint grab the actual information
|
// run local lightstyles to let SV_LightPoint grab the actual information
|
||||||
|
@ -386,6 +366,7 @@ typedef struct
|
||||||
int next_client_entities; // next client_entity to use
|
int next_client_entities; // next client_entity to use
|
||||||
entity_state_t *packet_entities; // [num_client_entities]
|
entity_state_t *packet_entities; // [num_client_entities]
|
||||||
entity_state_t *baselines; // [GI->max_edicts]
|
entity_state_t *baselines; // [GI->max_edicts]
|
||||||
|
entity_state_t *static_entities; // [MAX_STATIC_ENTITIES];
|
||||||
|
|
||||||
double last_heartbeat;
|
double last_heartbeat;
|
||||||
challenge_t challenges[MAX_CHALLENGES]; // to prevent invalid IPs from connecting
|
challenge_t challenges[MAX_CHALLENGES]; // to prevent invalid IPs from connecting
|
||||||
|
@ -576,6 +557,7 @@ void SV_RequestMissingResources( void );
|
||||||
// sv_frame.c
|
// sv_frame.c
|
||||||
//
|
//
|
||||||
void SV_InactivateClients( void );
|
void SV_InactivateClients( void );
|
||||||
|
int SV_FindBestBaselineForStatic( int index, entity_state_t **baseline, entity_state_t *to );
|
||||||
void SV_WriteFrameToClient( sv_client_t *client, sizebuf_t *msg );
|
void SV_WriteFrameToClient( sv_client_t *client, sizebuf_t *msg );
|
||||||
void SV_BuildClientFrame( sv_client_t *client );
|
void SV_BuildClientFrame( sv_client_t *client );
|
||||||
void SV_SendMessagesToAll( void );
|
void SV_SendMessagesToAll( void );
|
||||||
|
@ -612,8 +594,8 @@ const char *SV_GetString( string_t iString );
|
||||||
sv_client_t *SV_ClientFromEdict( const edict_t *pEdict, qboolean spawned_only );
|
sv_client_t *SV_ClientFromEdict( const edict_t *pEdict, qboolean spawned_only );
|
||||||
int SV_MapIsValid( const char *filename, const char *spawn_entity, const char *landmark_name );
|
int SV_MapIsValid( const char *filename, const char *spawn_entity, const char *landmark_name );
|
||||||
void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch );
|
void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch );
|
||||||
void SV_CreateStaticEntity( struct sizebuf_s *msg, sv_static_entity_t *ent );
|
|
||||||
edict_t *SV_FindGlobalEntity( string_t classname, string_t globalname );
|
edict_t *SV_FindGlobalEntity( string_t classname, string_t globalname );
|
||||||
|
qboolean SV_CreateStaticEntity( struct sizebuf_s *msg, int index );
|
||||||
void SV_SendUserReg( sizebuf_t *msg, sv_user_message_t *user );
|
void SV_SendUserReg( sizebuf_t *msg, sv_user_message_t *user );
|
||||||
edict_t* pfnPEntityOfEntIndex( int iEntIndex );
|
edict_t* pfnPEntityOfEntIndex( int iEntIndex );
|
||||||
int pfnIndexOfEdict( const edict_t *pEdict );
|
int pfnIndexOfEdict( const edict_t *pEdict );
|
||||||
|
@ -622,6 +604,7 @@ void SV_UpdateBaseVelocity( edict_t *ent );
|
||||||
byte *pfnSetFatPVS( const float *org );
|
byte *pfnSetFatPVS( const float *org );
|
||||||
byte *pfnSetFatPAS( const float *org );
|
byte *pfnSetFatPAS( const float *org );
|
||||||
int pfnPrecacheModel( const char *s );
|
int pfnPrecacheModel( const char *s );
|
||||||
|
int pfnModelIndex( const char *m );
|
||||||
void pfnRemoveEntity( edict_t* e );
|
void pfnRemoveEntity( edict_t* e );
|
||||||
void SV_RestartAmbientSounds( void );
|
void SV_RestartAmbientSounds( void );
|
||||||
void SV_RestartDecals( void );
|
void SV_RestartDecals( void );
|
||||||
|
|
|
@ -800,6 +800,7 @@ void SV_InitHostCommands( void )
|
||||||
Cmd_AddCommand( "map_background", SV_MapBackground_f, "set background map" );
|
Cmd_AddCommand( "map_background", SV_MapBackground_f, "set background map" );
|
||||||
Cmd_AddCommand( "load", SV_Load_f, "load a saved game file" );
|
Cmd_AddCommand( "load", SV_Load_f, "load a saved game file" );
|
||||||
Cmd_AddCommand( "loadquick", SV_QuickLoad_f, "load a quick-saved game file" );
|
Cmd_AddCommand( "loadquick", SV_QuickLoad_f, "load a quick-saved game file" );
|
||||||
|
Cmd_AddCommand( "reload", SV_Reload_f, "continue from latest save or restart level" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -818,7 +819,6 @@ void SV_InitOperatorCommands( void )
|
||||||
Cmd_AddCommand( "clientinfo", SV_ClientInfo_f, "print user infostring (player num required)" );
|
Cmd_AddCommand( "clientinfo", SV_ClientInfo_f, "print user infostring (player num required)" );
|
||||||
Cmd_AddCommand( "playersonly", SV_PlayersOnly_f, "freezes time, except for players" );
|
Cmd_AddCommand( "playersonly", SV_PlayersOnly_f, "freezes time, except for players" );
|
||||||
Cmd_AddCommand( "restart", SV_Restart_f, "restarting current level" );
|
Cmd_AddCommand( "restart", SV_Restart_f, "restarting current level" );
|
||||||
Cmd_AddCommand( "reload", SV_Reload_f, "continue from latest save or restart level" );
|
|
||||||
Cmd_AddCommand( "entpatch", SV_EntPatch_f, "write entity patch to allow external editing" );
|
Cmd_AddCommand( "entpatch", SV_EntPatch_f, "write entity patch to allow external editing" );
|
||||||
Cmd_AddCommand( "edict_usage", SV_EdictUsage_f, "show info about edicts usage" );
|
Cmd_AddCommand( "edict_usage", SV_EdictUsage_f, "show info about edicts usage" );
|
||||||
Cmd_AddCommand( "entity_info", SV_EntityInfo_f, "show more info about edicts" );
|
Cmd_AddCommand( "entity_info", SV_EntityInfo_f, "show more info about edicts" );
|
||||||
|
@ -852,7 +852,6 @@ void SV_KillOperatorCommands( void )
|
||||||
Cmd_RemoveCommand( "clientinfo" );
|
Cmd_RemoveCommand( "clientinfo" );
|
||||||
Cmd_RemoveCommand( "playersonly" );
|
Cmd_RemoveCommand( "playersonly" );
|
||||||
Cmd_RemoveCommand( "restart" );
|
Cmd_RemoveCommand( "restart" );
|
||||||
Cmd_RemoveCommand( "reload" );
|
|
||||||
Cmd_RemoveCommand( "entpatch" );
|
Cmd_RemoveCommand( "entpatch" );
|
||||||
Cmd_RemoveCommand( "edict_usage" );
|
Cmd_RemoveCommand( "edict_usage" );
|
||||||
Cmd_RemoveCommand( "entity_info" );
|
Cmd_RemoveCommand( "entity_info" );
|
||||||
|
|
|
@ -172,6 +172,13 @@ Encode a client frame onto the network channel
|
||||||
|
|
||||||
=============================================================================
|
=============================================================================
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
SV_FindBestBaseline
|
||||||
|
|
||||||
|
trying to deltas with previous entities
|
||||||
|
=============
|
||||||
|
*/
|
||||||
int SV_FindBestBaseline( sv_client_t *cl, int index, entity_state_t **baseline, entity_state_t *to, client_frame_t *frame, qboolean player )
|
int SV_FindBestBaseline( sv_client_t *cl, int index, entity_state_t **baseline, entity_state_t *to, client_frame_t *frame, qboolean player )
|
||||||
{
|
{
|
||||||
int bestBitCount;
|
int bestBitCount;
|
||||||
|
@ -205,6 +212,43 @@ int SV_FindBestBaseline( sv_client_t *cl, int index, entity_state_t **baseline,
|
||||||
return index - bestfound;
|
return index - bestfound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
SV_FindBestBaselineForStatic
|
||||||
|
|
||||||
|
trying to deltas with previous static entities
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
int SV_FindBestBaselineForStatic( int index, entity_state_t **baseline, entity_state_t *to )
|
||||||
|
{
|
||||||
|
int bestBitCount;
|
||||||
|
int i, bitCount;
|
||||||
|
int bestfound, j;
|
||||||
|
|
||||||
|
bestBitCount = j = Delta_TestBaseline( *baseline, to, false, sv.time );
|
||||||
|
bestfound = index;
|
||||||
|
|
||||||
|
// lookup backward for previous 64 states and try to interpret current delta as baseline
|
||||||
|
for( i = index - 1; bestBitCount > 0 && i >= 0 && ( index - i ) < ( MAX_CUSTOM_BASELINES - 1 ); i-- )
|
||||||
|
{
|
||||||
|
// don't worry about underflow in circular buffer
|
||||||
|
entity_state_t *test = &svs.static_entities[i];
|
||||||
|
|
||||||
|
bitCount = Delta_TestBaseline( test, to, false, sv.time );
|
||||||
|
|
||||||
|
if( bitCount < bestBitCount )
|
||||||
|
{
|
||||||
|
bestBitCount = bitCount;
|
||||||
|
bestfound = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// using delta from previous entity as baseline for current
|
||||||
|
if( index != bestfound )
|
||||||
|
*baseline = &svs.static_entities[bestfound];
|
||||||
|
return index - bestfound;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=============
|
=============
|
||||||
SV_EmitPacketEntities
|
SV_EmitPacketEntities
|
||||||
|
|
|
@ -497,39 +497,47 @@ SV_CreateStaticEntity
|
||||||
NOTE: static entities only accepted when game is loading
|
NOTE: static entities only accepted when game is loading
|
||||||
=======================
|
=======================
|
||||||
*/
|
*/
|
||||||
void SV_CreateStaticEntity( sizebuf_t *msg, sv_static_entity_t *ent )
|
qboolean SV_CreateStaticEntity( sizebuf_t *msg, int index )
|
||||||
{
|
{
|
||||||
int index;
|
entity_state_t nullstate, *baseline;
|
||||||
|
entity_state_t *state;
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
if( index >= ( MAX_STATIC_ENTITIES - 1 ))
|
||||||
|
{
|
||||||
|
if( !sv.static_ents_overflow )
|
||||||
|
{
|
||||||
|
Con_Printf( S_WARN "MAX_STATIC_ENTITIES limit exceeded (%d)\n", MAX_STATIC_ENTITIES );
|
||||||
|
sv.static_ents_overflow = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
sv.ignored_static_ents++; // continue overflowed entities
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// this can happens if serialized map contain too many static entities...
|
// this can happens if serialized map contain too many static entities...
|
||||||
if( MSG_GetNumBytesLeft( msg ) < 35 )
|
if( MSG_GetNumBytesLeft( msg ) < 50 )
|
||||||
{
|
{
|
||||||
sv.ignored_static_ents++;
|
sv.ignored_static_ents++;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
index = SV_ModelIndex( ent->model );
|
state = &svs.static_entities[index]; // allocate a new one
|
||||||
|
memset( &nullstate, 0, sizeof( nullstate ));
|
||||||
|
baseline = &nullstate;
|
||||||
|
|
||||||
|
// restore modelindex from modelname (already precached)
|
||||||
|
state->modelindex = pfnModelIndex( STRING( state->messagenum ));
|
||||||
|
state->entityType = ENTITY_NORMAL; // select delta-encode
|
||||||
|
state->number = 0;
|
||||||
|
|
||||||
|
// trying to compress with previous delta's
|
||||||
|
offset = SV_FindBestBaselineForStatic( index, &baseline, state );
|
||||||
|
|
||||||
MSG_BeginServerCmd( msg, svc_spawnstatic );
|
MSG_BeginServerCmd( msg, svc_spawnstatic );
|
||||||
MSG_WriteShort( msg, index );
|
MSG_WriteDeltaEntity( baseline, state, msg, true, DELTA_STATIC, sv.time, offset );
|
||||||
MSG_WriteWord( msg, ent->sequence );
|
|
||||||
MSG_WriteWord( msg, ent->frame );
|
|
||||||
MSG_WriteWord( msg, ent->colormap );
|
|
||||||
MSG_WriteByte( msg, ent->skin );
|
|
||||||
MSG_WriteByte( msg, ent->body );
|
|
||||||
MSG_WriteCoord( msg, ent->scale );
|
|
||||||
MSG_WriteVec3Coord( msg, ent->origin );
|
|
||||||
MSG_WriteVec3Angles( msg, ent->angles );
|
|
||||||
MSG_WriteByte( msg, ent->rendermode );
|
|
||||||
|
|
||||||
if( ent->rendermode != kRenderNormal )
|
return true;
|
||||||
{
|
|
||||||
MSG_WriteByte( msg, ent->renderamt );
|
|
||||||
MSG_WriteByte( msg, ent->rendercolor.r );
|
|
||||||
MSG_WriteByte( msg, ent->rendercolor.g );
|
|
||||||
MSG_WriteByte( msg, ent->rendercolor.b );
|
|
||||||
MSG_WriteByte( msg, ent->renderfx );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -541,7 +549,6 @@ Write all the static ents into demo
|
||||||
*/
|
*/
|
||||||
void SV_RestartStaticEnts( void )
|
void SV_RestartStaticEnts( void )
|
||||||
{
|
{
|
||||||
sv_static_entity_t *clent;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// remove all the static entities on the client
|
// remove all the static entities on the client
|
||||||
|
@ -549,10 +556,7 @@ void SV_RestartStaticEnts( void )
|
||||||
|
|
||||||
// resend them again
|
// resend them again
|
||||||
for( i = 0; i < sv.num_static_entities; i++ )
|
for( i = 0; i < sv.num_static_entities; i++ )
|
||||||
{
|
SV_CreateStaticEntity( &sv.reliable_datagram, i );
|
||||||
clent = &sv.static_entities[i];
|
|
||||||
SV_CreateStaticEntity( &sv.reliable_datagram, clent );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1835,42 +1839,18 @@ move entity to client
|
||||||
*/
|
*/
|
||||||
static void pfnMakeStatic( edict_t *ent )
|
static void pfnMakeStatic( edict_t *ent )
|
||||||
{
|
{
|
||||||
sv_static_entity_t *clent;
|
entity_state_t *state;
|
||||||
|
|
||||||
if( !SV_IsValidEdict( ent ))
|
if( !SV_IsValidEdict( ent ))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( sv.num_static_entities >= MAX_STATIC_ENTITIES )
|
// fill the entity state
|
||||||
{
|
state = &svs.static_entities[sv.num_static_entities]; // allocate a new one
|
||||||
if( !sv.static_ents_overflow )
|
svgame.dllFuncs.pfnCreateBaseline( false, NUM_FOR_EDICT( ent ), state, ent, 0, vec3_origin, vec3_origin );
|
||||||
{
|
state->messagenum = ent->v.model; // member modelname
|
||||||
Con_Printf( S_WARN "MAX_STATIC_ENTITIES limit exceeded (%d)\n", MAX_STATIC_ENTITIES );
|
|
||||||
sv.static_ents_overflow = true;
|
|
||||||
}
|
|
||||||
sv.ignored_static_ents++; // continue overflowed entities
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
clent = &sv.static_entities[sv.num_static_entities++];
|
if( SV_CreateStaticEntity( &sv.signon, sv.num_static_entities ))
|
||||||
|
sv.num_static_entities++;
|
||||||
Q_strncpy( clent->model, STRING( ent->v.model ), sizeof( clent->model ));
|
|
||||||
VectorCopy( ent->v.origin, clent->origin );
|
|
||||||
VectorCopy( ent->v.angles, clent->angles );
|
|
||||||
|
|
||||||
clent->sequence = ent->v.sequence;
|
|
||||||
clent->frame = ent->v.frame * 128;
|
|
||||||
clent->colormap = ent->v.colormap;
|
|
||||||
clent->skin = ent->v.skin;
|
|
||||||
clent->body = ent->v.body;
|
|
||||||
clent->scale = ent->v.scale;
|
|
||||||
clent->rendermode = ent->v.rendermode;
|
|
||||||
clent->renderamt = ent->v.renderamt;
|
|
||||||
clent->rendercolor.r = ent->v.rendercolor[0];
|
|
||||||
clent->rendercolor.g = ent->v.rendercolor[1];
|
|
||||||
clent->rendercolor.b = ent->v.rendercolor[2];
|
|
||||||
clent->renderfx = ent->v.renderfx;
|
|
||||||
|
|
||||||
SV_CreateStaticEntity( &sv.signon, clent );
|
|
||||||
|
|
||||||
// remove at end of the frame
|
// remove at end of the frame
|
||||||
SetBits( ent->v.flags, FL_KILLME );
|
SetBits( ent->v.flags, FL_KILLME );
|
||||||
|
@ -1986,31 +1966,31 @@ int SV_BuildSoundMsg( sizebuf_t *msg, edict_t *ent, int chan, const char *sample
|
||||||
|
|
||||||
if( vol < 0 || vol > 255 )
|
if( vol < 0 || vol > 255 )
|
||||||
{
|
{
|
||||||
Con_Printf( S_ERROR "SV_StartSound: volume = %i\n", vol );
|
Con_Reportf( S_ERROR "SV_StartSound: volume = %i\n", vol );
|
||||||
vol = bound( 0, vol, 255 );
|
vol = bound( 0, vol, 255 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( attn < 0.0f || attn > 4.0f )
|
if( attn < 0.0f || attn > 4.0f )
|
||||||
{
|
{
|
||||||
Con_Printf( S_ERROR "SV_StartSound: attenuation %g must be in range 0-4\n", attn );
|
Con_Reportf( S_ERROR "SV_StartSound: attenuation %g must be in range 0-4\n", attn );
|
||||||
attn = bound( 0.0f, attn, 4.0f );
|
attn = bound( 0.0f, attn, 4.0f );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( chan < 0 || chan > 7 )
|
if( chan < 0 || chan > 7 )
|
||||||
{
|
{
|
||||||
Con_Printf( S_ERROR "SV_StartSound: channel must be in range 0-7\n" );
|
Con_Reportf( S_ERROR "SV_StartSound: channel must be in range 0-7\n" );
|
||||||
chan = bound( 0, chan, 7 );
|
chan = bound( 0, chan, 7 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( pitch < 0 || pitch > 255 )
|
if( pitch < 0 || pitch > 255 )
|
||||||
{
|
{
|
||||||
Con_Printf( S_ERROR "SV_StartSound: pitch = %i\n", pitch );
|
Con_Reportf( S_ERROR "SV_StartSound: pitch = %i\n", pitch );
|
||||||
pitch = bound( 0, pitch, 255 );
|
pitch = bound( 0, pitch, 255 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !COM_CheckString( sample ))
|
if( !COM_CheckString( sample ))
|
||||||
{
|
{
|
||||||
Con_Printf( S_ERROR "SV_StartSound: passed NULL sample\n" );
|
Con_Reportf( S_ERROR "SV_StartSound: passed NULL sample\n" );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4744,6 +4724,7 @@ void SV_UnloadProgs( void )
|
||||||
Cvar_FullSet( "sv_background", "0", FCVAR_READ_ONLY );
|
Cvar_FullSet( "sv_background", "0", FCVAR_READ_ONLY );
|
||||||
|
|
||||||
// free entity baselines
|
// free entity baselines
|
||||||
|
Z_Free( svs.static_entities );
|
||||||
Z_Free( svs.baselines );
|
Z_Free( svs.baselines );
|
||||||
svs.baselines = NULL;
|
svs.baselines = NULL;
|
||||||
|
|
||||||
|
@ -4872,6 +4853,7 @@ qboolean SV_LoadProgs( const char *name )
|
||||||
svgame.globals->maxEntities = GI->max_edicts;
|
svgame.globals->maxEntities = GI->max_edicts;
|
||||||
svgame.globals->maxClients = svs.maxclients;
|
svgame.globals->maxClients = svs.maxclients;
|
||||||
svgame.edicts = Mem_Calloc( svgame.mempool, sizeof( edict_t ) * GI->max_edicts );
|
svgame.edicts = Mem_Calloc( svgame.mempool, sizeof( edict_t ) * GI->max_edicts );
|
||||||
|
svs.static_entities = Z_Calloc( sizeof( entity_state_t ) * MAX_STATIC_ENTITIES );
|
||||||
svs.baselines = Z_Calloc( sizeof( entity_state_t ) * GI->max_edicts );
|
svs.baselines = Z_Calloc( sizeof( entity_state_t ) * GI->max_edicts );
|
||||||
svgame.numEntities = svs.maxclients + 1; // clients + world
|
svgame.numEntities = svs.maxclients + 1; // clients + world
|
||||||
|
|
||||||
|
|
|
@ -378,7 +378,7 @@ void SV_CreateBaseline( void )
|
||||||
{
|
{
|
||||||
entity_state_t nullstate, *base;
|
entity_state_t nullstate, *base;
|
||||||
int playermodel;
|
int playermodel;
|
||||||
qboolean player;
|
int delta_type;
|
||||||
int entnum;
|
int entnum;
|
||||||
|
|
||||||
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
||||||
|
@ -396,13 +396,13 @@ void SV_CreateBaseline( void )
|
||||||
|
|
||||||
if( entnum != 0 && entnum <= svs.maxclients )
|
if( entnum != 0 && entnum <= svs.maxclients )
|
||||||
{
|
{
|
||||||
player = true;
|
delta_type = DELTA_PLAYER;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( !pEdict->v.modelindex )
|
if( !pEdict->v.modelindex )
|
||||||
continue; // invisible
|
continue; // invisible
|
||||||
player = false;
|
delta_type = DELTA_ENTITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// take current state as baseline
|
// take current state as baseline
|
||||||
|
@ -415,7 +415,7 @@ void SV_CreateBaseline( void )
|
||||||
base->entityType = ENTITY_BEAM;
|
base->entityType = ENTITY_BEAM;
|
||||||
else base->entityType = ENTITY_NORMAL;
|
else base->entityType = ENTITY_NORMAL;
|
||||||
|
|
||||||
svgame.dllFuncs.pfnCreateBaseline( player, entnum, base, pEdict, playermodel, host.player_mins[0], host.player_maxs[0] );
|
svgame.dllFuncs.pfnCreateBaseline( delta_type, entnum, base, pEdict, playermodel, host.player_mins[0], host.player_maxs[0] );
|
||||||
sv.last_valid_baseline = entnum;
|
sv.last_valid_baseline = entnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,19 +434,19 @@ void SV_CreateBaseline( void )
|
||||||
|
|
||||||
if( entnum != 0 && entnum <= svs.maxclients )
|
if( entnum != 0 && entnum <= svs.maxclients )
|
||||||
{
|
{
|
||||||
player = true;
|
delta_type = DELTA_PLAYER;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( !pEdict->v.modelindex )
|
if( !pEdict->v.modelindex )
|
||||||
continue; // invisible
|
continue; // invisible
|
||||||
player = false;
|
delta_type = DELTA_ENTITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// take current state as baseline
|
// take current state as baseline
|
||||||
base = &svs.baselines[entnum];
|
base = &svs.baselines[entnum];
|
||||||
|
|
||||||
MSG_WriteDeltaEntity( &nullstate, base, &sv.signon, true, player, 1.0f, 0 );
|
MSG_WriteDeltaEntity( &nullstate, base, &sv.signon, true, delta_type, 1.0f, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
MSG_WriteUBitLong( &sv.signon, LAST_EDICT, MAX_ENTITY_BITS ); // end of baselines
|
MSG_WriteUBitLong( &sv.signon, LAST_EDICT, MAX_ENTITY_BITS ); // end of baselines
|
||||||
|
@ -455,7 +455,7 @@ void SV_CreateBaseline( void )
|
||||||
for( entnum = 0; entnum < sv.num_instanced; entnum++ )
|
for( entnum = 0; entnum < sv.num_instanced; entnum++ )
|
||||||
{
|
{
|
||||||
base = &sv.instanced[entnum].baseline;
|
base = &sv.instanced[entnum].baseline;
|
||||||
MSG_WriteDeltaEntity( &nullstate, base, &sv.signon, true, false, 1.0f, 0 );
|
MSG_WriteDeltaEntity( &nullstate, base, &sv.signon, true, DELTA_ENTITY, 1.0f, 0 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -783,6 +783,7 @@ qboolean SV_SpawnServer( const char *mapname, const char *startspot, qboolean ba
|
||||||
MSG_Init( &sv.spec_datagram, "Spectator Datagram", sv.spectator_buf, sizeof( sv.spectator_buf ));
|
MSG_Init( &sv.spec_datagram, "Spectator Datagram", sv.spectator_buf, sizeof( sv.spectator_buf ));
|
||||||
|
|
||||||
// clearing all the baselines
|
// clearing all the baselines
|
||||||
|
memset( svs.static_entities, 0, sizeof( entity_state_t ) * MAX_STATIC_ENTITIES );
|
||||||
memset( svs.baselines, 0, sizeof( entity_state_t ) * GI->max_edicts );
|
memset( svs.baselines, 0, sizeof( entity_state_t ) * GI->max_edicts );
|
||||||
|
|
||||||
// make cvars consistant
|
// make cvars consistant
|
||||||
|
|
|
@ -158,7 +158,7 @@ void SV_UpdateMovevars( qboolean initialize )
|
||||||
if( sv_zmax.value < 256.0f ) Cvar_SetValue( "sv_zmax", 256.0f );
|
if( sv_zmax.value < 256.0f ) Cvar_SetValue( "sv_zmax", 256.0f );
|
||||||
|
|
||||||
// clamp it right
|
// clamp it right
|
||||||
if( host.features & ENGINE_WRITE_LARGE_COORD )
|
if( FBitSet( host.features, ENGINE_WRITE_LARGE_COORD ))
|
||||||
{
|
{
|
||||||
if( sv_zmax.value > 131070.0f )
|
if( sv_zmax.value > 131070.0f )
|
||||||
Cvar_SetValue( "sv_zmax", 131070.0f );
|
Cvar_SetValue( "sv_zmax", 131070.0f );
|
||||||
|
@ -599,7 +599,7 @@ void Host_ServerFrame( void )
|
||||||
// if server is not active, do nothing
|
// if server is not active, do nothing
|
||||||
if( !svs.initialized ) return;
|
if( !svs.initialized ) return;
|
||||||
|
|
||||||
if( sv.simulating || sv.state != ss_active )
|
if( sv_fps.value != 0.0f && ( sv.simulating || sv.state != ss_active ))
|
||||||
sv.time_residual += host.frametime;
|
sv.time_residual += host.frametime;
|
||||||
|
|
||||||
if( sv_fps.value == 0.0f )
|
if( sv_fps.value == 0.0f )
|
||||||
|
|
|
@ -30,7 +30,7 @@ half-life implementation of saverestore system
|
||||||
#define SAVEFILE_HEADER (('V'<<24)+('L'<<16)+('A'<<8)+'V') // little-endian "VALV"
|
#define SAVEFILE_HEADER (('V'<<24)+('L'<<16)+('A'<<8)+'V') // little-endian "VALV"
|
||||||
#define SAVEGAME_HEADER (('V'<<24)+('A'<<16)+('S'<<8)+'J') // little-endian "JSAV"
|
#define SAVEGAME_HEADER (('V'<<24)+('A'<<16)+('S'<<8)+'J') // little-endian "JSAV"
|
||||||
#define SAVEGAME_VERSION 0x0071 // Version 0.71 GoldSrc compatible
|
#define SAVEGAME_VERSION 0x0071 // Version 0.71 GoldSrc compatible
|
||||||
#define CLIENT_SAVEGAME_VERSION 0x0065 // Version 0.65
|
#define CLIENT_SAVEGAME_VERSION 0x0067 // Version 0.67
|
||||||
|
|
||||||
#define SAVE_HEAPSIZE 0x400000 // reserve 4Mb for now
|
#define SAVE_HEAPSIZE 0x400000 // reserve 4Mb for now
|
||||||
#define SAVE_HASHSTRINGS 0xFFF // 4095 unique strings
|
#define SAVE_HASHSTRINGS 0xFFF // 4095 unique strings
|
||||||
|
@ -160,19 +160,40 @@ static TYPEDESCRIPTION gDecalEntry[] =
|
||||||
|
|
||||||
static TYPEDESCRIPTION gStaticEntry[] =
|
static TYPEDESCRIPTION gStaticEntry[] =
|
||||||
{
|
{
|
||||||
DEFINE_ARRAY( sv_static_entity_t, model, FIELD_CHARACTER, 64 ),
|
DEFINE_FIELD( entity_state_t, messagenum, FIELD_MODELNAME ), // HACKHACK: store model into messagenum
|
||||||
DEFINE_FIELD( sv_static_entity_t, origin, FIELD_VECTOR ),
|
DEFINE_FIELD( entity_state_t, origin, FIELD_VECTOR ),
|
||||||
DEFINE_FIELD( sv_static_entity_t, angles, FIELD_VECTOR ),
|
DEFINE_FIELD( entity_state_t, angles, FIELD_VECTOR ),
|
||||||
DEFINE_FIELD( sv_static_entity_t, sequence, FIELD_SHORT ),
|
DEFINE_FIELD( entity_state_t, sequence, FIELD_INTEGER ),
|
||||||
DEFINE_FIELD( sv_static_entity_t, frame, FIELD_SHORT ),
|
DEFINE_FIELD( entity_state_t, frame, FIELD_FLOAT ),
|
||||||
DEFINE_FIELD( sv_static_entity_t, colormap, FIELD_SHORT ),
|
DEFINE_FIELD( entity_state_t, colormap, FIELD_INTEGER ),
|
||||||
DEFINE_FIELD( sv_static_entity_t, skin, FIELD_CHARACTER ),
|
DEFINE_FIELD( entity_state_t, skin, FIELD_SHORT ),
|
||||||
DEFINE_FIELD( sv_static_entity_t, body, FIELD_CHARACTER ),
|
DEFINE_FIELD( entity_state_t, body, FIELD_INTEGER ),
|
||||||
DEFINE_FIELD( sv_static_entity_t, scale, FIELD_FLOAT ),
|
DEFINE_FIELD( entity_state_t, scale, FIELD_FLOAT ),
|
||||||
DEFINE_FIELD( sv_static_entity_t, rendermode, FIELD_CHARACTER ),
|
DEFINE_FIELD( entity_state_t, effects, FIELD_INTEGER ),
|
||||||
DEFINE_FIELD( sv_static_entity_t, renderamt, FIELD_CHARACTER ),
|
DEFINE_FIELD( entity_state_t, framerate, FIELD_FLOAT ),
|
||||||
DEFINE_ARRAY( sv_static_entity_t, rendercolor, FIELD_CHARACTER, sizeof( color24 )),
|
DEFINE_FIELD( entity_state_t, mins, FIELD_VECTOR ),
|
||||||
DEFINE_FIELD( sv_static_entity_t, renderfx, FIELD_CHARACTER ),
|
DEFINE_FIELD( entity_state_t, maxs, FIELD_VECTOR ),
|
||||||
|
DEFINE_FIELD( entity_state_t, rendermode, FIELD_INTEGER ),
|
||||||
|
DEFINE_FIELD( entity_state_t, renderamt, FIELD_FLOAT ),
|
||||||
|
DEFINE_ARRAY( entity_state_t, rendercolor, FIELD_CHARACTER, sizeof( color24 )),
|
||||||
|
DEFINE_FIELD( entity_state_t, renderfx, FIELD_INTEGER ),
|
||||||
|
DEFINE_FIELD( entity_state_t, controller, FIELD_INTEGER ),
|
||||||
|
DEFINE_FIELD( entity_state_t, blending, FIELD_INTEGER ),
|
||||||
|
DEFINE_FIELD( entity_state_t, solid, FIELD_SHORT ),
|
||||||
|
DEFINE_FIELD( entity_state_t, animtime, FIELD_TIME ),
|
||||||
|
DEFINE_FIELD( entity_state_t, movetype, FIELD_INTEGER ),
|
||||||
|
DEFINE_FIELD( entity_state_t, vuser1, FIELD_VECTOR ),
|
||||||
|
DEFINE_FIELD( entity_state_t, vuser2, FIELD_VECTOR ),
|
||||||
|
DEFINE_FIELD( entity_state_t, vuser3, FIELD_VECTOR ),
|
||||||
|
DEFINE_FIELD( entity_state_t, vuser4, FIELD_VECTOR ),
|
||||||
|
DEFINE_FIELD( entity_state_t, iuser1, FIELD_INTEGER ),
|
||||||
|
DEFINE_FIELD( entity_state_t, iuser2, FIELD_INTEGER ),
|
||||||
|
DEFINE_FIELD( entity_state_t, iuser3, FIELD_INTEGER ),
|
||||||
|
DEFINE_FIELD( entity_state_t, iuser4, FIELD_INTEGER ),
|
||||||
|
DEFINE_FIELD( entity_state_t, fuser1, FIELD_FLOAT ),
|
||||||
|
DEFINE_FIELD( entity_state_t, fuser2, FIELD_FLOAT ),
|
||||||
|
DEFINE_FIELD( entity_state_t, fuser3, FIELD_FLOAT ),
|
||||||
|
DEFINE_FIELD( entity_state_t, fuser4, FIELD_FLOAT ),
|
||||||
};
|
};
|
||||||
|
|
||||||
static TYPEDESCRIPTION gSoundEntry[] =
|
static TYPEDESCRIPTION gSoundEntry[] =
|
||||||
|
@ -1145,7 +1166,7 @@ static void SaveClientState( SAVERESTOREDATA *pSaveData, const char *level, int
|
||||||
|
|
||||||
// write client entities
|
// write client entities
|
||||||
for( i = 0; i < header.entityCount; i++ )
|
for( i = 0; i < header.entityCount; i++ )
|
||||||
svgame.dllFuncs.pfnSaveWriteFields( pSaveData, "STATICENTITY", &sv.static_entities[i], gStaticEntry, ARRAYSIZE( gStaticEntry ));
|
svgame.dllFuncs.pfnSaveWriteFields( pSaveData, "STATICENTITY", &svs.static_entities[i], gStaticEntry, ARRAYSIZE( gStaticEntry ));
|
||||||
|
|
||||||
// write sounds
|
// write sounds
|
||||||
for( i = 0; i < header.soundCount; i++ )
|
for( i = 0; i < header.soundCount; i++ )
|
||||||
|
@ -1188,7 +1209,6 @@ static void LoadClientState( SAVERESTOREDATA *pSaveData, const char *level, qboo
|
||||||
int i, size, id, version;
|
int i, size, id, version;
|
||||||
sv_client_t *cl = svs.clients;
|
sv_client_t *cl = svs.clients;
|
||||||
char name[MAX_QPATH];
|
char name[MAX_QPATH];
|
||||||
sv_static_entity_t staticEntry;
|
|
||||||
soundlist_t soundEntry;
|
soundlist_t soundEntry;
|
||||||
decallist_t decalEntry;
|
decallist_t decalEntry;
|
||||||
SAVE_CLIENT header;
|
SAVE_CLIENT header;
|
||||||
|
@ -1248,21 +1268,18 @@ static void LoadClientState( SAVERESTOREDATA *pSaveData, const char *level, qboo
|
||||||
// clear old entities
|
// clear old entities
|
||||||
if( !adjacent )
|
if( !adjacent )
|
||||||
{
|
{
|
||||||
memset( sv.static_entities, 0, sizeof( sv.static_entities ));
|
memset( svs.static_entities, 0, sizeof( entity_state_t ) * MAX_STATIC_ENTITIES );
|
||||||
sv.num_static_entities = 0;
|
sv.num_static_entities = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore client entities
|
// restore client entities
|
||||||
for( i = 0; i < header.entityCount; i++ )
|
for( i = 0; i < header.entityCount; i++ )
|
||||||
{
|
{
|
||||||
svgame.dllFuncs.pfnSaveReadFields( pSaveData, "STATICENTITY", &staticEntry, gStaticEntry, ARRAYSIZE( gStaticEntry ));
|
id = sv.num_static_entities;
|
||||||
|
svgame.dllFuncs.pfnSaveReadFields( pSaveData, "STATICENTITY", &svs.static_entities[id], gStaticEntry, ARRAYSIZE( gStaticEntry ));
|
||||||
if( adjacent ) continue; // static entities won't loading from adjacent levels
|
if( adjacent ) continue; // static entities won't loading from adjacent levels
|
||||||
|
|
||||||
if( i >= MAX_STATIC_ENTITIES )
|
if( SV_CreateStaticEntity( &sv.signon, id ))
|
||||||
continue; // silently overflowed
|
|
||||||
|
|
||||||
SV_CreateStaticEntity( &sv.signon, &staticEntry );
|
|
||||||
sv.static_entities[i] = staticEntry;
|
|
||||||
sv.num_static_entities++;
|
sv.num_static_entities++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1558,7 +1575,7 @@ static int LoadGameState( char const *level, qboolean changelevel )
|
||||||
|
|
||||||
if( pent != NULL )
|
if( pent != NULL )
|
||||||
{
|
{
|
||||||
if( svgame.dllFuncs.pfnRestore( pent, pSaveData, false ) < 0 )
|
if( svgame.dllFuncs.pfnRestore( pent, pSaveData, 0 ) < 0 )
|
||||||
{
|
{
|
||||||
SetBits( pent->v.flags, FL_KILLME );
|
SetBits( pent->v.flags, FL_KILLME );
|
||||||
pTable->pent = NULL;
|
pTable->pent = NULL;
|
||||||
|
|
Loading…
Add table
Reference in a new issue