mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 11:35:05 +08:00
Compare commits
61 Commits
continuous
...
continuous
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
215feb3ba9 | ||
|
|
150e2607d9 | ||
|
|
e8452c68d7 | ||
|
|
7fe0aba71c | ||
|
|
adcc9eb0df | ||
|
|
081d1da640 | ||
|
|
4aadea40a3 | ||
|
|
8deea9dc7e | ||
|
|
d650d8c271 | ||
|
|
eb89c8b222 | ||
|
|
659ffc4519 | ||
|
|
63a63a52de | ||
|
|
e082d76a45 | ||
|
|
cb8e2a4f9f | ||
|
|
5f55930cb7 | ||
|
|
dd03723144 | ||
|
|
26f07196ea | ||
|
|
8c291fdfe3 | ||
|
|
d1e118f07c | ||
|
|
6c531c14e6 | ||
|
|
433213c915 | ||
|
|
ab0c0b18c2 | ||
|
|
29fd5f9fbe | ||
|
|
882d8afc93 | ||
|
|
e11635d15c | ||
|
|
5d79d93aac | ||
|
|
7ccf651fd0 | ||
|
|
67af41cce8 | ||
|
|
e2c96e62e1 | ||
|
|
2ecae442fc | ||
|
|
a1060b0eb5 | ||
|
|
ddd8de888f | ||
|
|
a758dffbc1 | ||
|
|
87775faeca | ||
|
|
ef0fc46ed8 | ||
|
|
138b4fa247 | ||
|
|
47d1f3459c | ||
|
|
4712aae834 | ||
|
|
2900ee1cde | ||
|
|
c6c4178dd2 | ||
|
|
a3ce0e6b1b | ||
|
|
0b1ad3b7f0 | ||
|
|
37fb46f092 | ||
|
|
bc8bf9a9fb | ||
|
|
9e28c98911 | ||
|
|
0a1269d52d | ||
|
|
2e5bc31c9e | ||
|
|
1b335fd945 | ||
|
|
0c8b2d007a | ||
|
|
9ee1b32e2d | ||
|
|
953ad98a16 | ||
|
|
1357057bd8 | ||
|
|
35c9323de6 | ||
|
|
13a0afef06 | ||
|
|
c7ad8e4bf6 | ||
|
|
f1754bdd5f | ||
|
|
c462a1c500 | ||
|
|
0bba184994 | ||
|
|
178602ea1f | ||
|
|
2eb8f88a20 | ||
|
|
96d11df06c |
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -19,3 +19,6 @@
|
||||
[submodule "3rdparty/xash-extras"]
|
||||
path = 3rdparty/extras/xash-extras
|
||||
url = https://github.com/FWGS/xash-extras
|
||||
[submodule "3rdparty/bzip2/bzip2"]
|
||||
path = 3rdparty/bzip2/bzip2
|
||||
url = https://gitlab.com/bzip2/bzip2
|
||||
|
||||
1
3rdparty/bzip2/bzip2
vendored
Submodule
1
3rdparty/bzip2/bzip2
vendored
Submodule
Submodule 3rdparty/bzip2/bzip2 added at 66c46b8c94
35
3rdparty/bzip2/wscript
vendored
Normal file
35
3rdparty/bzip2/wscript
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
BZIP_CHECK='''#include <bzlib.h>
|
||||
int main(void) { return BZ2_bzlibVersion() != NULL; }
|
||||
'''
|
||||
|
||||
def options(opt):
|
||||
pass
|
||||
|
||||
def configure(conf):
|
||||
conf.define('_GNU_SOURCE', 1)
|
||||
|
||||
if conf.env.DEST_OS == 'win32':
|
||||
conf.define('BZ_LCCWIN32', 1)
|
||||
else:
|
||||
conf.define('BZ_UNIX', 1)
|
||||
|
||||
def build(bld):
|
||||
bld(
|
||||
features = 'subst',
|
||||
source = 'bzip2/bz_version.h.in',
|
||||
target = 'bz_version.h',
|
||||
BZ_VERSION='1.1.0-fwgs'
|
||||
)
|
||||
|
||||
bld.stlib(
|
||||
source = bld.path.ant_glob(['bzip2/*.c']),
|
||||
target = 'bzip2',
|
||||
use = 'bz_version.h',
|
||||
features = 'c',
|
||||
includes = ['bzip2/', '.'],
|
||||
subsystem = bld.env.MSVC_SUBSYSTEM,
|
||||
export_includes = ['bzip2/']
|
||||
)
|
||||
@@ -14,3 +14,4 @@ When `-bugcomp` is specified with argument, it interpreted as flags separated wi
|
||||
| ------- | ----------- | ---------------------------- |
|
||||
| `peoei` | Reverts `pfnPEntityOfEntIndex` behavior to GoldSrc, where it returns NULL for last player due to incorrect player index comparison | * Counter-Strike: Condition Zero - Deleted Scenes |
|
||||
| `gsmrf` | Rewrites message at the moment when Game DLL attempts to write an internal engine message, usually specific to GoldSrc protocol. Right now only supports `svc_spawnstaticsound`, more messages added by request. | * MetaMod/AMXModX based mods |
|
||||
| `sp_attn_none` | Makes sounds with attenuation zero spatialized, i.e. have a stereo effect. | Possibly, every game that was made for GoldSrc. |
|
||||
|
||||
@@ -67,9 +67,9 @@ This repository contains our fork of HLSDK and restored source code for Half-Lif
|
||||
`$ sudo dpkg --add-architecture i386`
|
||||
* Install development tools
|
||||
* For 32-bit engine on amd64: \
|
||||
`$ sudo apt install build-essential gcc-multilib g++-multilib python libsdl2-dev:i386 libfontconfig-dev:i386 libfreetype6-dev:i386`
|
||||
`$ sudo apt install build-essential gcc-multilib g++-multilib python libsdl2-dev:i386 libfontconfig-dev:i386 libfreetype6-dev:i386 libopus-dev:i386 libbz2-dev:i386`
|
||||
* For everything else: \
|
||||
`$ sudo apt install build-essential python libsdl2-dev libfontconfig-dev libfreetype6-dev`
|
||||
`$ sudo apt install build-essential python libsdl2-dev libfontconfig-dev libfreetype6-dev libopus-dev libbz2-dev`
|
||||
* Clone this repostory:
|
||||
`$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`
|
||||
|
||||
|
||||
@@ -14,9 +14,6 @@
|
||||
****/
|
||||
#ifndef CONST_H
|
||||
#define CONST_H
|
||||
|
||||
#include <stddef.h> // ptrdiff_t
|
||||
|
||||
//
|
||||
// Constants shared by the engine and dlls
|
||||
// This header file included by engine files and DLL files.
|
||||
@@ -724,7 +721,7 @@ enum
|
||||
};
|
||||
|
||||
typedef int func_t;
|
||||
typedef ptrdiff_t string_t;
|
||||
typedef int string_t;
|
||||
|
||||
typedef unsigned short word;
|
||||
|
||||
|
||||
@@ -79,11 +79,22 @@ typedef uint64_t longtime_t;
|
||||
#define GAME_EXPORT
|
||||
#endif
|
||||
|
||||
#define MALLOC __attribute__(( malloc ))
|
||||
|
||||
// added in GCC 11
|
||||
#if __GNUC__ >= 11
|
||||
// might want to set noclone due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116893
|
||||
// but it's easier to not force mismatched-dealloc to error yet
|
||||
#define MALLOC_LIKE( x, y ) __attribute__(( malloc( x, y )))
|
||||
#else
|
||||
#define MALLOC_LIKE( x, y ) MALLOC
|
||||
#endif
|
||||
#define NORETURN __attribute__(( noreturn ))
|
||||
#define NONNULL __attribute__(( nonnull ))
|
||||
#define _format( x ) __attribute__(( format( printf, x, x + 1 )))
|
||||
#define ALLOC_CHECK( x ) __attribute__(( alloc_size( x )))
|
||||
#define NO_ASAN __attribute__(( no_sanitize( "address" )))
|
||||
#define WARN_UNUSED_RESULT __attribute__(( warn_unused_result ))
|
||||
#define RENAME_SYMBOL( x ) asm( x )
|
||||
#else
|
||||
#if defined( _MSC_VER )
|
||||
@@ -99,6 +110,9 @@ typedef uint64_t longtime_t;
|
||||
#define _format( x )
|
||||
#define ALLOC_CHECK( x )
|
||||
#define RENAME_SYMBOL( x )
|
||||
#define MALLOC
|
||||
#define MALLOC_LIKE( x, y )
|
||||
#define WARN_UNUSED_RESULT
|
||||
#endif
|
||||
|
||||
#if __GNUC__ >= 3
|
||||
|
||||
@@ -274,6 +274,13 @@ void CL_GenericShot_f( void )
|
||||
string checkname;
|
||||
int i;
|
||||
|
||||
// allow overriding screenshot by users request
|
||||
if( Cmd_Argc() > 1 )
|
||||
{
|
||||
Q_strncpy( cls.shotname, Cmd_Argv( 1 ), sizeof( cls.shotname ));
|
||||
break;
|
||||
}
|
||||
|
||||
if( type == scrshot_snapshot )
|
||||
{
|
||||
fmt = "../%s_%04d.png";
|
||||
|
||||
@@ -40,6 +40,8 @@ GNU General Public License for more details.
|
||||
#define IDEMOHEADER (('M'<<24)+('E'<<16)+('D'<<8)+'I') // little-endian "IDEM"
|
||||
#define DEMO_PROTOCOL 3
|
||||
|
||||
#define PROTOCOL_GOLDSRC_VERSION_DEMO (PROTOCOL_GOLDSRC_VERSION | (BIT( 7 ))) // should be 48, only to differentiate it from PROTOCOL_LEGACY_VERSION
|
||||
|
||||
const char *demo_cmd[dem_lastcmd+1] =
|
||||
{
|
||||
"dem_unknown",
|
||||
@@ -120,7 +122,7 @@ static int CL_GetDemoNetProtocol( connprotocol_t proto )
|
||||
case PROTO_QUAKE:
|
||||
return PROTOCOL_VERSION_QUAKE;
|
||||
case PROTO_GOLDSRC:
|
||||
return PROTOCOL_GOLDSRC_VERSION;
|
||||
return PROTOCOL_GOLDSRC_VERSION_DEMO;
|
||||
}
|
||||
|
||||
return PROTOCOL_VERSION;
|
||||
@@ -136,7 +138,7 @@ static connprotocol_t CL_GetProtocolFromDemo( int net_protocol )
|
||||
return PROTO_LEGACY;
|
||||
case PROTOCOL_VERSION_QUAKE:
|
||||
return PROTO_QUAKE;
|
||||
case PROTOCOL_GOLDSRC_VERSION:
|
||||
case PROTOCOL_GOLDSRC_VERSION_DEMO:
|
||||
return PROTO_GOLDSRC;
|
||||
}
|
||||
|
||||
@@ -706,7 +708,7 @@ static void CL_DemoStartPlayback( int mode )
|
||||
|
||||
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 );
|
||||
Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize, 0 );
|
||||
|
||||
memset( demo.cmds, 0, sizeof( demo.cmds ));
|
||||
demo.angle_position = 1;
|
||||
|
||||
@@ -380,7 +380,7 @@ CL_ParseReliableEvent
|
||||
|
||||
=============
|
||||
*/
|
||||
void CL_ParseReliableEvent( sizebuf_t *msg )
|
||||
void CL_ParseReliableEvent( sizebuf_t *msg, connprotocol_t proto )
|
||||
{
|
||||
int event_index;
|
||||
event_args_t nullargs, args;
|
||||
@@ -390,11 +390,19 @@ void CL_ParseReliableEvent( sizebuf_t *msg )
|
||||
|
||||
event_index = MSG_ReadUBitLong( msg, MAX_EVENT_BITS );
|
||||
|
||||
if( MSG_ReadOneBit( msg ))
|
||||
delay = (float)MSG_ReadWord( msg ) * (1.0f / 100.0f);
|
||||
|
||||
// reliable events not use delta-compression just null-compression
|
||||
MSG_ReadDeltaEvent( msg, &nullargs, &args );
|
||||
if( proto == PROTO_GOLDSRC )
|
||||
{
|
||||
Delta_ReadGSFields( msg, DT_EVENT_T, &nullargs, &args, 0.0f );
|
||||
if( MSG_ReadOneBit( msg ))
|
||||
delay = (float)MSG_ReadWord( msg ) * (1.0f / 100.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( MSG_ReadOneBit( msg ))
|
||||
delay = (float)MSG_ReadWord( msg ) * (1.0f / 100.0f);
|
||||
MSG_ReadDeltaEvent( msg, &nullargs, &args );
|
||||
}
|
||||
|
||||
if( args.entindex > 0 && args.entindex <= cl.maxclients )
|
||||
args.angles[PITCH] *= -3.0f;
|
||||
@@ -409,7 +417,7 @@ CL_ParseEvent
|
||||
|
||||
=============
|
||||
*/
|
||||
void CL_ParseEvent( sizebuf_t *msg )
|
||||
void CL_ParseEvent( sizebuf_t *msg, connprotocol_t proto )
|
||||
{
|
||||
int event_index;
|
||||
int i, num_events;
|
||||
@@ -417,24 +425,33 @@ void CL_ParseEvent( sizebuf_t *msg )
|
||||
event_args_t nullargs, args;
|
||||
entity_state_t *state;
|
||||
float delay;
|
||||
int entity_bits;
|
||||
|
||||
memset( &nullargs, 0, sizeof( nullargs ));
|
||||
memset( &args, 0, sizeof( args ));
|
||||
|
||||
num_events = MSG_ReadUBitLong( msg, 5 );
|
||||
|
||||
if( proto == PROTO_GOLDSRC )
|
||||
entity_bits = MAX_GOLDSRC_ENTITY_BITS;
|
||||
else if( proto == PROTO_LEGACY )
|
||||
entity_bits = MAX_LEGACY_ENTITY_BITS;
|
||||
else entity_bits = MAX_ENTITY_BITS;
|
||||
|
||||
// parse events queue
|
||||
for( i = 0 ; i < num_events; i++ )
|
||||
{
|
||||
event_index = MSG_ReadUBitLong( msg, MAX_EVENT_BITS );
|
||||
|
||||
if( MSG_ReadOneBit( msg ))
|
||||
packet_index = MSG_ReadUBitLong( msg, cls.legacymode ? MAX_LEGACY_ENTITY_BITS : MAX_ENTITY_BITS );
|
||||
packet_index = MSG_ReadUBitLong( msg, entity_bits );
|
||||
else packet_index = -1;
|
||||
|
||||
if( MSG_ReadOneBit( msg ))
|
||||
{
|
||||
MSG_ReadDeltaEvent( msg, &nullargs, &args );
|
||||
if( proto == PROTO_GOLDSRC )
|
||||
Delta_ReadGSFields( msg, DT_EVENT_T, &nullargs, &args, 0.0f );
|
||||
else MSG_ReadDeltaEvent( msg, &nullargs, &args );
|
||||
}
|
||||
|
||||
if( MSG_ReadOneBit( msg ))
|
||||
|
||||
@@ -669,9 +669,9 @@ FRAME PARSING
|
||||
|
||||
=========================================================================
|
||||
*/
|
||||
static qboolean CL_ParseEntityNumFromPacket( sizebuf_t *msg, int *newnum )
|
||||
static qboolean CL_ParseEntityNumFromPacket( sizebuf_t *msg, int *newnum, connprotocol_t proto )
|
||||
{
|
||||
if( cls.legacymode )
|
||||
if( proto == PROTO_LEGACY )
|
||||
{
|
||||
*newnum = MSG_ReadWord( msg );
|
||||
if( *newnum == 0 )
|
||||
@@ -694,7 +694,7 @@ CL_FlushEntityPacket
|
||||
Read and ignore whole entity packet.
|
||||
=================
|
||||
*/
|
||||
static void CL_FlushEntityPacket( sizebuf_t *msg )
|
||||
static void CL_FlushEntityPacket( sizebuf_t *msg, connprotocol_t proto )
|
||||
{
|
||||
int newnum;
|
||||
entity_state_t from, to;
|
||||
@@ -707,7 +707,7 @@ static void CL_FlushEntityPacket( sizebuf_t *msg )
|
||||
// read it all, but ignore it
|
||||
while( 1 )
|
||||
{
|
||||
if( !CL_ParseEntityNumFromPacket( msg, &newnum ))
|
||||
if( !CL_ParseEntityNumFromPacket( msg, &newnum, proto ))
|
||||
break; // done
|
||||
|
||||
if( MSG_CheckOverflow( msg ))
|
||||
@@ -717,6 +717,47 @@ static void CL_FlushEntityPacket( sizebuf_t *msg )
|
||||
}
|
||||
}
|
||||
|
||||
qboolean CL_ValidateDeltaPacket( uint oldpacket, frame_t *oldframe )
|
||||
{
|
||||
int subtracted = ( cls.netchan.incoming_sequence - oldpacket ) & 0xFF;
|
||||
|
||||
if( subtracted == 0 )
|
||||
{
|
||||
Con_NPrintf( 2, "^3Warning:^1 update too old\n^7\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( subtracted >= CL_UPDATE_MASK )
|
||||
{
|
||||
// we can't use this, it is too old
|
||||
Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if(( cls.next_client_entities - oldframe->first_entity ) > ( cls.num_client_entities - NUM_PACKET_ENTITIES ))
|
||||
{
|
||||
Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CL_UpdateOldEntNum( int oldindex, frame_t *oldframe, entity_state_t **oldent )
|
||||
{
|
||||
if( !oldframe )
|
||||
{
|
||||
*oldent = NULL;
|
||||
return MAX_ENTNUMBER;
|
||||
}
|
||||
|
||||
if( oldindex >= oldframe->num_entities )
|
||||
return MAX_ENTNUMBER;
|
||||
|
||||
*oldent = &cls.packet_entities[(oldframe->first_entity + oldindex) % cls.num_client_entities];
|
||||
return (*oldent)->number;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_DeltaEntity
|
||||
@@ -787,7 +828,7 @@ An svc_packetentities has just been parsed, deal with the
|
||||
rest of the data stream.
|
||||
==================
|
||||
*/
|
||||
int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
|
||||
int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta, connprotocol_t proto )
|
||||
{
|
||||
frame_t *newframe, *oldframe;
|
||||
int oldindex, newnum, oldnum;
|
||||
@@ -803,7 +844,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
|
||||
CL_WriteDemoJumpTime();
|
||||
|
||||
// sentinel count. save it for debug checking
|
||||
if( cls.legacymode )
|
||||
if( proto == PROTO_LEGACY )
|
||||
count = MSG_ReadWord( msg );
|
||||
else count = MSG_ReadUBitLong( msg, MAX_VISIBLE_PACKET_BITS ) + 1;
|
||||
|
||||
@@ -817,32 +858,12 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
|
||||
|
||||
if( delta )
|
||||
{
|
||||
int subtracted;
|
||||
|
||||
oldpacket = MSG_ReadByte( msg );
|
||||
subtracted = ( cls.netchan.incoming_sequence - oldpacket ) & 0xFF;
|
||||
|
||||
if( subtracted == 0 )
|
||||
{
|
||||
Con_NPrintf( 2, "^3Warning:^1 update too old\n^7\n" );
|
||||
CL_FlushEntityPacket( msg );
|
||||
return playerbytes;
|
||||
}
|
||||
|
||||
if( subtracted >= CL_UPDATE_MASK )
|
||||
{
|
||||
// we can't use this, it is too old
|
||||
Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" );
|
||||
CL_FlushEntityPacket( msg );
|
||||
return playerbytes;
|
||||
}
|
||||
|
||||
uint oldpacket = MSG_ReadByte( msg );
|
||||
oldframe = &cl.frames[oldpacket & CL_UPDATE_MASK];
|
||||
|
||||
if(( cls.next_client_entities - oldframe->first_entity ) > ( cls.num_client_entities - NUM_PACKET_ENTITIES ))
|
||||
if( !CL_ValidateDeltaPacket( oldpacket, oldframe ))
|
||||
{
|
||||
Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" );
|
||||
CL_FlushEntityPacket( msg );
|
||||
CL_FlushEntityPacket( msg, proto );
|
||||
return playerbytes;
|
||||
}
|
||||
}
|
||||
@@ -860,27 +881,11 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
|
||||
|
||||
oldent = NULL;
|
||||
oldindex = 0;
|
||||
|
||||
if( !oldframe )
|
||||
{
|
||||
oldnum = MAX_ENTNUMBER;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( oldindex >= oldframe->num_entities )
|
||||
{
|
||||
oldnum = MAX_ENTNUMBER;
|
||||
}
|
||||
else
|
||||
{
|
||||
oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
|
||||
oldnum = oldent->number;
|
||||
}
|
||||
}
|
||||
oldnum = CL_UpdateOldEntNum( oldindex, oldframe, &oldent );
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
if( !CL_ParseEntityNumFromPacket( msg, &newnum ))
|
||||
if( !CL_ParseEntityNumFromPacket( msg, &newnum, proto ))
|
||||
break; // done
|
||||
|
||||
if( MSG_CheckOverflow( msg ))
|
||||
@@ -892,17 +897,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
|
||||
{
|
||||
// one or more entities from the old packet are unchanged
|
||||
CL_DeltaEntity( msg, newframe, oldnum, oldent, false );
|
||||
oldindex++;
|
||||
|
||||
if( oldindex >= oldframe->num_entities )
|
||||
{
|
||||
oldnum = MAX_ENTNUMBER;
|
||||
}
|
||||
else
|
||||
{
|
||||
oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
|
||||
oldnum = oldent->number;
|
||||
}
|
||||
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
|
||||
}
|
||||
|
||||
if( oldnum == newnum )
|
||||
@@ -911,17 +906,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
|
||||
bufStart = MSG_GetNumBytesRead( msg );
|
||||
CL_DeltaEntity( msg, newframe, newnum, oldent, true );
|
||||
if( player ) playerbytes += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
oldindex++;
|
||||
|
||||
if( oldindex >= oldframe->num_entities )
|
||||
{
|
||||
oldnum = MAX_ENTNUMBER;
|
||||
}
|
||||
else
|
||||
{
|
||||
oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
|
||||
oldnum = oldent->number;
|
||||
}
|
||||
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -940,17 +925,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
|
||||
{
|
||||
// one or more entities from the old packet are unchanged
|
||||
CL_DeltaEntity( msg, newframe, oldnum, oldent, false );
|
||||
oldindex++;
|
||||
|
||||
if( oldindex >= oldframe->num_entities )
|
||||
{
|
||||
oldnum = MAX_ENTNUMBER;
|
||||
}
|
||||
else
|
||||
{
|
||||
oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
|
||||
oldnum = oldent->number;
|
||||
}
|
||||
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
|
||||
}
|
||||
|
||||
if( newframe->num_entities != count && newframe->num_entities != 0 )
|
||||
@@ -972,7 +947,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
|
||||
cls.signon = SIGNONS;
|
||||
|
||||
// Clear loading plaque.
|
||||
CL_SignonReply ();
|
||||
CL_SignonReply( proto );
|
||||
}
|
||||
|
||||
return playerbytes;
|
||||
|
||||
@@ -252,18 +252,18 @@ static int CL_AdjustXPos( float x, int width, int totalWidth )
|
||||
|
||||
if( x == -1 )
|
||||
{
|
||||
xPos = ( refState.width - width ) * 0.5f;
|
||||
xPos = ( clgame.scrInfo.iWidth - width ) * 0.5f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( x < 0 )
|
||||
xPos = (1.0f + x) * refState.width - totalWidth; // Alight right
|
||||
xPos = (1.0f + x) * clgame.scrInfo.iWidth - totalWidth; // Alight right
|
||||
else // align left
|
||||
xPos = x * refState.width;
|
||||
xPos = x * clgame.scrInfo.iWidth;
|
||||
}
|
||||
|
||||
if( xPos + width > refState.width )
|
||||
xPos = refState.width - width;
|
||||
if( xPos + width > clgame.scrInfo.iWidth )
|
||||
xPos = clgame.scrInfo.iWidth - width;
|
||||
else if( xPos < 0 )
|
||||
xPos = 0;
|
||||
|
||||
@@ -283,19 +283,19 @@ static int CL_AdjustYPos( float y, int height )
|
||||
|
||||
if( y == -1 ) // centered?
|
||||
{
|
||||
yPos = ( refState.height - height ) * 0.5f;
|
||||
yPos = ( clgame.scrInfo.iHeight - height ) * 0.5f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Alight bottom?
|
||||
if( y < 0 )
|
||||
yPos = (1.0f + y) * refState.height - height; // Alight bottom
|
||||
yPos = (1.0f + y) * clgame.scrInfo.iHeight - height; // Alight bottom
|
||||
else // align top
|
||||
yPos = y * refState.height;
|
||||
yPos = y * clgame.scrInfo.iHeight;
|
||||
}
|
||||
|
||||
if( yPos + height > refState.height )
|
||||
yPos = refState.height - height;
|
||||
if( yPos + height > clgame.scrInfo.iHeight )
|
||||
yPos = clgame.scrInfo.iHeight - height;
|
||||
else if( yPos < 0 )
|
||||
yPos = 0;
|
||||
|
||||
|
||||
@@ -170,6 +170,11 @@ int CL_IsDevOverviewMode( void )
|
||||
return 0;
|
||||
}
|
||||
|
||||
connprotocol_t CL_Protocol( void )
|
||||
{
|
||||
return cls.legacymode;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
CL_CheckClientState
|
||||
@@ -217,7 +222,7 @@ CL_SignonReply
|
||||
An svc_signonnum has been received, perform a client side setup
|
||||
=====================
|
||||
*/
|
||||
void CL_SignonReply( void )
|
||||
void CL_SignonReply( connprotocol_t proto )
|
||||
{
|
||||
// g-cont. my favorite message :-)
|
||||
Con_Reportf( "%s: %i\n", __func__, cls.signon );
|
||||
@@ -225,7 +230,7 @@ void CL_SignonReply( void )
|
||||
switch( cls.signon )
|
||||
{
|
||||
case 1:
|
||||
CL_ServerCommand( true, "begin" );
|
||||
CL_ServerCommand( true, proto == PROTO_GOLDSRC ? "sendents" : "begin" );
|
||||
if( host_developer.value >= DEV_EXTENDED )
|
||||
Mem_PrintStats();
|
||||
break;
|
||||
@@ -693,7 +698,13 @@ void CL_WriteUsercmd( sizebuf_t *msg, int from, int to )
|
||||
t = &cl.commands[to].cmd;
|
||||
|
||||
// write it into the buffer
|
||||
MSG_WriteDeltaUsercmd( msg, f, t );
|
||||
if( cls.legacymode == PROTO_GOLDSRC )
|
||||
{
|
||||
MSG_StartBitWriting( msg );
|
||||
Delta_WriteGSFields( msg, DT_USERCMD_T, f, t, 0.0f );
|
||||
MSG_EndBitWriting( msg );
|
||||
}
|
||||
else MSG_WriteDeltaUsercmd( msg, f, t );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -792,6 +803,9 @@ static void CL_WritePacket( void )
|
||||
// begin a client move command
|
||||
MSG_BeginClientCmd( &buf, clc_move );
|
||||
|
||||
if( cls.legacymode == PROTO_GOLDSRC )
|
||||
MSG_WriteByte( &buf, 0 );
|
||||
|
||||
// save the position for a checksum byte
|
||||
key = MSG_GetRealBytesWritten( &buf );
|
||||
MSG_WriteByte( &buf, 0 );
|
||||
@@ -829,8 +843,16 @@ static void CL_WritePacket( void )
|
||||
|
||||
// calculate a checksum over the move commands
|
||||
size = MSG_GetRealBytesWritten( &buf ) - key - 1;
|
||||
if( cls.legacymode == PROTO_GOLDSRC )
|
||||
{
|
||||
size = Q_min( size, 255 );
|
||||
buf.pData[key - 1] = size;
|
||||
}
|
||||
buf.pData[key] = CRC32_BlockSequence( buf.pData + key + 1, size, cls.netchan.outgoing_sequence );
|
||||
|
||||
if( cls.legacymode == PROTO_GOLDSRC )
|
||||
COM_Munge( buf.pData + key + 1, size, cls.netchan.outgoing_sequence );
|
||||
|
||||
// message we are constructing.
|
||||
i = cls.netchan.outgoing_sequence & CL_UPDATE_MASK;
|
||||
|
||||
@@ -1048,7 +1070,31 @@ static void CL_SendConnectPacket( void )
|
||||
Info_SetValueForKey( protinfo, "a", Q_buildarch(), sizeof( protinfo ) );
|
||||
}
|
||||
|
||||
if( cls.legacymode )
|
||||
if( cls.legacymode == PROTO_GOLDSRC )
|
||||
{
|
||||
byte send_buf[MAX_PRINT_MSG];
|
||||
byte steam_cert[512];
|
||||
sizebuf_t send;
|
||||
|
||||
protinfo[0] = 0;
|
||||
|
||||
memset( steam_cert, 0, sizeof( steam_cert ));
|
||||
|
||||
Info_SetValueForKey( protinfo, "prot", "3", sizeof( protinfo )); // steam auth type
|
||||
Info_SetValueForKey( protinfo, "raw", "steam", sizeof( protinfo ));
|
||||
Info_SetValueForKey( protinfo, "cdkey", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", sizeof( protinfo ));
|
||||
|
||||
Info_SetValueForStarKey( cls.userinfo, "*hltv", "0", sizeof( cls.userinfo ));
|
||||
|
||||
MSG_Init( &send, "GoldSrcConnect", send_buf, sizeof( send_buf ));
|
||||
MSG_WriteLong( &send, NET_HEADER_OUTOFBANDPACKET );
|
||||
MSG_WriteStringf( &send, "connect %i %i \"%s\" \"%s\"\n",
|
||||
PROTOCOL_GOLDSRC_VERSION, cls.challenge, protinfo, cls.userinfo );
|
||||
MSG_WriteBytes( &send, steam_cert, sizeof( steam_cert ));
|
||||
|
||||
NET_SendPacket( NS_CLIENT, MSG_GetNumBytesWritten( &send ), MSG_GetData( &send ), adr );
|
||||
}
|
||||
else if( cls.legacymode == PROTO_LEGACY )
|
||||
{
|
||||
// set related userinfo keys
|
||||
if( cl_dlmax.value >= 40000 || cl_dlmax.value < 100 )
|
||||
@@ -1147,7 +1193,7 @@ static void CL_CheckForResend( void )
|
||||
if(( host.realtime - cls.connect_time ) < resendTime )
|
||||
return;
|
||||
|
||||
res = NET_StringToAdrNB( cls.servername, &adr );
|
||||
res = NET_StringToAdrNB( cls.servername, &adr, false );
|
||||
|
||||
if( res == NET_EAI_NONAME )
|
||||
{
|
||||
@@ -1278,11 +1324,12 @@ static void CL_Connect_f( void )
|
||||
proto = PROTO_CURRENT;
|
||||
else if( !Q_strcmp( s, "legacy" ) || !Q_strcmp( s, "48" ))
|
||||
proto = PROTO_LEGACY;
|
||||
else if( !Q_strcmp( s, "goldsrc" ))
|
||||
proto = PROTO_GOLDSRC;
|
||||
else
|
||||
{
|
||||
// quake protocol only used for demos
|
||||
// goldsrc protocol is not supported yet
|
||||
Con_Printf( "Unknown protocol. Supported are: current, legacy\n" );
|
||||
Con_Printf( "Unknown protocol. Supported are: current, legacy, goldsrc\n" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1477,16 +1524,19 @@ static void CL_Reconnect( qboolean setup_netchan )
|
||||
{
|
||||
if( setup_netchan )
|
||||
{
|
||||
Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize );
|
||||
uint flags = 0;
|
||||
|
||||
if( cls.legacymode )
|
||||
if( cls.legacymode == PROTO_GOLDSRC )
|
||||
{
|
||||
SetBits( flags, NETCHAN_USE_MUNGE | NETCHAN_USE_BZIP2 | NETCHAN_GOLDSRC );
|
||||
}
|
||||
else if( cls.legacymode == PROTO_LEGACY )
|
||||
{
|
||||
unsigned int extensions = Q_atoi( Cmd_Argv( 1 ) );
|
||||
|
||||
if( extensions & NET_LEGACY_EXT_SPLIT )
|
||||
if( FBitSet( extensions, NET_LEGACY_EXT_SPLIT ))
|
||||
{
|
||||
// only enable incoming split for legacy mode
|
||||
cls.netchan.split = true;
|
||||
SetBits( flags, NETCHAN_USE_LEGACY_SPLIT );
|
||||
Con_Reportf( "^2NET_EXT_SPLIT enabled^7 (packet sizes is %d/%d)\n", (int)cl_dlmax.value, 65536 );
|
||||
}
|
||||
}
|
||||
@@ -1494,12 +1544,11 @@ static void CL_Reconnect( qboolean setup_netchan )
|
||||
{
|
||||
cls.extensions = Q_atoi( Info_ValueForKey( Cmd_Argv( 1 ), "ext" ));
|
||||
|
||||
if( cls.extensions & NET_EXT_SPLITSIZE )
|
||||
{
|
||||
if( FBitSet( cls.extensions, NET_EXT_SPLITSIZE ))
|
||||
Con_Reportf( "^2NET_EXT_SPLITSIZE enabled^7 (packet size is %d)\n", (int)cl_dlmax.value );
|
||||
}
|
||||
}
|
||||
|
||||
Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize, flags );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2047,7 +2096,7 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
||||
Con_Reportf( "%s: %s : %s\n", __func__, NET_AdrToString( from ), c );
|
||||
|
||||
// server connection
|
||||
if( !Q_strcmp( c, "client_connect" ))
|
||||
if( !Q_strcmp( c, "client_connect" ) || !Q_strcmp( c, S2C_CONNECTION ))
|
||||
{
|
||||
if( !CL_IsFromConnectingServer( from ))
|
||||
return;
|
||||
@@ -2169,7 +2218,7 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
||||
// ping from somewhere
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, from, "ack" );
|
||||
}
|
||||
else if( !Q_strcmp( c, "challenge" ))
|
||||
else if( !Q_strcmp( c, "challenge" ) || !Q_strcmp( c, S2C_CHALLENGE ))
|
||||
{
|
||||
// this message only used during connection
|
||||
// it doesn't make sense after client_connect
|
||||
@@ -2206,7 +2255,7 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
||||
// dropped the connection but it is still getting packets from us
|
||||
CL_Disconnect_f();
|
||||
}
|
||||
else if( !Q_strcmp( c, "errormsg" ))
|
||||
else if( !Q_strcmp( c, "errormsg" ) || c[0] == S2C_REJECT || c[0] == S2C_REJECT_BADPASSWORD )
|
||||
{
|
||||
char formatted_msg[MAX_VA_STRING];
|
||||
|
||||
@@ -2214,6 +2263,8 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
||||
return;
|
||||
|
||||
args = MSG_ReadString( msg );
|
||||
if( c[0] == S2C_REJECT || c[0] == S2C_REJECT_BADPASSWORD )
|
||||
args++; // skip one byte
|
||||
|
||||
Q_snprintf( formatted_msg, sizeof( formatted_msg ), "^3Server message^7\n%s", args );
|
||||
|
||||
@@ -2378,6 +2429,8 @@ static void CL_ReadNetMessage( void )
|
||||
parsefn = CL_ParseQuakeMessage;
|
||||
break;
|
||||
case PROTO_GOLDSRC:
|
||||
parsefn = CL_ParseGoldSrcServerMessage;
|
||||
break;
|
||||
default:
|
||||
ASSERT( 0 );
|
||||
return;
|
||||
@@ -2697,7 +2750,7 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
|
||||
MSG_Init( &msg, "Resource Registration", msg_buf, sizeof( msg_buf ));
|
||||
|
||||
if( CL_PrecacheResources( ))
|
||||
CL_RegisterResources( &msg );
|
||||
CL_RegisterResources( &msg, cls.legacymode );
|
||||
|
||||
if( MSG_GetNumBytesWritten( &msg ) > 0 )
|
||||
{
|
||||
|
||||
@@ -216,7 +216,7 @@ CL_ParseSignon
|
||||
|
||||
==================
|
||||
*/
|
||||
void CL_ParseSignon( sizebuf_t *msg )
|
||||
void CL_ParseSignon( sizebuf_t *msg, connprotocol_t proto )
|
||||
{
|
||||
int i = MSG_ReadByte( msg );
|
||||
|
||||
@@ -228,7 +228,7 @@ void CL_ParseSignon( sizebuf_t *msg )
|
||||
}
|
||||
|
||||
cls.signon = i;
|
||||
CL_SignonReply();
|
||||
CL_SignonReply( proto );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -304,7 +304,7 @@ CL_ParseStaticEntity
|
||||
static client entity
|
||||
==================
|
||||
*/
|
||||
static void CL_ParseStaticEntity( sizebuf_t *msg )
|
||||
void CL_ParseStaticEntity( sizebuf_t *msg )
|
||||
{
|
||||
int i, newnum;
|
||||
entity_state_t from, to;
|
||||
@@ -388,7 +388,6 @@ void CL_ParseStaticDecal( sizebuf_t *msg )
|
||||
{
|
||||
vec3_t origin;
|
||||
int decalIndex, entityIndex, modelIndex;
|
||||
cl_entity_t *ent = NULL;
|
||||
float scale;
|
||||
int flags;
|
||||
|
||||
@@ -532,7 +531,7 @@ void CL_BatchResourceRequest( qboolean initialize )
|
||||
{
|
||||
if( done_downloading && CL_PrecacheResources( ))
|
||||
{
|
||||
CL_RegisterResources( &msg );
|
||||
CL_RegisterResources( &msg, cls.legacymode );
|
||||
}
|
||||
|
||||
Netchan_CreateFragments( &cls.netchan, &msg );
|
||||
@@ -846,7 +845,7 @@ void CL_ParseFileTransferFailed( sizebuf_t *msg )
|
||||
CL_ParseServerData
|
||||
==================
|
||||
*/
|
||||
void CL_ParseServerData( sizebuf_t *msg, qboolean legacy )
|
||||
void CL_ParseServerData( sizebuf_t *msg, connprotocol_t proto )
|
||||
{
|
||||
char gamefolder[MAX_QPATH];
|
||||
string mapfile;
|
||||
@@ -856,7 +855,18 @@ void CL_ParseServerData( sizebuf_t *msg, qboolean legacy )
|
||||
|
||||
HPAK_CheckSize( hpk_custom_file.string );
|
||||
|
||||
Con_Reportf( "%s packet received.\n", legacy ? "Legacy serverdata" : "Serverdata" );
|
||||
switch( proto )
|
||||
{
|
||||
case PROTO_LEGACY:
|
||||
Con_Reportf( "Legacy serverdata packet received.\n" );
|
||||
break;
|
||||
case PROTO_GOLDSRC:
|
||||
Con_Reportf( "GoldSrc serverdata packet received.\n" );
|
||||
break;
|
||||
default:
|
||||
Con_Reportf( "Serverdata packet received.\n" );
|
||||
break;
|
||||
}
|
||||
|
||||
cls.timestart = Sys_DoubleTime();
|
||||
cls.demowaiting = false; // server is changed
|
||||
@@ -873,7 +883,7 @@ void CL_ParseServerData( sizebuf_t *msg, qboolean legacy )
|
||||
// parse protocol version number
|
||||
i = MSG_ReadLong( msg );
|
||||
|
||||
if( legacy )
|
||||
if( proto == PROTO_LEGACY || proto == PROTO_GOLDSRC ) // GoldSrc protocol version is 48, same as Xash3D 48
|
||||
{
|
||||
if( i != PROTOCOL_LEGACY_VERSION )
|
||||
Host_Error( "Server use invalid protocol (%i should be %i)\n", i, PROTOCOL_LEGACY_VERSION );
|
||||
@@ -886,40 +896,64 @@ void CL_ParseServerData( sizebuf_t *msg, qboolean legacy )
|
||||
|
||||
cl.servercount = MSG_ReadLong( msg );
|
||||
cl.checksum = MSG_ReadLong( msg );
|
||||
cl.playernum = MSG_ReadByte( msg );
|
||||
cl.maxclients = MSG_ReadByte( msg );
|
||||
clgame.maxEntities = MSG_ReadWord( msg );
|
||||
if( legacy )
|
||||
if( proto == PROTO_GOLDSRC )
|
||||
{
|
||||
clgame.maxEntities = bound( MIN_LEGACY_EDICTS, clgame.maxEntities, MAX_LEGACY_EDICTS );
|
||||
byte clientdllmd5[16];
|
||||
byte unused;
|
||||
|
||||
MSG_ReadBytes( msg, clientdllmd5, sizeof( clientdllmd5 ));
|
||||
cl.maxclients = MSG_ReadByte( msg );
|
||||
cl.playernum = MSG_ReadByte( msg );
|
||||
unused = MSG_ReadByte( msg ); // coop flag
|
||||
Q_strncpy( gamefolder, MSG_ReadString( msg ), sizeof( gamefolder ));
|
||||
MSG_ReadString( msg ); // hostname
|
||||
Q_strncpy( clgame.mapname, MSG_ReadString( msg ), sizeof( clgame.mapname ));
|
||||
MSG_ReadString( msg ); // mapcycle?????
|
||||
unused = MSG_ReadByte( msg ); // vac secure
|
||||
|
||||
background = false;
|
||||
clgame.maxEntities = GI->max_edicts + (( cl.maxclients - 1 ) * 15 );
|
||||
clgame.maxEntities = bound( MIN_LEGACY_EDICTS, clgame.maxEntities, MAX_GOLDSRC_EDICTS );
|
||||
clgame.maxModels = 512; // ???
|
||||
Q_strncpy( clgame.maptitle, clgame.mapname, sizeof( clgame.maptitle ));
|
||||
}
|
||||
else
|
||||
{
|
||||
clgame.maxEntities = bound( MIN_EDICTS, clgame.maxEntities, MAX_EDICTS );
|
||||
clgame.maxModels = MSG_ReadWord( msg );
|
||||
}
|
||||
Q_strncpy( clgame.mapname, MSG_ReadString( msg ), sizeof( clgame.mapname ));
|
||||
Q_strncpy( clgame.maptitle, MSG_ReadString( msg ), sizeof( clgame.maptitle ));
|
||||
background = MSG_ReadOneBit( msg );
|
||||
Q_strncpy( gamefolder, MSG_ReadString( msg ), sizeof( gamefolder ));
|
||||
Host_ValidateEngineFeatures( MSG_ReadDword( msg ));
|
||||
|
||||
if( !legacy )
|
||||
{
|
||||
// receive the player hulls
|
||||
for( i = 0; i < MAX_MAP_HULLS * 3; i++ )
|
||||
cl.playernum = MSG_ReadByte( msg );
|
||||
cl.maxclients = MSG_ReadByte( msg );
|
||||
clgame.maxEntities = MSG_ReadWord( msg );
|
||||
if( proto == PROTO_LEGACY )
|
||||
{
|
||||
host.player_mins[i/3][i%3] = MSG_ReadChar( msg );
|
||||
host.player_maxs[i/3][i%3] = MSG_ReadChar( msg );
|
||||
clgame.maxEntities = bound( MIN_LEGACY_EDICTS, clgame.maxEntities, MAX_LEGACY_EDICTS );
|
||||
clgame.maxModels = 512; // ???
|
||||
}
|
||||
else
|
||||
{
|
||||
clgame.maxEntities = bound( MIN_EDICTS, clgame.maxEntities, MAX_EDICTS );
|
||||
clgame.maxModels = MSG_ReadWord( msg );
|
||||
}
|
||||
Q_strncpy( clgame.mapname, MSG_ReadString( msg ), sizeof( clgame.mapname ));
|
||||
Q_strncpy( clgame.maptitle, MSG_ReadString( msg ), sizeof( clgame.maptitle ));
|
||||
background = MSG_ReadOneBit( msg );
|
||||
Q_strncpy( gamefolder, MSG_ReadString( msg ), sizeof( gamefolder ));
|
||||
Host_ValidateEngineFeatures( MSG_ReadDword( msg ));
|
||||
|
||||
if( proto == PROTO_LEGACY )
|
||||
{
|
||||
// receive the player hulls
|
||||
for( i = 0; i < MAX_MAP_HULLS * 3; i++ )
|
||||
{
|
||||
host.player_mins[i/3][i%3] = MSG_ReadChar( msg );
|
||||
host.player_maxs[i/3][i%3] = MSG_ReadChar( msg );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Q_snprintf( mapfile, sizeof( mapfile ), "maps/%s.bsp", clgame.mapname );
|
||||
if( CRC32_MapFile( &mapCRC, mapfile, cl.maxclients > 1 ))
|
||||
if( CRC32_MapFile( &cl.worldmapCRC, mapfile, cl.maxclients > 1 ))
|
||||
{
|
||||
// validate map checksum
|
||||
if( mapCRC != cl.checksum )
|
||||
if( cl.worldmapCRC != cl.checksum )
|
||||
{
|
||||
Con_Printf( S_ERROR "Your map [%s] differs from the server's.\n", clgame.mapname );
|
||||
CL_Disconnect_f(); // for local game, call EndGame
|
||||
@@ -1000,7 +1034,7 @@ void CL_ParseServerData( sizebuf_t *msg, qboolean legacy )
|
||||
COM_ClearCustomizationList( &cl.players[i].customdata, true );
|
||||
CL_CreateCustomizationList();
|
||||
|
||||
if( !legacy )
|
||||
if( proto != PROTO_LEGACY )
|
||||
{
|
||||
// request resources from server
|
||||
CL_ServerCommand( true, "sendres %i\n", cl.servercount );
|
||||
@@ -1018,7 +1052,7 @@ void CL_ParseServerData( sizebuf_t *msg, qboolean legacy )
|
||||
CL_ParseClientData
|
||||
===================
|
||||
*/
|
||||
void CL_ParseClientData( sizebuf_t *msg )
|
||||
void CL_ParseClientData( sizebuf_t *msg, connprotocol_t proto )
|
||||
{
|
||||
float parsecounttime;
|
||||
int i, j, command_ack;
|
||||
@@ -1152,7 +1186,9 @@ void CL_ParseClientData( sizebuf_t *msg )
|
||||
from_wd = nullwd;
|
||||
}
|
||||
|
||||
MSG_ReadClientData( msg, from_cd, to_cd, cl.mtime[0] );
|
||||
if( proto == PROTO_GOLDSRC )
|
||||
Delta_ReadGSFields( msg, DT_CLIENTDATA_T, from_cd, to_cd, cl.mtime[0] );
|
||||
else MSG_ReadClientData( msg, from_cd, to_cd, cl.mtime[0] );
|
||||
|
||||
for( i = 0; i < 64; i++ )
|
||||
{
|
||||
@@ -1160,9 +1196,11 @@ void CL_ParseClientData( sizebuf_t *msg )
|
||||
if( !MSG_ReadOneBit( msg )) break;
|
||||
|
||||
// read the weapon idx
|
||||
idx = MSG_ReadUBitLong( msg, cls.legacymode ? MAX_LEGACY_WEAPON_BITS : MAX_WEAPON_BITS );
|
||||
idx = MSG_ReadUBitLong( msg, proto == PROTO_LEGACY ? MAX_LEGACY_WEAPON_BITS : MAX_WEAPON_BITS );
|
||||
|
||||
MSG_ReadWeaponData( msg, &from_wd[idx], &to_wd[idx], cl.mtime[0] );
|
||||
if( proto == PROTO_GOLDSRC )
|
||||
Delta_ReadGSFields( msg, DT_WEAPONDATA_T, &from_wd[idx], &to_wd[idx], cl.mtime[0] );
|
||||
else MSG_ReadWeaponData( msg, &from_wd[idx], &to_wd[idx], cl.mtime[0] );
|
||||
}
|
||||
|
||||
// make a local copy of physinfo
|
||||
@@ -1179,55 +1217,87 @@ void CL_ParseClientData( sizebuf_t *msg )
|
||||
CL_ParseBaseline
|
||||
==================
|
||||
*/
|
||||
void CL_ParseBaseline( sizebuf_t *msg, qboolean legacy )
|
||||
void CL_ParseBaseline( sizebuf_t *msg, connprotocol_t proto )
|
||||
{
|
||||
int i, newnum;
|
||||
entity_state_t nullstate;
|
||||
qboolean player;
|
||||
cl_entity_t *ent;
|
||||
const entity_state_t nullstate = { 0 };
|
||||
|
||||
Delta_InitClient (); // finalize client delta's
|
||||
|
||||
memset( &nullstate, 0, sizeof( nullstate ));
|
||||
if( proto == PROTO_GOLDSRC )
|
||||
MSG_StartBitWriting( msg );
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
if( legacy )
|
||||
cl_entity_t *ent;
|
||||
qboolean player;
|
||||
int newnum;
|
||||
|
||||
if( proto == PROTO_LEGACY )
|
||||
{
|
||||
newnum = MSG_ReadWord( msg );
|
||||
}
|
||||
else if( proto == PROTO_GOLDSRC )
|
||||
{
|
||||
uint value = MSG_ReadWord( msg );
|
||||
|
||||
if( value == 0xffff ) break; // end of baselines
|
||||
|
||||
MSG_SeekToBit( msg, -16, SEEK_CUR );
|
||||
newnum = MSG_ReadUBitLong( msg, MAX_GOLDSRC_ENTITY_BITS );
|
||||
}
|
||||
else
|
||||
{
|
||||
newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
|
||||
if( newnum == LAST_EDICT ) break; // end of baselines
|
||||
}
|
||||
|
||||
player = CL_IsPlayerIndex( newnum );
|
||||
|
||||
if( newnum >= clgame.maxEntities )
|
||||
Host_Error( "%s: no free edicts\n", __func__ );
|
||||
|
||||
ent = CL_EDICT_NUM( newnum );
|
||||
memset( &ent->prevstate, 0, sizeof( ent->prevstate ));
|
||||
ent->prevstate = nullstate;
|
||||
ent->index = newnum;
|
||||
|
||||
MSG_ReadDeltaEntity( msg, &ent->prevstate, &ent->baseline, newnum, player, 1.0f );
|
||||
|
||||
if( legacy )
|
||||
if( proto == PROTO_GOLDSRC )
|
||||
{
|
||||
break; // only one baseline allowed in legacy protocol
|
||||
int type = MSG_ReadUBitLong( msg, 2 );
|
||||
int bits = MSG_GetNumBitsWritten( msg );
|
||||
int delta_type;
|
||||
|
||||
if( player ) delta_type = DT_ENTITY_STATE_PLAYER_T;
|
||||
else if( type != ENTITY_NORMAL ) delta_type = DT_CUSTOM_ENTITY_STATE_T;
|
||||
else delta_type = DT_ENTITY_STATE_T;
|
||||
|
||||
Delta_ReadGSFields( msg, delta_type, &ent->prevstate, &ent->baseline, 1.0f );
|
||||
}
|
||||
else MSG_ReadDeltaEntity( msg, &nullstate, &ent->baseline, newnum, player, 1.0f );
|
||||
|
||||
if( proto == PROTO_LEGACY )
|
||||
break; // only one baseline allowed in legacy protocol
|
||||
}
|
||||
|
||||
if( !legacy )
|
||||
if( proto != PROTO_LEGACY )
|
||||
{
|
||||
int i;
|
||||
|
||||
cl.instanced_baseline_count = MSG_ReadUBitLong( msg, 6 );
|
||||
|
||||
for( i = 0; i < cl.instanced_baseline_count; i++ )
|
||||
{
|
||||
newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
|
||||
MSG_ReadDeltaEntity( msg, &nullstate, &cl.instanced_baseline[i], newnum, false, 1.0f );
|
||||
if( proto == PROTO_GOLDSRC )
|
||||
Delta_ReadGSFields( msg, DT_ENTITY_STATE_T, &nullstate, &cl.instanced_baseline[i], 1.0f );
|
||||
else
|
||||
{
|
||||
int newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
|
||||
MSG_ReadDeltaEntity( msg, &nullstate, &cl.instanced_baseline[i], newnum, false, 1.0f );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( proto == PROTO_GOLDSRC )
|
||||
MSG_EndBitWriting( msg );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1235,15 +1305,16 @@ void CL_ParseBaseline( sizebuf_t *msg, qboolean legacy )
|
||||
CL_ParseLightStyle
|
||||
================
|
||||
*/
|
||||
void CL_ParseLightStyle( sizebuf_t *msg )
|
||||
void CL_ParseLightStyle( sizebuf_t *msg, connprotocol_t proto )
|
||||
{
|
||||
int style;
|
||||
const char *s;
|
||||
float f;
|
||||
float f = 0.0f;
|
||||
|
||||
style = MSG_ReadByte( msg );
|
||||
s = MSG_ReadString( msg );
|
||||
f = MSG_ReadFloat( msg );
|
||||
if( proto != PROTO_GOLDSRC )
|
||||
f = MSG_ReadFloat( msg );
|
||||
|
||||
CL_SetLightstyle( style, s, f );
|
||||
}
|
||||
@@ -1372,26 +1443,36 @@ CL_UpdateUserinfo
|
||||
collect userinfo from all players
|
||||
================
|
||||
*/
|
||||
void CL_UpdateUserinfo( sizebuf_t *msg, qboolean legacy )
|
||||
void CL_UpdateUserinfo( sizebuf_t *msg, connprotocol_t proto )
|
||||
{
|
||||
int slot, id;
|
||||
qboolean active;
|
||||
player_info_t *player;
|
||||
|
||||
slot = MSG_ReadUBitLong( msg, MAX_CLIENT_BITS );
|
||||
if( proto == PROTO_GOLDSRC )
|
||||
{
|
||||
slot = MSG_ReadByte( msg );
|
||||
id = MSG_ReadLong( msg );
|
||||
active = true;
|
||||
}
|
||||
else if( proto == PROTO_LEGACY )
|
||||
{
|
||||
slot = MSG_ReadUBitLong( msg, MAX_CLIENT_BITS );
|
||||
id = 0; // bogus
|
||||
active = MSG_ReadOneBit( msg ) ? true : false;
|
||||
}
|
||||
else
|
||||
{
|
||||
slot = MSG_ReadUBitLong( msg, MAX_CLIENT_BITS );
|
||||
id = MSG_ReadLong( msg ); // unique user ID
|
||||
active = MSG_ReadOneBit( msg ) ? true : false;
|
||||
}
|
||||
|
||||
if( slot >= MAX_CLIENTS )
|
||||
Host_Error( "%s: svc_updateuserinfo >= MAX_CLIENTS\n", __func__ );
|
||||
|
||||
player = &cl.players[slot];
|
||||
|
||||
if( !legacy )
|
||||
id = MSG_ReadLong( msg ); // unique user ID
|
||||
else
|
||||
id = 0; // bogus
|
||||
|
||||
active = MSG_ReadOneBit( msg ) ? true : false;
|
||||
|
||||
if( active )
|
||||
{
|
||||
Q_strncpy( player->userinfo, MSG_ReadString( msg ), sizeof( player->userinfo ));
|
||||
@@ -1400,7 +1481,7 @@ void CL_UpdateUserinfo( sizebuf_t *msg, qboolean legacy )
|
||||
player->topcolor = Q_atoi( Info_ValueForKey( player->userinfo, "topcolor" ));
|
||||
player->bottomcolor = Q_atoi( Info_ValueForKey( player->userinfo, "bottomcolor" ));
|
||||
player->spectator = Q_atoi( Info_ValueForKey( player->userinfo, "*hltv" ));
|
||||
if( !legacy )
|
||||
if( proto != PROTO_LEGACY )
|
||||
MSG_ReadBytes( msg, player->hashedcdkey, sizeof( player->hashedcdkey ));
|
||||
|
||||
if( slot == cl.playernum ) gameui.playerinfo = *player;
|
||||
@@ -1610,7 +1691,7 @@ CL_RegisterResources
|
||||
Clean up and move to next part of sequence.
|
||||
==================
|
||||
*/
|
||||
void CL_RegisterResources( sizebuf_t *msg )
|
||||
void CL_RegisterResources( sizebuf_t *msg, connprotocol_t proto )
|
||||
{
|
||||
model_t *mod;
|
||||
int i;
|
||||
@@ -1672,7 +1753,13 @@ void CL_RegisterResources( sizebuf_t *msg )
|
||||
// done with all resources, issue prespawn command.
|
||||
// Include server count in case server disconnects and changes level during d/l
|
||||
MSG_BeginClientCmd( msg, clc_stringcmd );
|
||||
MSG_WriteStringf( msg, "spawn %i", cl.servercount );
|
||||
if( proto == PROTO_GOLDSRC )
|
||||
{
|
||||
int32_t crc = cl.worldmapCRC;
|
||||
COM_Munge2((byte*)&crc, sizeof( crc ), ( 0xff - cl.servercount ) & 0xff );
|
||||
MSG_WriteStringf( msg, "spawn %i %i", cl.servercount, crc );
|
||||
}
|
||||
else MSG_WriteStringf( msg, "spawn %i", cl.servercount );
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1682,7 +1769,7 @@ void CL_RegisterResources( sizebuf_t *msg )
|
||||
}
|
||||
}
|
||||
|
||||
static void CL_ParseConsistencyInfo( sizebuf_t *msg )
|
||||
static void CL_ParseConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
|
||||
{
|
||||
int lastcheck;
|
||||
int delta;
|
||||
@@ -1710,7 +1797,7 @@ static void CL_ParseConsistencyInfo( sizebuf_t *msg )
|
||||
isdelta = MSG_ReadOneBit( msg );
|
||||
|
||||
if( isdelta ) delta = MSG_ReadUBitLong( msg, 5 ) + lastcheck;
|
||||
else delta = MSG_ReadUBitLong( msg, MAX_MODEL_BITS );
|
||||
else delta = MSG_ReadUBitLong( msg, proto == PROTO_GOLDSRC ? MAX_GOLDSRC_MODEL_BITS : MAX_MODEL_BITS );
|
||||
|
||||
skip = delta - lastcheck;
|
||||
|
||||
@@ -1747,12 +1834,12 @@ CL_ParseResourceList
|
||||
|
||||
==============
|
||||
*/
|
||||
static void CL_ParseResourceList( sizebuf_t *msg )
|
||||
void CL_ParseResourceList( sizebuf_t *msg, connprotocol_t proto )
|
||||
{
|
||||
resource_t *pResource;
|
||||
int i, total;
|
||||
|
||||
total = MSG_ReadUBitLong( msg, MAX_RESOURCE_BITS );
|
||||
total = MSG_ReadUBitLong( msg, proto == PROTO_GOLDSRC ? MAX_GOLDSRC_RESOURCE_BITS : MAX_RESOURCE_BITS );
|
||||
|
||||
for( i = 0; i < total; i++ )
|
||||
{
|
||||
@@ -1761,7 +1848,7 @@ static void CL_ParseResourceList( sizebuf_t *msg )
|
||||
|
||||
Q_strncpy( pResource->szFileName, MSG_ReadString( msg ), sizeof( pResource->szFileName ));
|
||||
pResource->nIndex = MSG_ReadUBitLong( msg, MAX_MODEL_BITS );
|
||||
pResource->nDownloadSize = MSG_ReadSBitLong( msg, 24 );
|
||||
pResource->nDownloadSize = MSG_ReadBitLong( msg, 24, proto != PROTO_GOLDSRC );
|
||||
pResource->ucFlags = MSG_ReadUBitLong( msg, 3 ) & ~RES_WASMISSING;
|
||||
|
||||
if( FBitSet( pResource->ucFlags, RES_CUSTOM ))
|
||||
@@ -1773,7 +1860,7 @@ static void CL_ParseResourceList( sizebuf_t *msg )
|
||||
CL_AddToResourceList( pResource, &cl.resourcesneeded );
|
||||
}
|
||||
|
||||
CL_ParseConsistencyInfo( msg );
|
||||
CL_ParseConsistencyInfo( msg, proto );
|
||||
|
||||
CL_StartResourceDownloading( "Verifying and downloading resources...\n", false );
|
||||
}
|
||||
@@ -1784,7 +1871,7 @@ CL_ParseVoiceInit
|
||||
|
||||
==================
|
||||
*/
|
||||
static void CL_ParseVoiceInit( sizebuf_t *msg )
|
||||
void CL_ParseVoiceInit( sizebuf_t *msg )
|
||||
{
|
||||
char *pszCodec = MSG_ReadString( msg );
|
||||
int quality = MSG_ReadByte( msg );
|
||||
@@ -1798,7 +1885,7 @@ CL_ParseVoiceData
|
||||
|
||||
==================
|
||||
*/
|
||||
static void CL_ParseVoiceData( sizebuf_t *msg )
|
||||
void CL_ParseVoiceData( sizebuf_t *msg )
|
||||
{
|
||||
int size, idx, frames;
|
||||
byte received[8192];
|
||||
@@ -2045,7 +2132,7 @@ CL_ParseExec
|
||||
Exec map/class specific configs
|
||||
==============
|
||||
*/
|
||||
static void CL_ParseExec( sizebuf_t *msg )
|
||||
void CL_ParseExec( sizebuf_t *msg )
|
||||
{
|
||||
qboolean is_class;
|
||||
int class_idx;
|
||||
@@ -2268,7 +2355,7 @@ void CL_ParseServerMessage( sizebuf_t *msg )
|
||||
Host_AbortCurrentFrame ();
|
||||
break;
|
||||
case svc_event:
|
||||
CL_ParseEvent( msg );
|
||||
CL_ParseEvent( msg, PROTO_CURRENT );
|
||||
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_changing:
|
||||
@@ -2343,19 +2430,19 @@ void CL_ParseServerMessage( sizebuf_t *msg )
|
||||
break;
|
||||
case svc_serverdata:
|
||||
Cbuf_Execute(); // make sure any stuffed commands are done
|
||||
CL_ParseServerData( msg, false );
|
||||
CL_ParseServerData( msg, PROTO_CURRENT );
|
||||
break;
|
||||
case svc_lightstyle:
|
||||
CL_ParseLightStyle( msg );
|
||||
CL_ParseLightStyle( msg, PROTO_CURRENT );
|
||||
break;
|
||||
case svc_updateuserinfo:
|
||||
CL_UpdateUserinfo( msg, false );
|
||||
CL_UpdateUserinfo( msg, PROTO_CURRENT );
|
||||
break;
|
||||
case svc_deltatable:
|
||||
Delta_ParseTableField( msg );
|
||||
break;
|
||||
case svc_clientdata:
|
||||
CL_ParseClientData( msg );
|
||||
CL_ParseClientData( msg, PROTO_CURRENT );
|
||||
cl.frames[cl.parsecountmod].graphdata.client += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_resource:
|
||||
@@ -2375,21 +2462,21 @@ void CL_ParseServerMessage( sizebuf_t *msg )
|
||||
CL_ParseStaticEntity( msg );
|
||||
break;
|
||||
case svc_event_reliable:
|
||||
CL_ParseReliableEvent( msg );
|
||||
CL_ParseReliableEvent( msg, PROTO_CURRENT );
|
||||
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_spawnbaseline:
|
||||
CL_ParseBaseline( msg, false );
|
||||
CL_ParseBaseline( msg, PROTO_CURRENT );
|
||||
break;
|
||||
case svc_temp_entity:
|
||||
CL_ParseTempEntity( msg );
|
||||
CL_ParseTempEntity( msg, PROTO_CURRENT );
|
||||
cl.frames[cl.parsecountmod].graphdata.tentities += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_setpause:
|
||||
cl.paused = ( MSG_ReadOneBit( msg ) != 0 );
|
||||
break;
|
||||
case svc_signonnum:
|
||||
CL_ParseSignon( msg );
|
||||
CL_ParseSignon( msg, PROTO_CURRENT );
|
||||
break;
|
||||
case svc_centerprint:
|
||||
CL_CenterPrint( MSG_ReadString( msg ), 0.25f );
|
||||
@@ -2432,12 +2519,12 @@ void CL_ParseServerMessage( sizebuf_t *msg )
|
||||
CL_RegisterUserMessage( msg );
|
||||
break;
|
||||
case svc_packetentities:
|
||||
playerbytes = CL_ParsePacketEntities( msg, false );
|
||||
playerbytes = CL_ParsePacketEntities( msg, false, PROTO_CURRENT );
|
||||
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
|
||||
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
|
||||
break;
|
||||
case svc_deltapacketentities:
|
||||
playerbytes = CL_ParsePacketEntities( msg, true );
|
||||
playerbytes = CL_ParsePacketEntities( msg, true, PROTO_CURRENT );
|
||||
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
|
||||
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
|
||||
break;
|
||||
@@ -2446,7 +2533,7 @@ void CL_ParseServerMessage( sizebuf_t *msg )
|
||||
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].receivedtime = -2.0;
|
||||
break;
|
||||
case svc_resourcelist:
|
||||
CL_ParseResourceList( msg );
|
||||
CL_ParseResourceList( msg, PROTO_CURRENT );
|
||||
break;
|
||||
case svc_deltamovevars:
|
||||
CL_ParseMovevars( msg );
|
||||
|
||||
@@ -359,7 +359,7 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
|
||||
Host_AbortCurrentFrame ();
|
||||
break;
|
||||
case svc_legacy_event:
|
||||
CL_ParseEvent( msg );
|
||||
CL_ParseEvent( msg, PROTO_LEGACY );
|
||||
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_legacy_changing:
|
||||
@@ -446,19 +446,19 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
|
||||
break;
|
||||
case svc_serverdata:
|
||||
Cbuf_Execute(); // make sure any stuffed commands are done
|
||||
CL_ParseServerData( msg, true );
|
||||
CL_ParseServerData( msg, PROTO_LEGACY );
|
||||
break;
|
||||
case svc_lightstyle:
|
||||
CL_ParseLightStyle( msg );
|
||||
CL_ParseLightStyle( msg, PROTO_LEGACY );
|
||||
break;
|
||||
case svc_updateuserinfo:
|
||||
CL_UpdateUserinfo( msg, true );
|
||||
CL_UpdateUserinfo( msg, PROTO_LEGACY );
|
||||
break;
|
||||
case svc_deltatable:
|
||||
Delta_ParseTableField( msg );
|
||||
break;
|
||||
case svc_clientdata:
|
||||
CL_ParseClientData( msg );
|
||||
CL_ParseClientData( msg, PROTO_LEGACY );
|
||||
cl.frames[cl.parsecountmod].graphdata.client += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_resource:
|
||||
@@ -478,21 +478,21 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
|
||||
CL_LegacyParseStaticEntity( msg );
|
||||
break;
|
||||
case svc_event_reliable:
|
||||
CL_ParseReliableEvent( msg );
|
||||
CL_ParseReliableEvent( msg, PROTO_LEGACY );
|
||||
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_spawnbaseline:
|
||||
CL_ParseBaseline( msg, true );
|
||||
CL_ParseBaseline( msg, PROTO_LEGACY );
|
||||
break;
|
||||
case svc_temp_entity:
|
||||
CL_ParseTempEntity( msg );
|
||||
CL_ParseTempEntity( msg, PROTO_LEGACY );
|
||||
cl.frames[cl.parsecountmod].graphdata.tentities += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_setpause:
|
||||
cl.paused = ( MSG_ReadOneBit( msg ) != 0 );
|
||||
break;
|
||||
case svc_signonnum:
|
||||
CL_ParseSignon( msg );
|
||||
CL_ParseSignon( msg, PROTO_LEGACY );
|
||||
break;
|
||||
case svc_centerprint:
|
||||
CL_CenterPrint( MSG_ReadString( msg ), 0.25f );
|
||||
@@ -538,12 +538,12 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
|
||||
CL_RegisterUserMessage( msg );
|
||||
break;
|
||||
case svc_packetentities:
|
||||
playerbytes = CL_ParsePacketEntities( msg, false );
|
||||
playerbytes = CL_ParsePacketEntities( msg, false, PROTO_LEGACY );
|
||||
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
|
||||
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
|
||||
break;
|
||||
case svc_deltapacketentities:
|
||||
playerbytes = CL_ParsePacketEntities( msg, true );
|
||||
playerbytes = CL_ParsePacketEntities( msg, true, PROTO_LEGACY );
|
||||
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
|
||||
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
|
||||
break;
|
||||
@@ -658,8 +658,3 @@ void CL_LegacyPrecache_f( void )
|
||||
MSG_WriteStringf( &cls.netchan.message, "begin %i", spawncount );
|
||||
cls.signon = SIGNONS - 1;
|
||||
}
|
||||
|
||||
qboolean CL_LegacyMode( void )
|
||||
{
|
||||
return cls.legacymode == PROTO_LEGACY;
|
||||
}
|
||||
|
||||
761
engine/client/cl_parse_gs.c
Normal file
761
engine/client/cl_parse_gs.c
Normal file
@@ -0,0 +1,761 @@
|
||||
/*
|
||||
cl_parse.c - parse a message received from the server (GoldSrc 48 protocol)
|
||||
Copyright (C) 2008 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 "cl_tent.h"
|
||||
#include "shake.h"
|
||||
#include "hltv.h"
|
||||
#include "input.h"
|
||||
#include "server.h"
|
||||
|
||||
static void CL_ParseExtraInfo( sizebuf_t *msg )
|
||||
{
|
||||
string clientfallback;
|
||||
|
||||
Q_strncpy( clientfallback, MSG_ReadString( msg ), sizeof( clientfallback ));
|
||||
Cvar_FullSet( "sv_cheats", MSG_ReadByte( msg ) ? "1" : "0", FCVAR_READ_ONLY | FCVAR_SERVER );
|
||||
}
|
||||
|
||||
static void CL_ParseNewMovevars( sizebuf_t *msg )
|
||||
{
|
||||
Delta_InitClient(); // finalize client delta's
|
||||
|
||||
clgame.movevars.gravity = MSG_ReadFloat( msg );
|
||||
clgame.movevars.stopspeed = MSG_ReadFloat( msg );
|
||||
clgame.movevars.maxspeed = MSG_ReadFloat( msg );
|
||||
clgame.movevars.spectatormaxspeed = MSG_ReadFloat( msg );
|
||||
clgame.movevars.accelerate = MSG_ReadFloat( msg );
|
||||
clgame.movevars.airaccelerate = MSG_ReadFloat( msg );
|
||||
clgame.movevars.wateraccelerate = MSG_ReadFloat( msg );
|
||||
clgame.movevars.friction = MSG_ReadFloat( msg );
|
||||
clgame.movevars.edgefriction = MSG_ReadFloat( msg );
|
||||
clgame.movevars.waterfriction = MSG_ReadFloat( msg );
|
||||
clgame.movevars.entgravity = MSG_ReadFloat( msg );
|
||||
clgame.movevars.bounce = MSG_ReadFloat( msg );
|
||||
clgame.movevars.stepsize = MSG_ReadFloat( msg );
|
||||
clgame.movevars.maxvelocity = MSG_ReadFloat( msg );
|
||||
clgame.movevars.zmax = MSG_ReadFloat( msg );
|
||||
clgame.movevars.waveHeight = MSG_ReadFloat( msg );
|
||||
clgame.movevars.footsteps = MSG_ReadByte( msg );
|
||||
clgame.movevars.rollangle = MSG_ReadFloat( msg );
|
||||
clgame.movevars.rollspeed = MSG_ReadFloat( msg );
|
||||
clgame.movevars.skycolor_r = MSG_ReadFloat( msg );
|
||||
clgame.movevars.skycolor_g = MSG_ReadFloat( msg );
|
||||
clgame.movevars.skycolor_b = MSG_ReadFloat( msg );
|
||||
clgame.movevars.skyvec_x = MSG_ReadFloat( msg );
|
||||
clgame.movevars.skyvec_y = MSG_ReadFloat( msg );
|
||||
clgame.movevars.skyvec_z = MSG_ReadFloat( msg );
|
||||
|
||||
Q_strncpy( clgame.movevars.skyName, MSG_ReadString( msg ), sizeof( clgame.movevars.skyName ));
|
||||
|
||||
// water alpha is not allowed
|
||||
if( !FBitSet( world.flags, FWORLD_WATERALPHA ))
|
||||
clgame.movevars.wateralpha = 1.0f;
|
||||
|
||||
// update sky if changed
|
||||
if( Q_strcmp( clgame.oldmovevars.skyName, clgame.movevars.skyName ) && cl.video_prepped )
|
||||
R_SetupSky( clgame.movevars.skyName );
|
||||
|
||||
memcpy( &clgame.oldmovevars, &clgame.movevars, sizeof( movevars_t ));
|
||||
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
|
||||
|
||||
// keep features an actual!
|
||||
clgame.oldmovevars.features = clgame.movevars.features = host.features;
|
||||
}
|
||||
|
||||
static void CL_ParseNewUserMsg( sizebuf_t *msg )
|
||||
{
|
||||
int svc_num, size;
|
||||
char s[16];
|
||||
|
||||
svc_num = MSG_ReadByte( msg );
|
||||
size = MSG_ReadByte( msg );
|
||||
MSG_ReadBytes( msg, s, sizeof( s ));
|
||||
|
||||
s[15] = 0;
|
||||
if( size == 255 )
|
||||
size = -1;
|
||||
|
||||
CL_LinkUserMessage( s, svc_num, size );
|
||||
}
|
||||
|
||||
typedef struct delta_header_t
|
||||
{
|
||||
qboolean remove : 1;
|
||||
qboolean custom : 1;
|
||||
qboolean instanced : 1;
|
||||
uint instanced_baseline_index : 6;
|
||||
uint offset : 6;
|
||||
} delta_header_t;
|
||||
|
||||
static int CL_ParseDeltaHeader( sizebuf_t *msg, qboolean delta, int oldnum, struct delta_header_t *hdr )
|
||||
{
|
||||
int entnum;
|
||||
|
||||
hdr->remove = hdr->custom = hdr->instanced = false;
|
||||
hdr->instanced_baseline_index = hdr->offset = 0;
|
||||
entnum = oldnum;
|
||||
|
||||
if( !delta )
|
||||
{
|
||||
// if we have one bit set, then it's a next entity in line
|
||||
// if we have next bit NON set, then it's a one of next 64 entities
|
||||
// if not, it's a new entity
|
||||
if( MSG_ReadOneBit( msg ))
|
||||
entnum++;
|
||||
else if( MSG_ReadOneBit( msg ) == 0 )
|
||||
entnum += MSG_ReadUBitLong( msg, 6 );
|
||||
else
|
||||
entnum += MSG_ReadUBitLong( msg, MAX_GOLDSRC_ENTITY_BITS );
|
||||
}
|
||||
else
|
||||
{
|
||||
// does this packet encode entity deletion?
|
||||
hdr->remove = MSG_ReadOneBit( msg );
|
||||
|
||||
// same logic as above
|
||||
if( MSG_ReadOneBit( msg ) == 0 )
|
||||
entnum += MSG_ReadUBitLong( msg, 6 );
|
||||
else entnum = MSG_ReadUBitLong( msg, MAX_GOLDSRC_ENTITY_BITS );
|
||||
}
|
||||
|
||||
// if we are not removing this entity
|
||||
if( !hdr->remove )
|
||||
{
|
||||
hdr->custom = MSG_ReadOneBit( msg );
|
||||
|
||||
hdr->instanced = false;
|
||||
hdr->instanced_baseline_index = 0;
|
||||
|
||||
// do we got instanced baselines in svc_spawnbaselines?
|
||||
if( cl.instanced_baseline_count )
|
||||
{
|
||||
hdr->instanced = MSG_ReadOneBit( msg );
|
||||
if( hdr->instanced )
|
||||
hdr->instanced_baseline_index = MSG_ReadUBitLong( msg, 6 );
|
||||
}
|
||||
|
||||
hdr->offset = 0;
|
||||
if( !delta && !hdr->instanced )
|
||||
{
|
||||
if( MSG_ReadOneBit( msg ))
|
||||
hdr->offset = MSG_ReadUBitLong( msg, 6 );
|
||||
}
|
||||
}
|
||||
|
||||
return entnum;
|
||||
}
|
||||
|
||||
static int CL_GetEntityDelta( const struct delta_header_t *hdr, int entnum )
|
||||
{
|
||||
if( hdr->custom )
|
||||
return DT_CUSTOM_ENTITY_STATE_T;
|
||||
|
||||
if( CL_IsPlayerIndex( entnum ))
|
||||
return DT_ENTITY_STATE_PLAYER_T;
|
||||
|
||||
return DT_ENTITY_STATE_T;
|
||||
}
|
||||
|
||||
static void CL_FlushEntityPacketGS( frame_t *frame, sizebuf_t *msg )
|
||||
{
|
||||
frame->valid = false;
|
||||
cl.validsequence = 0; // can't render a frame
|
||||
|
||||
// read it all but ignore it
|
||||
while( 1 )
|
||||
{
|
||||
int num = 0;
|
||||
entity_state_t from = { 0 }, to;
|
||||
delta_header_t hdr;
|
||||
|
||||
if( MSG_ReadWord( msg ) != 0 )
|
||||
{
|
||||
MSG_SeekToBit( msg, -16, SEEK_CUR );
|
||||
|
||||
num = CL_ParseDeltaHeader( msg, false, num, &hdr );
|
||||
}
|
||||
else break;
|
||||
|
||||
if( MSG_CheckOverflow( msg ))
|
||||
Host_Error( "%s: overflow\n", __func__ );
|
||||
|
||||
if( hdr.remove )
|
||||
continue;
|
||||
|
||||
Delta_ReadGSFields( msg, CL_GetEntityDelta( &hdr, num ), &from, &to, cl.mtime[0] );
|
||||
}
|
||||
|
||||
MSG_EndBitWriting( msg );
|
||||
}
|
||||
|
||||
static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t *frame, int newnum, entity_state_t *from, qboolean has_update )
|
||||
{
|
||||
cl_entity_t *ent;
|
||||
entity_state_t *to;
|
||||
qboolean newent = from == NULL;
|
||||
int pack = frame->num_entities;
|
||||
|
||||
// alloc next slot to store update
|
||||
to = &cls.packet_entities[cls.next_client_entities % cls.num_client_entities];
|
||||
|
||||
if(( newnum < 0 ) || ( newnum >= clgame.maxEntities ))
|
||||
{
|
||||
Con_DPrintf( S_ERROR "CL_DeltaEntity: invalid newnum: %d\n", newnum );
|
||||
Host_Error( "%s: bad delta entity number: %i", __func__, newnum );
|
||||
return;
|
||||
}
|
||||
|
||||
ent = CL_EDICT_NUM( newnum );
|
||||
if( hdr->remove )
|
||||
{
|
||||
if( !newent )
|
||||
CL_KillDeadBeams( ent );
|
||||
return;
|
||||
}
|
||||
|
||||
ent->index = newnum; // enumerate entity index
|
||||
if( newent )
|
||||
{
|
||||
if( hdr->instanced )
|
||||
from = &cl.instanced_baseline[hdr->instanced_baseline_index];
|
||||
else if( hdr->offset != 0 )
|
||||
from = &cls.packet_entities[(cls.next_client_entities - hdr->offset) % cls.num_client_entities];
|
||||
else
|
||||
from = &ent->baseline;
|
||||
}
|
||||
|
||||
if( has_update )
|
||||
Delta_ReadGSFields( msg, CL_GetEntityDelta( hdr, newnum ), from, to, cl.mtime[0] );
|
||||
else memcpy( to, from, sizeof( entity_state_t ));
|
||||
|
||||
to->entityType = hdr->custom ? ENTITY_BEAM : ENTITY_NORMAL;
|
||||
to->number = newnum;
|
||||
|
||||
if( newent )
|
||||
{
|
||||
// interpolation must be reset
|
||||
SETVISBIT( frame->flags, pack );
|
||||
|
||||
// release beams from previous entity
|
||||
CL_KillDeadBeams( ent );
|
||||
}
|
||||
|
||||
// add entity to packet
|
||||
cls.next_client_entities++;
|
||||
frame->num_entities++;
|
||||
}
|
||||
|
||||
static void CL_CopyPacketEntity( frame_t *frame, int num, entity_state_t *from )
|
||||
{
|
||||
delta_header_t fakehdr =
|
||||
{
|
||||
.custom = FBitSet( from->entityType, ENTITY_BEAM ) == ENTITY_BEAM,
|
||||
};
|
||||
CL_DeltaEntityGS( &fakehdr, NULL, frame, num, from, false );
|
||||
}
|
||||
|
||||
static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta )
|
||||
{
|
||||
frame_t *frame, *oldframe;
|
||||
int oldindex, newnum, oldnum, numbase = 0;
|
||||
entity_state_t *oldent;
|
||||
int count;
|
||||
int playerbytes = 0;
|
||||
|
||||
// save first uncompressed packet as timestamp
|
||||
if( cls.changelevel && !delta && cls.demorecording )
|
||||
CL_WriteDemoJumpTime();
|
||||
|
||||
count = MSG_ReadWord( msg );
|
||||
|
||||
frame = &cl.frames[cl.parsecountmod];
|
||||
memset( frame->flags, 0, sizeof( frame->flags ));
|
||||
frame->first_entity = cls.next_client_entities;
|
||||
frame->num_entities = 0;
|
||||
frame->valid = true;
|
||||
|
||||
MSG_StartBitWriting( msg );
|
||||
|
||||
if( delta )
|
||||
{
|
||||
uint oldpacket = MSG_ReadByte( msg );
|
||||
oldframe = &cl.frames[oldpacket & CL_UPDATE_MASK];
|
||||
|
||||
if( !CL_ValidateDeltaPacket( oldpacket, oldframe ))
|
||||
{
|
||||
CL_FlushEntityPacketGS( frame, msg );
|
||||
return playerbytes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
oldframe = NULL;
|
||||
cl.send_reply = true;
|
||||
cls.demowaiting = false;
|
||||
}
|
||||
|
||||
cl.validsequence = cls.netchan.incoming_sequence;
|
||||
|
||||
oldent = NULL;
|
||||
oldindex = 0;
|
||||
oldnum = CL_UpdateOldEntNum( oldindex, oldframe, &oldent );
|
||||
|
||||
// read it all but ignore it
|
||||
while( 1 )
|
||||
{
|
||||
int bufstart;
|
||||
qboolean player;
|
||||
delta_header_t hdr;
|
||||
int val = MSG_ReadWord( msg );
|
||||
|
||||
if( val )
|
||||
{
|
||||
MSG_SeekToBit( msg, -16, SEEK_CUR );
|
||||
numbase = newnum = CL_ParseDeltaHeader( msg, delta, numbase, &hdr );
|
||||
}
|
||||
else break;
|
||||
|
||||
if( MSG_CheckOverflow( msg ))
|
||||
Host_Error( "%s: overflow\n", __func__ );
|
||||
|
||||
player = CL_IsPlayerIndex( newnum );
|
||||
|
||||
while( oldnum < newnum )
|
||||
{
|
||||
// one or more entities from the old packet are unchanged
|
||||
CL_CopyPacketEntity( frame, oldnum, oldent );
|
||||
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
|
||||
}
|
||||
|
||||
bufstart = MSG_GetNumBytesRead( msg );
|
||||
|
||||
if( oldnum == newnum )
|
||||
{
|
||||
// from delta
|
||||
CL_DeltaEntityGS( &hdr, msg, frame, newnum, oldent, true );
|
||||
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
|
||||
}
|
||||
else if( oldnum > newnum )
|
||||
{
|
||||
// from baseline
|
||||
CL_DeltaEntityGS( &hdr, msg, frame, newnum, NULL, true );
|
||||
}
|
||||
|
||||
if( player ) playerbytes += MSG_GetNumBytesRead( msg ) - bufstart;
|
||||
}
|
||||
|
||||
if( MSG_CheckOverflow( msg ))
|
||||
Host_Error( "%s: overflow\n", __func__ );
|
||||
|
||||
// any remaining entities in the old frame are copied over
|
||||
while( oldnum != MAX_ENTNUMBER )
|
||||
{
|
||||
// one or more entities from the old packet are unchanged
|
||||
CL_CopyPacketEntity( frame, oldnum, oldent );
|
||||
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
|
||||
}
|
||||
|
||||
MSG_EndBitWriting( msg );
|
||||
|
||||
if( frame->num_entities != count )
|
||||
Con_Reportf( S_WARN "CL_Parse%sPacketEntitiesGS: (%i should be %i)\n", delta ? "Delta" : "", frame->num_entities, count );
|
||||
|
||||
if( !frame->valid )
|
||||
return playerbytes;
|
||||
|
||||
CL_ProcessPacket( frame );
|
||||
CL_SetSolidEntities();
|
||||
|
||||
// first update is the final signon stage where we actually receive an entity (i.e., the world at least)
|
||||
if( cls.signon == ( SIGNONS - 1 ))
|
||||
{
|
||||
// we are done with signon sequence.
|
||||
cls.signon = SIGNONS;
|
||||
|
||||
// Clear loading plaque.
|
||||
CL_SignonReply( PROTO_GOLDSRC );
|
||||
}
|
||||
|
||||
return playerbytes;
|
||||
}
|
||||
|
||||
static float MSG_ReadGSBitCoord( sizebuf_t *sb )
|
||||
{
|
||||
float value = 0;
|
||||
int ival, fval;
|
||||
|
||||
ival = MSG_ReadOneBit( sb );
|
||||
fval = MSG_ReadOneBit( sb );
|
||||
|
||||
if( ival || fval )
|
||||
{
|
||||
int sign = MSG_ReadOneBit( sb );
|
||||
|
||||
if( ival )
|
||||
ival = MSG_ReadUBitLong( sb, 12 );
|
||||
if( fval )
|
||||
fval = MSG_ReadUBitLong( sb, 3 );
|
||||
|
||||
value = (float)( fval / 8.0 + ival );
|
||||
if( sign )
|
||||
value = -value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void MSG_ReadGSBitVec3Coord( sizebuf_t *sb, vec3_t fa )
|
||||
{
|
||||
qboolean x, y, z;
|
||||
|
||||
VectorClear( fa );
|
||||
|
||||
x = MSG_ReadOneBit( sb );
|
||||
y = MSG_ReadOneBit( sb );
|
||||
z = MSG_ReadOneBit( sb );
|
||||
if( x )
|
||||
fa[0] = MSG_ReadGSBitCoord( sb );
|
||||
if( y )
|
||||
fa[1] = MSG_ReadGSBitCoord( sb );
|
||||
if( z )
|
||||
fa[2] = MSG_ReadGSBitCoord( sb );
|
||||
}
|
||||
|
||||
static void CL_ParseSoundPacketGS( sizebuf_t *msg )
|
||||
{
|
||||
vec3_t pos;
|
||||
int chan, sound;
|
||||
float volume, attn;
|
||||
int flags, pitch, entnum;
|
||||
sound_t handle = 0;
|
||||
|
||||
MSG_StartBitWriting( msg );
|
||||
|
||||
flags = MSG_ReadUBitLong( msg, 9 );
|
||||
|
||||
if( FBitSet( flags, SND_VOLUME ))
|
||||
volume = (float)MSG_ReadByte( msg ) / 255.0f;
|
||||
else volume = VOL_NORM;
|
||||
|
||||
if( FBitSet( flags, SND_ATTENUATION ))
|
||||
attn = (float)MSG_ReadByte( msg ) / 64.0f;
|
||||
else attn = ATTN_NONE;
|
||||
|
||||
chan = MSG_ReadUBitLong( msg, 3 );
|
||||
entnum = MSG_ReadUBitLong( msg, MAX_GOLDSRC_ENTITY_BITS );
|
||||
sound = MSG_ReadUBitLong( msg, FBitSet( flags, SND_SEQUENCE ) ? 16 : 8 );
|
||||
MSG_ReadGSBitVec3Coord( msg, pos );
|
||||
|
||||
if( FBitSet( flags, SND_PITCH ))
|
||||
pitch = MSG_ReadByte( msg );
|
||||
else pitch = PITCH_NORM;
|
||||
|
||||
MSG_EndBitWriting( msg );
|
||||
|
||||
if( FBitSet( flags, SND_SENTENCE ))
|
||||
{
|
||||
char sentenceName[32];
|
||||
|
||||
if( FBitSet( flags, SND_SEQUENCE ))
|
||||
Q_snprintf( sentenceName, sizeof( sentenceName ), "!#%i", sound + MAX_SOUNDS_NONSENTENCE );
|
||||
else Q_snprintf( sentenceName, sizeof( sentenceName ), "!%i", sound );
|
||||
|
||||
handle = S_RegisterSound( sentenceName );
|
||||
}
|
||||
else handle = cl.sound_index[sound]; // see precached sound
|
||||
|
||||
if( !cl.audio_prepped )
|
||||
return; // too early
|
||||
|
||||
// g-cont. sound and ambient sound have only difference with channel
|
||||
if( chan == CHAN_STATIC )
|
||||
{
|
||||
S_AmbientSound( pos, entnum, handle, volume, attn, pitch, flags );
|
||||
}
|
||||
else
|
||||
{
|
||||
S_StartSound( pos, entnum, chan, handle, volume, attn, pitch, flags );
|
||||
}
|
||||
}
|
||||
|
||||
static void CL_ParseSpawnStaticSound( sizebuf_t *msg )
|
||||
{
|
||||
vec3_t pos;
|
||||
int handle, entnum, pitch, flags;
|
||||
float volume, attn;
|
||||
|
||||
MSG_ReadVec3Coord( msg, pos );
|
||||
handle = MSG_ReadShort( msg );
|
||||
volume = MSG_ReadByte( msg ) * ( 1.0f / 255.0f );
|
||||
attn = MSG_ReadByte( msg ) * ( 1.0f / 64.0f );
|
||||
entnum = MSG_ReadShort( msg );
|
||||
pitch = MSG_ReadByte( msg );
|
||||
flags = MSG_ReadByte( msg );
|
||||
|
||||
S_AmbientSound( pos, entnum, handle, volume, attn, pitch, flags );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================================================
|
||||
|
||||
ACTION MESSAGES
|
||||
|
||||
=====================================================================
|
||||
*/
|
||||
/*
|
||||
=====================
|
||||
CL_ParseGoldSrcServerMessage
|
||||
|
||||
dispatch messages
|
||||
=====================
|
||||
*/
|
||||
void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
|
||||
{
|
||||
size_t bufStart, playerbytes;
|
||||
int cmd, param1, param2;
|
||||
int old_background;
|
||||
const char *s;
|
||||
|
||||
// parse the message
|
||||
while( 1 )
|
||||
{
|
||||
if( MSG_CheckOverflow( msg ))
|
||||
{
|
||||
Host_Error( "CL_ParseServerMessage: overflow!\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// mark start position
|
||||
bufStart = MSG_GetNumBytesRead( msg );
|
||||
|
||||
// end of message (align bits)
|
||||
if( MSG_GetNumBitsLeft( msg ) < 8 )
|
||||
break;
|
||||
|
||||
cmd = MSG_ReadServerCmd( msg );
|
||||
|
||||
// record command for debugging spew on parse problem
|
||||
CL_Parse_RecordCommand( cmd, bufStart );
|
||||
|
||||
// other commands
|
||||
switch( cmd )
|
||||
{
|
||||
case svc_bad:
|
||||
Host_Error( "svc_bad\n" );
|
||||
break;
|
||||
case svc_nop:
|
||||
// this does nothing
|
||||
break;
|
||||
case svc_disconnect:
|
||||
CL_Drop ();
|
||||
Host_AbortCurrentFrame ();
|
||||
break;
|
||||
case svc_event:
|
||||
MSG_StartBitWriting( msg );
|
||||
CL_ParseEvent( msg, PROTO_GOLDSRC );
|
||||
MSG_EndBitWriting( msg );
|
||||
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_setview:
|
||||
CL_ParseViewEntity( msg );
|
||||
break;
|
||||
case svc_sound:
|
||||
CL_ParseSoundPacketGS( msg );
|
||||
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_time:
|
||||
CL_ParseServerTime( msg );
|
||||
break;
|
||||
case svc_print:
|
||||
Con_Printf( "%s", MSG_ReadString( msg ));
|
||||
break;
|
||||
case svc_stufftext:
|
||||
s = MSG_ReadString( msg );
|
||||
#ifdef HACKS_RELATED_HLMODS
|
||||
// disable Cry Of Fear antisave protection
|
||||
if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS )
|
||||
break; // too early
|
||||
#endif
|
||||
Cbuf_AddFilteredText( s );
|
||||
break;
|
||||
case svc_setangle:
|
||||
CL_ParseSetAngle( msg );
|
||||
break;
|
||||
case svc_goldsrc_serverinfo:
|
||||
Cbuf_Execute(); // make sure any stuffed commands are done
|
||||
CL_ParseServerData( msg, PROTO_GOLDSRC );
|
||||
Delta_InitMeta();
|
||||
break;
|
||||
case svc_lightstyle:
|
||||
CL_ParseLightStyle( msg, PROTO_GOLDSRC );
|
||||
break;
|
||||
case svc_updateuserinfo:
|
||||
CL_UpdateUserinfo( msg, PROTO_GOLDSRC );
|
||||
break;
|
||||
case svc_goldsrc_deltadescription:
|
||||
Delta_ParseTableField_GS( msg );
|
||||
break;
|
||||
case svc_clientdata:
|
||||
MSG_StartBitWriting( msg );
|
||||
CL_ParseClientData( msg, PROTO_GOLDSRC );
|
||||
MSG_EndBitWriting( msg );
|
||||
cl.frames[cl.parsecountmod].graphdata.client += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_pings:
|
||||
MSG_StartBitWriting( msg );
|
||||
CL_UpdateUserPings( msg );
|
||||
MSG_EndBitWriting( msg );
|
||||
break;
|
||||
case svc_particle:
|
||||
CL_ParseParticles( msg );
|
||||
break;
|
||||
case svc_spawnstatic:
|
||||
CL_ParseStaticEntity( msg );
|
||||
break;
|
||||
case svc_event_reliable:
|
||||
MSG_StartBitWriting( msg );
|
||||
CL_ParseReliableEvent( msg, PROTO_GOLDSRC );
|
||||
MSG_EndBitWriting( msg );
|
||||
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_spawnbaseline:
|
||||
CL_ParseBaseline( msg, PROTO_GOLDSRC );
|
||||
break;
|
||||
case svc_temp_entity:
|
||||
CL_ParseTempEntity( msg, PROTO_GOLDSRC );
|
||||
cl.frames[cl.parsecountmod].graphdata.tentities += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_setpause:
|
||||
cl.paused = ( MSG_ReadOneBit( msg ) != 0 );
|
||||
break;
|
||||
case svc_signonnum:
|
||||
CL_ParseSignon( msg, PROTO_GOLDSRC );
|
||||
break;
|
||||
case svc_centerprint:
|
||||
CL_CenterPrint( MSG_ReadString( msg ), 0.25f );
|
||||
break;
|
||||
case svc_goldsrc_spawnstaticsound:
|
||||
CL_ParseSpawnStaticSound( msg );
|
||||
break;
|
||||
case svc_intermission:
|
||||
cl.intermission = 1;
|
||||
break;
|
||||
case svc_finale:
|
||||
CL_ParseFinaleCutscene( msg, 2 );
|
||||
break;
|
||||
case svc_cdtrack:
|
||||
param1 = MSG_ReadByte( msg );
|
||||
param1 = bound( 1, param1, MAX_CDTRACKS ); // tracknum
|
||||
param2 = MSG_ReadByte( msg );
|
||||
param2 = bound( 1, param2, MAX_CDTRACKS ); // loopnum
|
||||
S_StartBackgroundTrack( clgame.cdtracks[param1-1], clgame.cdtracks[param2-1], 0, false );
|
||||
break;
|
||||
case svc_restore:
|
||||
CL_ParseRestore( msg );
|
||||
break;
|
||||
case svc_cutscene:
|
||||
CL_ParseFinaleCutscene( msg, 3 );
|
||||
break;
|
||||
case svc_weaponanim:
|
||||
param1 = MSG_ReadByte( msg ); // iAnim
|
||||
param2 = MSG_ReadByte( msg ); // body
|
||||
CL_WeaponAnim( param1, param2 );
|
||||
break;
|
||||
case svc_roomtype:
|
||||
param1 = MSG_ReadShort( msg );
|
||||
Cvar_SetValue( "room_type", param1 );
|
||||
break;
|
||||
case svc_addangle:
|
||||
CL_ParseAddAngle( msg );
|
||||
break;
|
||||
case svc_goldsrc_newusermsg:
|
||||
CL_ParseNewUserMsg( msg );
|
||||
break;
|
||||
case svc_packetentities:
|
||||
playerbytes = CL_ParsePacketEntitiesGS( msg, false );
|
||||
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
|
||||
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
|
||||
break;
|
||||
case svc_deltapacketentities:
|
||||
playerbytes = CL_ParsePacketEntitiesGS( msg, true );
|
||||
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
|
||||
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
|
||||
break;
|
||||
case svc_choke:
|
||||
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = true;
|
||||
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].receivedtime = -2.0;
|
||||
break;
|
||||
case svc_resourcelist:
|
||||
MSG_StartBitWriting( msg );
|
||||
CL_ParseResourceList( msg, PROTO_GOLDSRC );
|
||||
MSG_EndBitWriting( msg );
|
||||
break;
|
||||
case svc_goldsrc_newmovevars:
|
||||
CL_ParseNewMovevars( msg );
|
||||
break;
|
||||
case svc_resourcerequest:
|
||||
CL_ParseResourceRequest( msg );
|
||||
break;
|
||||
case svc_customization:
|
||||
CL_ParseCustomization( msg );
|
||||
break;
|
||||
case svc_crosshairangle:
|
||||
CL_ParseCrosshairAngle( msg );
|
||||
break;
|
||||
case svc_soundfade:
|
||||
CL_ParseSoundFade( msg );
|
||||
break;
|
||||
case svc_filetxferfailed:
|
||||
CL_ParseFileTransferFailed( msg );
|
||||
break;
|
||||
case svc_hltv:
|
||||
CL_ParseHLTV( msg );
|
||||
break;
|
||||
case svc_director:
|
||||
CL_ParseDirector( msg );
|
||||
break;
|
||||
case svc_voiceinit:
|
||||
CL_ParseVoiceInit( msg );
|
||||
break;
|
||||
case svc_voicedata:
|
||||
CL_ParseVoiceData( msg );
|
||||
cl.frames[cl.parsecountmod].graphdata.voicebytes += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_resourcelocation:
|
||||
CL_ParseResLocation( msg );
|
||||
break;
|
||||
case svc_goldsrc_sendextrainfo:
|
||||
CL_ParseExtraInfo( msg );
|
||||
break;
|
||||
case svc_querycvarvalue:
|
||||
CL_ParseCvarValue( msg, false, PROTO_GOLDSRC );
|
||||
break;
|
||||
case svc_querycvarvalue2:
|
||||
CL_ParseCvarValue( msg, true, PROTO_GOLDSRC );
|
||||
break;
|
||||
case svc_exec:
|
||||
CL_ParseExec( msg );
|
||||
break;
|
||||
default:
|
||||
CL_ParseUserMessage( msg, cmd );
|
||||
cl.frames[cl.parsecountmod].graphdata.usr += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -431,7 +431,7 @@ static void CL_ParseQuakeEntityData( sizebuf_t *msg, int bits )
|
||||
cls.signon = SIGNONS;
|
||||
|
||||
// Clear loading plaque.
|
||||
CL_SignonReply ();
|
||||
CL_SignonReply( PROTO_QUAKE );
|
||||
}
|
||||
|
||||
// alloc next slot to store update
|
||||
@@ -626,7 +626,7 @@ CL_ParseStaticEntity
|
||||
|
||||
===================
|
||||
*/
|
||||
static void CL_ParseStaticEntity( sizebuf_t *msg )
|
||||
static void CL_ParseQuakeStaticEntity( sizebuf_t *msg )
|
||||
{
|
||||
entity_state_t state;
|
||||
cl_entity_t *ent;
|
||||
@@ -1006,7 +1006,7 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
|
||||
CL_ParseQuakeDamage( msg );
|
||||
break;
|
||||
case svc_spawnstatic:
|
||||
CL_ParseStaticEntity( msg );
|
||||
CL_ParseQuakeStaticEntity( msg );
|
||||
break;
|
||||
case svc_spawnbinary:
|
||||
// never used in Quake
|
||||
|
||||
@@ -1269,6 +1269,73 @@ void GAME_EXPORT R_Sprite_Smoke( TEMPENTITY *pTemp, float scale )
|
||||
pTemp->entity.curstate.scale = scale;
|
||||
}
|
||||
|
||||
static void R_Spray_Generic( const char *func, const vec3_t pos, const vec3_t dir, int modelIndex, int count, int speed, int spread, int rendermode, qboolean sprite_spray )
|
||||
{
|
||||
model_t *mod = CL_ModelHandle( modelIndex );
|
||||
float noise = spread / 100.0f;
|
||||
float znoise = noise * 1.5f;
|
||||
int i;
|
||||
|
||||
znoise = Q_min( 1.0f, znoise );
|
||||
|
||||
if( !mod )
|
||||
{
|
||||
Con_Reportf( "%s: No model %d!\n", func, modelIndex );
|
||||
return;
|
||||
}
|
||||
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
TEMPENTITY *tent = CL_TempEntAlloc( pos, mod );
|
||||
float rand_speed;
|
||||
vec3_t noise_vec, vout;
|
||||
|
||||
if( !tent )
|
||||
break;
|
||||
|
||||
tent->flags |= FTENT_SLOWGRAVITY;
|
||||
tent->entity.curstate.rendermode = rendermode;
|
||||
tent->entity.curstate.renderamt = 255;
|
||||
tent->entity.baseline.renderamt = 255;
|
||||
tent->entity.curstate.renderfx = kRenderFxNoDissipation;
|
||||
|
||||
noise_vec[0] = COM_RandomFloat( -noise, noise );
|
||||
noise_vec[1] = COM_RandomFloat( -noise, noise );
|
||||
noise_vec[2] = COM_RandomFloat( 0.0f, znoise );
|
||||
rand_speed = COM_RandomFloat( speed * 0.8f, speed * 1.2f );
|
||||
|
||||
VectorAdd( dir, noise_vec, vout );
|
||||
VectorScale( vout, rand_speed, tent->entity.baseline.origin );
|
||||
|
||||
if( sprite_spray ) // if TE_SPRITE_SPRAY
|
||||
{
|
||||
tent->flags |= FTENT_FADEOUT;
|
||||
tent->fadeSpeed = 2.0f;
|
||||
|
||||
tent->entity.curstate.framerate = 0.5f;
|
||||
tent->die = cl.time + 0.35;
|
||||
tent->entity.curstate.frame = COM_RandomLong( 0, tent->frameMax ); // frameMax inclusive
|
||||
}
|
||||
else
|
||||
{
|
||||
tent->flags |= FTENT_COLLIDEWORLD;
|
||||
|
||||
if( tent->frameMax > 1 )
|
||||
{
|
||||
tent->flags |= FTENT_SPRANIMATE;
|
||||
tent->entity.curstate.framerate = 10.0f;
|
||||
tent->die = cl.time + tent->frameMax * 0.1;
|
||||
}
|
||||
else
|
||||
{
|
||||
tent->entity.curstate.framerate = 1.0f;
|
||||
tent->die = cl.time + 0.35;
|
||||
}
|
||||
tent->entity.curstate.frame = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_Spray
|
||||
@@ -1278,61 +1345,7 @@ Throws a shower of sprites or models
|
||||
*/
|
||||
void GAME_EXPORT R_Spray( const vec3_t pos, const vec3_t dir, int modelIndex, int count, int speed, int spread, int rendermode )
|
||||
{
|
||||
TEMPENTITY *pTemp;
|
||||
float noise;
|
||||
float znoise;
|
||||
model_t *pmodel;
|
||||
int i;
|
||||
|
||||
if(( pmodel = CL_ModelHandle( modelIndex )) == NULL )
|
||||
{
|
||||
Con_Reportf( "No model %d!\n", modelIndex );
|
||||
return;
|
||||
}
|
||||
|
||||
noise = (float)spread / 100.0f;
|
||||
|
||||
// more vertical displacement
|
||||
znoise = Q_min( 1.0f, noise * 1.5f );
|
||||
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
pTemp = CL_TempEntAlloc( pos, pmodel );
|
||||
if( !pTemp ) return;
|
||||
|
||||
pTemp->entity.curstate.rendermode = rendermode;
|
||||
pTemp->entity.baseline.renderamt = pTemp->entity.curstate.renderamt = 255;
|
||||
pTemp->entity.curstate.renderfx = kRenderFxNoDissipation;
|
||||
|
||||
if( rendermode != kRenderGlow )
|
||||
{
|
||||
// spray
|
||||
pTemp->flags |= FTENT_COLLIDEWORLD | FTENT_SLOWGRAVITY;
|
||||
|
||||
if( pTemp->frameMax > 1 )
|
||||
{
|
||||
pTemp->flags |= FTENT_COLLIDEWORLD | FTENT_SLOWGRAVITY | FTENT_SPRANIMATE;
|
||||
pTemp->die = cl.time + (pTemp->frameMax * 0.1f);
|
||||
pTemp->entity.curstate.framerate = 10;
|
||||
}
|
||||
else pTemp->die = cl.time + 0.35f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// sprite spray
|
||||
pTemp->entity.curstate.frame = COM_RandomLong( 0, pTemp->frameMax );
|
||||
pTemp->flags |= FTENT_FADEOUT | FTENT_SLOWGRAVITY;
|
||||
pTemp->entity.curstate.framerate = 0.5;
|
||||
pTemp->die = cl.time + 0.35f;
|
||||
pTemp->fadeSpeed = 2.0;
|
||||
}
|
||||
|
||||
// make the spittle fly the direction indicated, but mix in some noise.
|
||||
pTemp->entity.baseline.origin[0] = dir[0] + COM_RandomFloat( -noise, noise );
|
||||
pTemp->entity.baseline.origin[1] = dir[1] + COM_RandomFloat( -noise, noise );
|
||||
pTemp->entity.baseline.origin[2] = dir[2] + COM_RandomFloat( 0, znoise );
|
||||
VectorScale( pTemp->entity.baseline.origin, COM_RandomFloat(( speed * 0.8f ), ( speed * 1.2f )), pTemp->entity.baseline.origin );
|
||||
}
|
||||
R_Spray_Generic( __func__, pos, dir, modelIndex, count, speed, spread, rendermode, false );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1344,7 +1357,7 @@ Spray of alpha sprites
|
||||
*/
|
||||
void GAME_EXPORT R_Sprite_Spray( const vec3_t pos, const vec3_t dir, int modelIndex, int count, int speed, int spread )
|
||||
{
|
||||
R_Spray( pos, dir, modelIndex, count, speed, spread, kRenderGlow );
|
||||
R_Spray_Generic( __func__, pos, dir, modelIndex, count, speed, spread, kRenderTransAlpha, true );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1879,13 +1892,13 @@ CL_ParseTempEntity
|
||||
handle temp-entity messages
|
||||
==============
|
||||
*/
|
||||
void CL_ParseTempEntity( sizebuf_t *msg )
|
||||
void CL_ParseTempEntity( sizebuf_t *msg, connprotocol_t proto )
|
||||
{
|
||||
sizebuf_t buf;
|
||||
byte pbuf[2048];
|
||||
sizebuf_t buf, *pbuf;
|
||||
byte msg_data[2048];
|
||||
int iSize;
|
||||
int type, color, count, flags;
|
||||
int decalIndex, modelIndex, entityIndex;
|
||||
int decalIndex = 0, modelIndex = 0, entityIndex = 0;
|
||||
float scale, life, frameRate, vel, random;
|
||||
float brightness, r, g, b;
|
||||
vec3_t pos, pos2, ang;
|
||||
@@ -1896,23 +1909,30 @@ void CL_ParseTempEntity( sizebuf_t *msg )
|
||||
sound_t hSound;
|
||||
const char *name;
|
||||
|
||||
if( cls.legacymode )
|
||||
iSize = MSG_ReadByte( msg );
|
||||
else iSize = MSG_ReadWord( msg );
|
||||
if( proto != PROTO_GOLDSRC )
|
||||
{
|
||||
if( proto == PROTO_LEGACY )
|
||||
iSize = MSG_ReadByte( msg );
|
||||
else iSize = MSG_ReadWord( msg );
|
||||
|
||||
decalIndex = modelIndex = entityIndex = 0;
|
||||
// this will probably be fatal anyway
|
||||
if( iSize > sizeof( pbuf ))
|
||||
Con_Printf( S_ERROR "%s: Temp buffer overflow!\n", __func__ );
|
||||
|
||||
// this will probably be fatal anyway
|
||||
if( iSize > sizeof( pbuf ))
|
||||
Con_Printf( S_ERROR "%s: Temp buffer overflow!\n", __func__ );
|
||||
// parse user message into buffer
|
||||
MSG_ReadBytes( msg, pbuf, iSize );
|
||||
|
||||
// parse user message into buffer
|
||||
MSG_ReadBytes( msg, pbuf, iSize );
|
||||
// init a safe tempbuffer
|
||||
MSG_Init( pbuf, "TempEntity", pbuf, iSize );
|
||||
|
||||
// init a safe tempbuffer
|
||||
MSG_Init( &buf, "TempEntity", pbuf, iSize );
|
||||
pbuf = pbuf;
|
||||
}
|
||||
else
|
||||
{
|
||||
pbuf = msg;
|
||||
}
|
||||
|
||||
type = MSG_ReadByte( &buf );
|
||||
type = MSG_ReadByte( pbuf );
|
||||
|
||||
switch( type )
|
||||
{
|
||||
@@ -1929,29 +1949,29 @@ void CL_ParseTempEntity( sizebuf_t *msg )
|
||||
case TE_BEAMRING:
|
||||
case TE_BEAMHOSE:
|
||||
case TE_KILLBEAM:
|
||||
CL_ParseViewBeam( &buf, type );
|
||||
CL_ParseViewBeam( pbuf, type );
|
||||
break;
|
||||
case TE_GUNSHOT:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
R_RicochetSound( pos );
|
||||
R_RunParticleEffect( pos, vec3_origin, 0, 20 );
|
||||
break;
|
||||
case TE_EXPLOSION:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
modelIndex = MSG_ReadShort( &buf );
|
||||
scale = (float)(MSG_ReadByte( &buf ) * 0.1f);
|
||||
frameRate = MSG_ReadByte( &buf );
|
||||
flags = MSG_ReadByte( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
modelIndex = MSG_ReadShort( pbuf );
|
||||
scale = (float)(MSG_ReadByte( pbuf ) * 0.1f);
|
||||
frameRate = MSG_ReadByte( pbuf );
|
||||
flags = MSG_ReadByte( pbuf );
|
||||
R_Explosion( pos, modelIndex, scale, frameRate, flags );
|
||||
break;
|
||||
case TE_TAREXPLOSION:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
R_BlobExplosion( pos );
|
||||
|
||||
if(( name = SoundList_Get( Explode, 0 )))
|
||||
@@ -1961,48 +1981,48 @@ void CL_ParseTempEntity( sizebuf_t *msg )
|
||||
}
|
||||
break;
|
||||
case TE_SMOKE:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
modelIndex = MSG_ReadShort( &buf );
|
||||
scale = (float)(MSG_ReadByte( &buf ) * 0.1f);
|
||||
frameRate = MSG_ReadByte( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
modelIndex = MSG_ReadShort( pbuf );
|
||||
scale = (float)(MSG_ReadByte( pbuf ) * 0.1f);
|
||||
frameRate = MSG_ReadByte( pbuf );
|
||||
pTemp = R_DefaultSprite( pos, modelIndex, frameRate );
|
||||
R_Sprite_Smoke( pTemp, scale );
|
||||
break;
|
||||
case TE_TRACER:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos2[0] = MSG_ReadCoord( &buf );
|
||||
pos2[1] = MSG_ReadCoord( &buf );
|
||||
pos2[2] = MSG_ReadCoord( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
pos2[0] = MSG_ReadCoord( pbuf );
|
||||
pos2[1] = MSG_ReadCoord( pbuf );
|
||||
pos2[2] = MSG_ReadCoord( pbuf );
|
||||
R_TracerEffect( pos, pos2 );
|
||||
break;
|
||||
case TE_SPARKS:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
R_SparkShower( pos );
|
||||
break;
|
||||
case TE_LAVASPLASH:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
R_LavaSplash( pos );
|
||||
break;
|
||||
case TE_TELEPORT:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
R_TeleportSplash( pos );
|
||||
break;
|
||||
case TE_EXPLOSION2:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
color = MSG_ReadByte( &buf );
|
||||
count = MSG_ReadByte( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
color = MSG_ReadByte( pbuf );
|
||||
count = MSG_ReadByte( pbuf );
|
||||
R_ParticleExplosion2( pos, color, count );
|
||||
|
||||
dl = CL_AllocDlight( 0 );
|
||||
@@ -2022,25 +2042,25 @@ void CL_ParseTempEntity( sizebuf_t *msg )
|
||||
case TE_WORLDDECAL:
|
||||
case TE_WORLDDECALHIGH:
|
||||
case TE_DECALHIGH:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
if( type == TE_BSPDECAL )
|
||||
{
|
||||
decalIndex = MSG_ReadShort( &buf );
|
||||
entityIndex = MSG_ReadShort( &buf );
|
||||
decalIndex = MSG_ReadShort( pbuf );
|
||||
entityIndex = MSG_ReadShort( pbuf );
|
||||
if( entityIndex )
|
||||
modelIndex = MSG_ReadShort( &buf );
|
||||
modelIndex = MSG_ReadShort( pbuf );
|
||||
else modelIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
decalIndex = MSG_ReadByte( &buf );
|
||||
decalIndex = MSG_ReadByte( pbuf );
|
||||
if( type == TE_DECALHIGH || type == TE_WORLDDECALHIGH )
|
||||
decalIndex += 256;
|
||||
|
||||
if( type == TE_DECALHIGH || type == TE_DECAL )
|
||||
entityIndex = MSG_ReadShort( &buf );
|
||||
entityIndex = MSG_ReadShort( pbuf );
|
||||
else entityIndex = 0;
|
||||
|
||||
pEnt = CL_GetEntityByIndex( entityIndex );
|
||||
@@ -2049,197 +2069,197 @@ void CL_ParseTempEntity( sizebuf_t *msg )
|
||||
CL_DecalShoot( CL_DecalIndex( decalIndex ), entityIndex, modelIndex, pos, type == TE_BSPDECAL ? FDECAL_PERMANENT : 0 );
|
||||
break;
|
||||
case TE_IMPLOSION:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
scale = MSG_ReadByte( &buf );
|
||||
count = MSG_ReadByte( &buf );
|
||||
life = (float)(MSG_ReadByte( &buf ) * 0.1f);
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
scale = MSG_ReadByte( pbuf );
|
||||
count = MSG_ReadByte( pbuf );
|
||||
life = (float)(MSG_ReadByte( pbuf ) * 0.1f);
|
||||
R_Implosion( pos, scale, count, life );
|
||||
break;
|
||||
case TE_SPRITETRAIL:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos2[0] = MSG_ReadCoord( &buf );
|
||||
pos2[1] = MSG_ReadCoord( &buf );
|
||||
pos2[2] = MSG_ReadCoord( &buf );
|
||||
modelIndex = MSG_ReadShort( &buf );
|
||||
count = MSG_ReadByte( &buf );
|
||||
life = (float)MSG_ReadByte( &buf ) * 0.1f;
|
||||
scale = (float)MSG_ReadByte( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
pos2[0] = MSG_ReadCoord( pbuf );
|
||||
pos2[1] = MSG_ReadCoord( pbuf );
|
||||
pos2[2] = MSG_ReadCoord( pbuf );
|
||||
modelIndex = MSG_ReadShort( pbuf );
|
||||
count = MSG_ReadByte( pbuf );
|
||||
life = (float)MSG_ReadByte( pbuf ) * 0.1f;
|
||||
scale = (float)MSG_ReadByte( pbuf );
|
||||
if( !scale ) scale = 1.0f;
|
||||
else scale *= 0.1f;
|
||||
vel = (float)MSG_ReadByte( &buf ) * 10;
|
||||
random = (float)MSG_ReadByte( &buf ) * 10;
|
||||
vel = (float)MSG_ReadByte( pbuf ) * 10;
|
||||
random = (float)MSG_ReadByte( pbuf ) * 10;
|
||||
R_Sprite_Trail( type, pos, pos2, modelIndex, count, life, scale, random, 255, vel );
|
||||
break;
|
||||
case TE_SPRITE:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
modelIndex = MSG_ReadShort( &buf );
|
||||
scale = (float)MSG_ReadByte( &buf ) * 0.1f;
|
||||
brightness = (float)MSG_ReadByte( &buf ) / 255.0f;
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
modelIndex = MSG_ReadShort( pbuf );
|
||||
scale = (float)MSG_ReadByte( pbuf ) * 0.1f;
|
||||
brightness = (float)MSG_ReadByte( pbuf ) / 255.0f;
|
||||
|
||||
R_TempSprite( pos, vec3_origin, scale, modelIndex,
|
||||
kRenderTransAdd, kRenderFxNone, brightness, 0.0, FTENT_SPRANIMATE );
|
||||
break;
|
||||
case TE_GLOWSPRITE:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
modelIndex = MSG_ReadShort( &buf );
|
||||
life = (float)MSG_ReadByte( &buf ) * 0.1f;
|
||||
scale = (float)MSG_ReadByte( &buf ) * 0.1f;
|
||||
brightness = (float)MSG_ReadByte( &buf ) / 255.0f;
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
modelIndex = MSG_ReadShort( pbuf );
|
||||
life = (float)MSG_ReadByte( pbuf ) * 0.1f;
|
||||
scale = (float)MSG_ReadByte( pbuf ) * 0.1f;
|
||||
brightness = (float)MSG_ReadByte( pbuf ) / 255.0f;
|
||||
|
||||
R_TempSprite( pos, vec3_origin, scale, modelIndex,
|
||||
kRenderGlow, kRenderFxNoDissipation, brightness, life, FTENT_FADEOUT );
|
||||
break;
|
||||
case TE_STREAK_SPLASH:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos2[0] = MSG_ReadCoord( &buf );
|
||||
pos2[1] = MSG_ReadCoord( &buf );
|
||||
pos2[2] = MSG_ReadCoord( &buf );
|
||||
color = MSG_ReadByte( &buf );
|
||||
count = MSG_ReadShort( &buf );
|
||||
vel = (float)MSG_ReadShort( &buf );
|
||||
random = (float)MSG_ReadShort( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
pos2[0] = MSG_ReadCoord( pbuf );
|
||||
pos2[1] = MSG_ReadCoord( pbuf );
|
||||
pos2[2] = MSG_ReadCoord( pbuf );
|
||||
color = MSG_ReadByte( pbuf );
|
||||
count = MSG_ReadShort( pbuf );
|
||||
vel = (float)MSG_ReadShort( pbuf );
|
||||
random = (float)MSG_ReadShort( pbuf );
|
||||
R_StreakSplash( pos, pos2, color, count, vel, -random, random );
|
||||
break;
|
||||
case TE_DLIGHT:
|
||||
dl = CL_AllocDlight( 0 );
|
||||
dl->origin[0] = MSG_ReadCoord( &buf );
|
||||
dl->origin[1] = MSG_ReadCoord( &buf );
|
||||
dl->origin[2] = MSG_ReadCoord( &buf );
|
||||
dl->radius = (float)(MSG_ReadByte( &buf ) * 10.0f);
|
||||
dl->color.r = MSG_ReadByte( &buf );
|
||||
dl->color.g = MSG_ReadByte( &buf );
|
||||
dl->color.b = MSG_ReadByte( &buf );
|
||||
dl->die = cl.time + (float)(MSG_ReadByte( &buf ) * 0.1f);
|
||||
dl->decay = (float)(MSG_ReadByte( &buf ) * 10.0f);
|
||||
dl->origin[0] = MSG_ReadCoord( pbuf );
|
||||
dl->origin[1] = MSG_ReadCoord( pbuf );
|
||||
dl->origin[2] = MSG_ReadCoord( pbuf );
|
||||
dl->radius = (float)(MSG_ReadByte( pbuf ) * 10.0f);
|
||||
dl->color.r = MSG_ReadByte( pbuf );
|
||||
dl->color.g = MSG_ReadByte( pbuf );
|
||||
dl->color.b = MSG_ReadByte( pbuf );
|
||||
dl->die = cl.time + (float)(MSG_ReadByte( pbuf ) * 0.1f);
|
||||
dl->decay = (float)(MSG_ReadByte( pbuf ) * 10.0f);
|
||||
break;
|
||||
case TE_ELIGHT:
|
||||
dl = CL_AllocElight( MSG_ReadShort( &buf ));
|
||||
dl->origin[0] = MSG_ReadCoord( &buf );
|
||||
dl->origin[1] = MSG_ReadCoord( &buf );
|
||||
dl->origin[2] = MSG_ReadCoord( &buf );
|
||||
dl->radius = MSG_ReadCoord( &buf );
|
||||
dl->color.r = MSG_ReadByte( &buf );
|
||||
dl->color.g = MSG_ReadByte( &buf );
|
||||
dl->color.b = MSG_ReadByte( &buf );
|
||||
life = (float)MSG_ReadByte( &buf ) * 0.1f;
|
||||
dl = CL_AllocElight( MSG_ReadShort( pbuf ));
|
||||
dl->origin[0] = MSG_ReadCoord( pbuf );
|
||||
dl->origin[1] = MSG_ReadCoord( pbuf );
|
||||
dl->origin[2] = MSG_ReadCoord( pbuf );
|
||||
dl->radius = MSG_ReadCoord( pbuf );
|
||||
dl->color.r = MSG_ReadByte( pbuf );
|
||||
dl->color.g = MSG_ReadByte( pbuf );
|
||||
dl->color.b = MSG_ReadByte( pbuf );
|
||||
life = (float)MSG_ReadByte( pbuf ) * 0.1f;
|
||||
dl->die = cl.time + life;
|
||||
dl->decay = MSG_ReadCoord( &buf );
|
||||
dl->decay = MSG_ReadCoord( pbuf );
|
||||
if( life != 0 ) dl->decay /= life;
|
||||
break;
|
||||
case TE_TEXTMESSAGE:
|
||||
CL_ParseTextMessage( &buf );
|
||||
CL_ParseTextMessage( pbuf );
|
||||
break;
|
||||
case TE_LINE:
|
||||
case TE_BOX:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos2[0] = MSG_ReadCoord( &buf );
|
||||
pos2[1] = MSG_ReadCoord( &buf );
|
||||
pos2[2] = MSG_ReadCoord( &buf );
|
||||
life = (float)(MSG_ReadShort( &buf ) * 0.1f);
|
||||
r = MSG_ReadByte( &buf );
|
||||
g = MSG_ReadByte( &buf );
|
||||
b = MSG_ReadByte( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
pos2[0] = MSG_ReadCoord( pbuf );
|
||||
pos2[1] = MSG_ReadCoord( pbuf );
|
||||
pos2[2] = MSG_ReadCoord( pbuf );
|
||||
life = (float)(MSG_ReadShort( pbuf ) * 0.1f);
|
||||
r = MSG_ReadByte( pbuf );
|
||||
g = MSG_ReadByte( pbuf );
|
||||
b = MSG_ReadByte( pbuf );
|
||||
if( type == TE_LINE ) R_ParticleLine( pos, pos2, r, g, b, life );
|
||||
else R_ParticleBox( pos, pos2, r, g, b, life );
|
||||
break;
|
||||
case TE_LARGEFUNNEL:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
modelIndex = MSG_ReadShort( &buf );
|
||||
flags = MSG_ReadShort( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
modelIndex = MSG_ReadShort( pbuf );
|
||||
flags = MSG_ReadShort( pbuf );
|
||||
R_LargeFunnel( pos, flags );
|
||||
R_FunnelSprite( pos, modelIndex, flags );
|
||||
break;
|
||||
case TE_BLOODSTREAM:
|
||||
case TE_BLOOD:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos2[0] = MSG_ReadCoord( &buf );
|
||||
pos2[1] = MSG_ReadCoord( &buf );
|
||||
pos2[2] = MSG_ReadCoord( &buf );
|
||||
color = MSG_ReadByte( &buf );
|
||||
count = MSG_ReadByte( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
pos2[0] = MSG_ReadCoord( pbuf );
|
||||
pos2[1] = MSG_ReadCoord( pbuf );
|
||||
pos2[2] = MSG_ReadCoord( pbuf );
|
||||
color = MSG_ReadByte( pbuf );
|
||||
count = MSG_ReadByte( pbuf );
|
||||
if( type == TE_BLOOD ) R_Blood( pos, pos2, color, count );
|
||||
else R_BloodStream( pos, pos2, color, count );
|
||||
break;
|
||||
case TE_SHOWLINE:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos2[0] = MSG_ReadCoord( &buf );
|
||||
pos2[1] = MSG_ReadCoord( &buf );
|
||||
pos2[2] = MSG_ReadCoord( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
pos2[0] = MSG_ReadCoord( pbuf );
|
||||
pos2[1] = MSG_ReadCoord( pbuf );
|
||||
pos2[2] = MSG_ReadCoord( pbuf );
|
||||
R_ShowLine( pos, pos2 );
|
||||
break;
|
||||
case TE_FIZZ:
|
||||
entityIndex = MSG_ReadShort( &buf );
|
||||
modelIndex = MSG_ReadShort( &buf );
|
||||
scale = MSG_ReadByte( &buf ); // same as density
|
||||
entityIndex = MSG_ReadShort( pbuf );
|
||||
modelIndex = MSG_ReadShort( pbuf );
|
||||
scale = MSG_ReadByte( pbuf ); // same as density
|
||||
pEnt = CL_GetEntityByIndex( entityIndex );
|
||||
R_FizzEffect( pEnt, modelIndex, scale );
|
||||
break;
|
||||
case TE_MODEL:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos2[0] = MSG_ReadCoord( &buf );
|
||||
pos2[1] = MSG_ReadCoord( &buf );
|
||||
pos2[2] = MSG_ReadCoord( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
pos2[0] = MSG_ReadCoord( pbuf );
|
||||
pos2[1] = MSG_ReadCoord( pbuf );
|
||||
pos2[2] = MSG_ReadCoord( pbuf );
|
||||
ang[0] = 0.0f;
|
||||
ang[1] = MSG_ReadAngle( &buf ); // yaw angle
|
||||
ang[1] = MSG_ReadAngle( pbuf ); // yaw angle
|
||||
ang[2] = 0.0f;
|
||||
modelIndex = MSG_ReadShort( &buf );
|
||||
flags = MSG_ReadByte( &buf ); // sound flags
|
||||
life = (float)(MSG_ReadByte( &buf ) * 0.1f);
|
||||
modelIndex = MSG_ReadShort( pbuf );
|
||||
flags = MSG_ReadByte( pbuf ); // sound flags
|
||||
life = (float)(MSG_ReadByte( pbuf ) * 0.1f);
|
||||
R_TempModel( pos, pos2, ang, life, modelIndex, flags );
|
||||
break;
|
||||
case TE_EXPLODEMODEL:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
vel = MSG_ReadCoord( &buf );
|
||||
modelIndex = MSG_ReadShort( &buf );
|
||||
count = MSG_ReadShort( &buf );
|
||||
life = (float)(MSG_ReadByte( &buf ) * 0.1f);
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
vel = MSG_ReadCoord( pbuf );
|
||||
modelIndex = MSG_ReadShort( pbuf );
|
||||
count = MSG_ReadShort( pbuf );
|
||||
life = (float)(MSG_ReadByte( pbuf ) * 0.1f);
|
||||
R_TempSphereModel( pos, vel, life, count, modelIndex );
|
||||
break;
|
||||
case TE_BREAKMODEL:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos2[0] = MSG_ReadCoord( &buf );
|
||||
pos2[1] = MSG_ReadCoord( &buf );
|
||||
pos2[2] = MSG_ReadCoord( &buf );
|
||||
ang[0] = MSG_ReadCoord( &buf );
|
||||
ang[1] = MSG_ReadCoord( &buf );
|
||||
ang[2] = MSG_ReadCoord( &buf );
|
||||
random = (float)MSG_ReadByte( &buf ) * 10.0f;
|
||||
modelIndex = MSG_ReadShort( &buf );
|
||||
count = MSG_ReadByte( &buf );
|
||||
life = (float)(MSG_ReadByte( &buf ) * 0.1f);
|
||||
flags = MSG_ReadByte( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
pos2[0] = MSG_ReadCoord( pbuf );
|
||||
pos2[1] = MSG_ReadCoord( pbuf );
|
||||
pos2[2] = MSG_ReadCoord( pbuf );
|
||||
ang[0] = MSG_ReadCoord( pbuf );
|
||||
ang[1] = MSG_ReadCoord( pbuf );
|
||||
ang[2] = MSG_ReadCoord( pbuf );
|
||||
random = (float)MSG_ReadByte( pbuf ) * 10.0f;
|
||||
modelIndex = MSG_ReadShort( pbuf );
|
||||
count = MSG_ReadByte( pbuf );
|
||||
life = (float)(MSG_ReadByte( pbuf ) * 0.1f);
|
||||
flags = MSG_ReadByte( pbuf );
|
||||
R_BreakModel( pos, pos2, ang, random, life, count, modelIndex, (char)flags );
|
||||
break;
|
||||
case TE_GUNSHOTDECAL:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
entityIndex = MSG_ReadShort( &buf );
|
||||
decalIndex = MSG_ReadByte( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
entityIndex = MSG_ReadShort( pbuf );
|
||||
decalIndex = MSG_ReadByte( pbuf );
|
||||
CL_DecalShoot( CL_DecalIndex( decalIndex ), entityIndex, 0, pos, 0 );
|
||||
R_BulletImpactParticles( pos );
|
||||
flags = COM_RandomLong( 0, 0x7fff );
|
||||
@@ -2248,139 +2268,139 @@ void CL_ParseTempEntity( sizebuf_t *msg )
|
||||
break;
|
||||
case TE_SPRAY:
|
||||
case TE_SPRITE_SPRAY:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos2[0] = MSG_ReadCoord( &buf );
|
||||
pos2[1] = MSG_ReadCoord( &buf );
|
||||
pos2[2] = MSG_ReadCoord( &buf );
|
||||
modelIndex = MSG_ReadShort( &buf );
|
||||
count = MSG_ReadByte( &buf );
|
||||
vel = (float)MSG_ReadByte( &buf );
|
||||
random = (float)MSG_ReadByte( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
pos2[0] = MSG_ReadCoord( pbuf );
|
||||
pos2[1] = MSG_ReadCoord( pbuf );
|
||||
pos2[2] = MSG_ReadCoord( pbuf );
|
||||
modelIndex = MSG_ReadShort( pbuf );
|
||||
count = MSG_ReadByte( pbuf );
|
||||
vel = (float)MSG_ReadByte( pbuf );
|
||||
random = (float)MSG_ReadByte( pbuf );
|
||||
if( type == TE_SPRAY )
|
||||
{
|
||||
flags = MSG_ReadByte( &buf ); // rendermode
|
||||
flags = MSG_ReadByte( pbuf ); // rendermode
|
||||
R_Spray( pos, pos2, modelIndex, count, vel, random, flags );
|
||||
}
|
||||
else R_Sprite_Spray( pos, pos2, modelIndex, count, vel * 2.0f, random );
|
||||
break;
|
||||
case TE_ARMOR_RICOCHET:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
scale = (float)(MSG_ReadByte( &buf ) * 0.1f);
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
scale = (float)(MSG_ReadByte( pbuf ) * 0.1f);
|
||||
R_RicochetSprite( pos, cl_sprite_ricochet, 0.1f, scale );
|
||||
R_RicochetSound( pos );
|
||||
break;
|
||||
case TE_PLAYERDECAL:
|
||||
color = MSG_ReadByte( &buf ) - 1; // playernum
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
entityIndex = MSG_ReadShort( &buf );
|
||||
decalIndex = MSG_ReadByte( &buf );
|
||||
color = MSG_ReadByte( pbuf ) - 1; // playernum
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
entityIndex = MSG_ReadShort( pbuf );
|
||||
decalIndex = MSG_ReadByte( pbuf );
|
||||
CL_PlayerDecal( color, decalIndex, entityIndex, pos );
|
||||
break;
|
||||
case TE_BUBBLES:
|
||||
case TE_BUBBLETRAIL:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos2[0] = MSG_ReadCoord( &buf );
|
||||
pos2[1] = MSG_ReadCoord( &buf );
|
||||
pos2[2] = MSG_ReadCoord( &buf );
|
||||
scale = MSG_ReadCoord( &buf ); // water height
|
||||
modelIndex = MSG_ReadShort( &buf );
|
||||
count = MSG_ReadByte( &buf );
|
||||
vel = MSG_ReadCoord( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
pos2[0] = MSG_ReadCoord( pbuf );
|
||||
pos2[1] = MSG_ReadCoord( pbuf );
|
||||
pos2[2] = MSG_ReadCoord( pbuf );
|
||||
scale = MSG_ReadCoord( pbuf ); // water height
|
||||
modelIndex = MSG_ReadShort( pbuf );
|
||||
count = MSG_ReadByte( pbuf );
|
||||
vel = MSG_ReadCoord( pbuf );
|
||||
if( type == TE_BUBBLES ) R_Bubbles( pos, pos2, scale, modelIndex, count, vel );
|
||||
else R_BubbleTrail( pos, pos2, scale, modelIndex, count, vel );
|
||||
break;
|
||||
case TE_BLOODSPRITE:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
modelIndex = MSG_ReadShort( &buf ); // sprite #1
|
||||
decalIndex = MSG_ReadShort( &buf ); // sprite #2
|
||||
color = MSG_ReadByte( &buf );
|
||||
scale = (float)MSG_ReadByte( &buf );
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
modelIndex = MSG_ReadShort( pbuf ); // sprite #1
|
||||
decalIndex = MSG_ReadShort( pbuf ); // sprite #2
|
||||
color = MSG_ReadByte( pbuf );
|
||||
scale = (float)MSG_ReadByte( pbuf );
|
||||
R_BloodSprite( pos, color, modelIndex, decalIndex, scale );
|
||||
break;
|
||||
case TE_PROJECTILE:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos2[0] = MSG_ReadCoord( &buf );
|
||||
pos2[1] = MSG_ReadCoord( &buf );
|
||||
pos2[2] = MSG_ReadCoord( &buf );
|
||||
modelIndex = MSG_ReadShort( &buf );
|
||||
life = MSG_ReadByte( &buf );
|
||||
color = MSG_ReadByte( &buf ); // playernum
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
pos2[0] = MSG_ReadCoord( pbuf );
|
||||
pos2[1] = MSG_ReadCoord( pbuf );
|
||||
pos2[2] = MSG_ReadCoord( pbuf );
|
||||
modelIndex = MSG_ReadShort( pbuf );
|
||||
life = MSG_ReadByte( pbuf );
|
||||
color = MSG_ReadByte( pbuf ); // playernum
|
||||
R_Projectile( pos, pos2, modelIndex, life, color, NULL );
|
||||
break;
|
||||
case TE_PLAYERSPRITES:
|
||||
color = MSG_ReadShort( &buf ); // entitynum
|
||||
modelIndex = MSG_ReadShort( &buf );
|
||||
count = MSG_ReadByte( &buf );
|
||||
random = (float)MSG_ReadByte( &buf );
|
||||
color = MSG_ReadShort( pbuf ); // entitynum
|
||||
modelIndex = MSG_ReadShort( pbuf );
|
||||
count = MSG_ReadByte( pbuf );
|
||||
random = (float)MSG_ReadByte( pbuf );
|
||||
R_PlayerSprites( color, modelIndex, count, random );
|
||||
break;
|
||||
case TE_PARTICLEBURST:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
scale = (float)MSG_ReadShort( &buf );
|
||||
color = MSG_ReadByte( &buf );
|
||||
life = (float)(MSG_ReadByte( &buf ) * 0.1f);
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
scale = (float)MSG_ReadShort( pbuf );
|
||||
color = MSG_ReadByte( pbuf );
|
||||
life = (float)(MSG_ReadByte( pbuf ) * 0.1f);
|
||||
R_ParticleBurst( pos, scale, color, life );
|
||||
break;
|
||||
case TE_FIREFIELD:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
scale = (float)MSG_ReadShort( &buf );
|
||||
modelIndex = MSG_ReadShort( &buf );
|
||||
count = MSG_ReadByte( &buf );
|
||||
flags = MSG_ReadByte( &buf );
|
||||
life = (float)(MSG_ReadByte( &buf ) * 0.1f);
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
scale = (float)MSG_ReadShort( pbuf );
|
||||
modelIndex = MSG_ReadShort( pbuf );
|
||||
count = MSG_ReadByte( pbuf );
|
||||
flags = MSG_ReadByte( pbuf );
|
||||
life = (float)(MSG_ReadByte( pbuf ) * 0.1f);
|
||||
R_FireField( pos, scale, modelIndex, count, flags, life );
|
||||
break;
|
||||
case TE_PLAYERATTACHMENT:
|
||||
color = MSG_ReadByte( &buf ); // playernum
|
||||
scale = MSG_ReadCoord( &buf ); // height
|
||||
modelIndex = MSG_ReadShort( &buf );
|
||||
life = (float)(MSG_ReadShort( &buf ) * 0.1f);
|
||||
color = MSG_ReadByte( pbuf ); // playernum
|
||||
scale = MSG_ReadCoord( pbuf ); // height
|
||||
modelIndex = MSG_ReadShort( pbuf );
|
||||
life = (float)(MSG_ReadShort( pbuf ) * 0.1f);
|
||||
R_AttachTentToPlayer( color, modelIndex, scale, life );
|
||||
break;
|
||||
case TE_KILLPLAYERATTACHMENTS:
|
||||
color = MSG_ReadByte( &buf ); // playernum
|
||||
color = MSG_ReadByte( pbuf ); // playernum
|
||||
R_KillAttachedTents( color );
|
||||
break;
|
||||
case TE_MULTIGUNSHOT:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos2[0] = MSG_ReadCoord( &buf ) * 0.1f;
|
||||
pos2[1] = MSG_ReadCoord( &buf ) * 0.1f;
|
||||
pos2[2] = MSG_ReadCoord( &buf ) * 0.1f;
|
||||
ang[0] = MSG_ReadCoord( &buf ) * 0.01f;
|
||||
ang[1] = MSG_ReadCoord( &buf ) * 0.01f;
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
pos2[0] = MSG_ReadCoord( pbuf ) * 0.1f;
|
||||
pos2[1] = MSG_ReadCoord( pbuf ) * 0.1f;
|
||||
pos2[2] = MSG_ReadCoord( pbuf ) * 0.1f;
|
||||
ang[0] = MSG_ReadCoord( pbuf ) * 0.01f;
|
||||
ang[1] = MSG_ReadCoord( pbuf ) * 0.01f;
|
||||
ang[2] = 0.0f;
|
||||
count = MSG_ReadByte( &buf );
|
||||
decalIndices[0] = MSG_ReadByte( &buf );
|
||||
count = MSG_ReadByte( pbuf );
|
||||
decalIndices[0] = MSG_ReadByte( pbuf );
|
||||
R_MultiGunshot( pos, pos2, ang, count, 1, decalIndices );
|
||||
break;
|
||||
case TE_USERTRACER:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
pos2[0] = MSG_ReadCoord( &buf );
|
||||
pos2[1] = MSG_ReadCoord( &buf );
|
||||
pos2[2] = MSG_ReadCoord( &buf );
|
||||
life = (float)(MSG_ReadByte( &buf ) * 0.1f);
|
||||
color = MSG_ReadByte( &buf );
|
||||
scale = (float)(MSG_ReadByte( &buf ) * 0.1f);
|
||||
pos[0] = MSG_ReadCoord( pbuf );
|
||||
pos[1] = MSG_ReadCoord( pbuf );
|
||||
pos[2] = MSG_ReadCoord( pbuf );
|
||||
pos2[0] = MSG_ReadCoord( pbuf );
|
||||
pos2[1] = MSG_ReadCoord( pbuf );
|
||||
pos2[2] = MSG_ReadCoord( pbuf );
|
||||
life = (float)(MSG_ReadByte( pbuf ) * 0.1f);
|
||||
color = MSG_ReadByte( pbuf );
|
||||
scale = (float)(MSG_ReadByte( pbuf ) * 0.1f);
|
||||
R_UserTracerParticle( pos, pos2, life, color, scale, 0, NULL );
|
||||
break;
|
||||
default:
|
||||
@@ -2389,7 +2409,7 @@ void CL_ParseTempEntity( sizebuf_t *msg )
|
||||
}
|
||||
|
||||
// throw warning
|
||||
if( MSG_CheckOverflow( &buf ))
|
||||
if( MSG_CheckOverflow( pbuf ))
|
||||
Con_DPrintf( S_WARN "%s: overflow TE message %i\n", __func__, type );
|
||||
}
|
||||
|
||||
@@ -3113,4 +3133,3 @@ void CL_ClearEffects( void )
|
||||
CL_ClearParticles ();
|
||||
CL_ClearLightStyles ();
|
||||
}
|
||||
|
||||
|
||||
@@ -278,6 +278,8 @@ typedef struct
|
||||
int lostpackets; // count lost packets and show dialog in menu
|
||||
|
||||
double frametime_remainder;
|
||||
|
||||
uint worldmapCRC;
|
||||
} client_t;
|
||||
|
||||
/*
|
||||
@@ -309,14 +311,6 @@ typedef enum
|
||||
CL_CHANGELEVEL, // draw 'loading' during changelevel
|
||||
} scrstate_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PROTO_CURRENT = 0, // Xash3D 49
|
||||
PROTO_LEGACY = 1, // Xash3D 48
|
||||
PROTO_QUAKE = 2, // Quake 15
|
||||
PROTO_GOLDSRC = 3, // GoldSrc 48
|
||||
} connprotocol_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[32];
|
||||
@@ -760,7 +754,7 @@ qboolean CL_PrecacheResources( void );
|
||||
void CL_SetupOverviewParams( void );
|
||||
void CL_UpdateFrameLerp( void );
|
||||
int CL_IsDevOverviewMode( void );
|
||||
void CL_SignonReply( void );
|
||||
void CL_SignonReply( connprotocol_t proto );
|
||||
void CL_ClearState( void );
|
||||
|
||||
//
|
||||
@@ -790,8 +784,8 @@ int CL_GetDemoComment( const char *demoname, char *comment );
|
||||
//
|
||||
// cl_events.c
|
||||
//
|
||||
void CL_ParseEvent( sizebuf_t *msg );
|
||||
void CL_ParseReliableEvent( sizebuf_t *msg );
|
||||
void CL_ParseEvent( sizebuf_t *msg, connprotocol_t proto );
|
||||
void CL_ParseReliableEvent( sizebuf_t *msg, connprotocol_t proto );
|
||||
void CL_SetEventIndex( const char *szEvName, int ev_index );
|
||||
void CL_PlaybackEvent( int flags, const edict_t *pInvoker, word eventindex, float delay, float *origin,
|
||||
float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 );
|
||||
@@ -868,20 +862,22 @@ _inline cl_entity_t *CL_EDICT_NUM( int n )
|
||||
// cl_parse.c
|
||||
//
|
||||
void CL_ParseSetAngle( sizebuf_t *msg );
|
||||
void CL_ParseServerData( sizebuf_t *msg, qboolean legacy );
|
||||
void CL_ParseLightStyle( sizebuf_t *msg );
|
||||
void CL_UpdateUserinfo( sizebuf_t *msg, qboolean legacy );
|
||||
void CL_ParseServerData( sizebuf_t *msg, connprotocol_t proto );
|
||||
void CL_ParseLightStyle( sizebuf_t *msg, connprotocol_t proto );
|
||||
void CL_UpdateUserinfo( sizebuf_t *msg, connprotocol_t proto );
|
||||
void CL_ParseResource( sizebuf_t *msg );
|
||||
void CL_ParseClientData( sizebuf_t *msg );
|
||||
void CL_ParseClientData( sizebuf_t *msg, connprotocol_t proto );
|
||||
void CL_UpdateUserPings( sizebuf_t *msg );
|
||||
void CL_ParseParticles( sizebuf_t *msg );
|
||||
void CL_ParseRestoreSoundPacket( sizebuf_t *msg );
|
||||
void CL_ParseBaseline( sizebuf_t *msg, qboolean legacy );
|
||||
void CL_ParseSignon( sizebuf_t *msg );
|
||||
void CL_ParseBaseline( sizebuf_t *msg, connprotocol_t proto );
|
||||
void CL_ParseSignon( sizebuf_t *msg, connprotocol_t proto );
|
||||
void CL_ParseRestore( sizebuf_t *msg );
|
||||
void CL_ParseStaticEntity( sizebuf_t *msg );
|
||||
void CL_ParseStaticDecal( sizebuf_t *msg );
|
||||
void CL_ParseAddAngle( sizebuf_t *msg );
|
||||
void CL_RegisterUserMessage( sizebuf_t *msg );
|
||||
void CL_ParseResourceList( sizebuf_t *msg, connprotocol_t proto );
|
||||
void CL_ParseMovevars( sizebuf_t *msg );
|
||||
void CL_ParseResourceRequest( sizebuf_t *msg );
|
||||
void CL_ParseCustomization( sizebuf_t *msg );
|
||||
@@ -890,18 +886,21 @@ void CL_ParseSoundFade( sizebuf_t *msg );
|
||||
void CL_ParseFileTransferFailed( sizebuf_t *msg );
|
||||
void CL_ParseHLTV( sizebuf_t *msg );
|
||||
void CL_ParseDirector( sizebuf_t *msg );
|
||||
void CL_ParseVoiceInit( sizebuf_t *msg );
|
||||
void CL_ParseVoiceData( sizebuf_t *msg );
|
||||
void CL_ParseResLocation( sizebuf_t *msg );
|
||||
void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext, const connprotocol_t proto );
|
||||
void CL_ParseServerMessage( sizebuf_t *msg );
|
||||
void CL_ParseTempEntity( sizebuf_t *msg );
|
||||
void CL_ParseTempEntity( sizebuf_t *msg, connprotocol_t proto );
|
||||
qboolean CL_DispatchUserMessage( const char *pszName, int iSize, void *pbuf );
|
||||
qboolean CL_RequestMissingResources( void );
|
||||
void CL_RegisterResources ( sizebuf_t *msg );
|
||||
void CL_RegisterResources( sizebuf_t *msg, connprotocol_t proto );
|
||||
void CL_ParseViewEntity( sizebuf_t *msg );
|
||||
void CL_ParseServerTime( sizebuf_t *msg );
|
||||
void CL_ParseUserMessage( sizebuf_t *msg, int svc_num );
|
||||
void CL_ParseFinaleCutscene( sizebuf_t *msg, int level );
|
||||
void CL_ParseTextMessage( sizebuf_t *msg );
|
||||
void CL_ParseExec( sizebuf_t *msg );
|
||||
void CL_BatchResourceRequest( qboolean initialize );
|
||||
int CL_EstimateNeededResources( void );
|
||||
|
||||
@@ -911,6 +910,11 @@ int CL_EstimateNeededResources( void );
|
||||
void CL_ParseLegacyServerMessage( sizebuf_t *msg );
|
||||
void CL_LegacyPrecache_f( void );
|
||||
|
||||
//
|
||||
// cl_parse_gs.c
|
||||
//
|
||||
void CL_ParseGoldSrcServerMessage( sizebuf_t *msg );
|
||||
|
||||
//
|
||||
// cl_scrn.c
|
||||
//
|
||||
@@ -975,7 +979,9 @@ void CL_ParseQuakeMessage( sizebuf_t *msg );
|
||||
//
|
||||
struct channel_s;
|
||||
struct rawchan_s;
|
||||
int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta );
|
||||
qboolean CL_ValidateDeltaPacket( uint oldpacket, frame_t *oldframe );
|
||||
int CL_UpdateOldEntNum( int oldindex, frame_t *oldframe, entity_state_t **oldent );
|
||||
int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta, connprotocol_t proto );
|
||||
qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType );
|
||||
void CL_ResetLatchedVars( cl_entity_t *ent, qboolean full_reset );
|
||||
qboolean CL_GetEntitySpatialization( struct channel_s *ch );
|
||||
|
||||
@@ -524,6 +524,12 @@ static void SND_Spatialize( channel_t *ch )
|
||||
dist = VectorNormalizeLength( source_vec );
|
||||
dot = DotProduct( s_listener.right, source_vec );
|
||||
|
||||
if( !FBitSet( host.bugcomp, BUGCOMP_SPATIALIZE_SOUND_WITH_ATTN_NONE ))
|
||||
{
|
||||
// don't pan sounds with no attenuation
|
||||
if( ch->dist_mult <= 0.0f ) dot = 0.0f;
|
||||
}
|
||||
|
||||
// fill out channel volumes for single location
|
||||
S_SpatializeChannel( &ch->leftvol, &ch->rightvol, ch->master_vol, gain, dot, dist * ch->dist_mult );
|
||||
|
||||
|
||||
@@ -112,6 +112,9 @@ typedef enum
|
||||
#include "con_nprint.h"
|
||||
#include "crclib.h"
|
||||
#include "ref_api.h"
|
||||
#define FSCALLBACK_OVERRIDE_OPEN
|
||||
#define FSCALLBACK_OVERRIDE_LOADFILE
|
||||
#define FSCALLBACK_OVERRIDE_MALLOC_LIKE
|
||||
#include "fscallback.h"
|
||||
|
||||
// PERFORMANCE INFO
|
||||
@@ -273,6 +276,9 @@ typedef enum bugcomp_e
|
||||
// rewrites mod's attempts to write GoldSrc-specific messages into Xash protocol
|
||||
// (new wrappers are added by request)
|
||||
BUGCOMP_MESSAGE_REWRITE_FACILITY_FLAG = BIT( 1 ),
|
||||
|
||||
// makes sound with no attenuation spatialized, like in GoldSrc
|
||||
BUGCOMP_SPATIALIZE_SOUND_WITH_ATTN_NONE = BIT( 2 ),
|
||||
} bugcomp_t;
|
||||
|
||||
typedef struct host_parm_s
|
||||
@@ -359,12 +365,49 @@ extern host_parm_t host;
|
||||
|
||||
typedef void (*xcommand_t)( void );
|
||||
|
||||
//
|
||||
// zone.c
|
||||
//
|
||||
void Memory_Init( void );
|
||||
void _Mem_Free( void *data, const char *filename, int fileline );
|
||||
void *_Mem_Realloc( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
ALLOC_CHECK( 3 ) WARN_UNUSED_RESULT;
|
||||
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
ALLOC_CHECK( 2 ) MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
poolhandle_t _Mem_AllocPool( const char *name, const char *filename, int fileline )
|
||||
WARN_UNUSED_RESULT;
|
||||
void _Mem_FreePool( poolhandle_t *poolptr, const char *filename, int fileline );
|
||||
void _Mem_EmptyPool( poolhandle_t poolptr, const char *filename, int fileline );
|
||||
void _Mem_Check( const char *filename, int fileline );
|
||||
qboolean Mem_IsAllocatedExt( poolhandle_t poolptr, void *data );
|
||||
void Mem_PrintList( size_t minallocationsize );
|
||||
void Mem_PrintStats( void );
|
||||
|
||||
#define Mem_Malloc( pool, size ) _Mem_Alloc( pool, size, false, __FILE__, __LINE__ )
|
||||
#define Mem_Calloc( pool, size ) _Mem_Alloc( pool, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Realloc( pool, ptr, size ) _Mem_Realloc( pool, ptr, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Free( mem ) _Mem_Free( mem, __FILE__, __LINE__ )
|
||||
#define Mem_AllocPool( name ) _Mem_AllocPool( name, __FILE__, __LINE__ )
|
||||
#define Mem_FreePool( pool ) _Mem_FreePool( pool, __FILE__, __LINE__ )
|
||||
#define Mem_EmptyPool( pool ) _Mem_EmptyPool( pool, __FILE__, __LINE__ )
|
||||
#define Mem_IsAllocated( mem ) Mem_IsAllocatedExt( NULL, mem )
|
||||
#define Mem_Check() _Mem_Check( __FILE__, __LINE__ )
|
||||
|
||||
//
|
||||
// filesystem_engine.c
|
||||
//
|
||||
void FS_Init( const char *basedir );
|
||||
void FS_Shutdown( void );
|
||||
void *FS_GetNativeObject( const char *obj );
|
||||
int FS_Close( file_t *file );
|
||||
search_t *FS_Search( const char *pattern, int caseinsensitive, int gamedironly )
|
||||
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
file_t *FS_Open( const char *filepath, const char *mode, qboolean gamedironly )
|
||||
MALLOC_LIKE( FS_Close, 1 ) WARN_UNUSED_RESULT;
|
||||
byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly )
|
||||
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr )
|
||||
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
|
||||
//
|
||||
// cmd.c
|
||||
@@ -397,30 +440,6 @@ void Cmd_ExecuteString( const char *text );
|
||||
void Cmd_ForwardToServer( void );
|
||||
void Cmd_Escape( char *newCommand, const char *oldCommand, int len );
|
||||
|
||||
//
|
||||
// zone.c
|
||||
//
|
||||
void Memory_Init( void );
|
||||
void *_Mem_Realloc( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline ) ALLOC_CHECK( 3 );
|
||||
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline ) ALLOC_CHECK( 2 );
|
||||
poolhandle_t _Mem_AllocPool( const char *name, const char *filename, int fileline );
|
||||
void _Mem_FreePool( poolhandle_t *poolptr, const char *filename, int fileline );
|
||||
void _Mem_EmptyPool( poolhandle_t poolptr, const char *filename, int fileline );
|
||||
void _Mem_Free( void *data, const char *filename, int fileline );
|
||||
void _Mem_Check( const char *filename, int fileline );
|
||||
qboolean Mem_IsAllocatedExt( poolhandle_t poolptr, void *data );
|
||||
void Mem_PrintList( size_t minallocationsize );
|
||||
void Mem_PrintStats( void );
|
||||
|
||||
#define Mem_Malloc( pool, size ) _Mem_Alloc( pool, size, false, __FILE__, __LINE__ )
|
||||
#define Mem_Calloc( pool, size ) _Mem_Alloc( pool, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Realloc( pool, ptr, size ) _Mem_Realloc( pool, ptr, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Free( mem ) _Mem_Free( mem, __FILE__, __LINE__ )
|
||||
#define Mem_AllocPool( name ) _Mem_AllocPool( name, __FILE__, __LINE__ )
|
||||
#define Mem_FreePool( pool ) _Mem_FreePool( pool, __FILE__, __LINE__ )
|
||||
#define Mem_EmptyPool( pool ) _Mem_EmptyPool( pool, __FILE__, __LINE__ )
|
||||
#define Mem_IsAllocated( mem ) Mem_IsAllocatedExt( NULL, mem )
|
||||
#define Mem_Check() _Mem_Check( __FILE__, __LINE__ )
|
||||
|
||||
//
|
||||
// imagelib
|
||||
@@ -431,10 +450,10 @@ void Image_Setup( void );
|
||||
void Image_Init( void );
|
||||
void Image_Shutdown( void );
|
||||
void Image_AddCmdFlags( uint flags );
|
||||
rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size );
|
||||
qboolean FS_SaveImage( const char *filename, rgbdata_t *pix );
|
||||
rgbdata_t *FS_CopyImage( rgbdata_t *in );
|
||||
void FS_FreeImage( rgbdata_t *pack );
|
||||
rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size ) MALLOC_LIKE( FS_FreeImage, 1 ) WARN_UNUSED_RESULT;
|
||||
qboolean FS_SaveImage( const char *filename, rgbdata_t *pix );
|
||||
rgbdata_t *FS_CopyImage( rgbdata_t *in ) MALLOC_LIKE( FS_FreeImage, 1 ) WARN_UNUSED_RESULT;
|
||||
extern const bpc_desc_t PFDesc[]; // image get pixelformat
|
||||
qboolean Image_Process( rgbdata_t **pix, int width, int height, uint flags, float reserved );
|
||||
void Image_PaletteHueReplace( byte *palSrc, int newHue, int start, int end, int pal_size );
|
||||
@@ -489,14 +508,14 @@ typedef struct
|
||||
//
|
||||
void Sound_Init( void );
|
||||
void Sound_Shutdown( void );
|
||||
wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size );
|
||||
void FS_FreeSound( wavdata_t *pack );
|
||||
stream_t *FS_OpenStream( const char *filename );
|
||||
void FS_FreeStream( stream_t *stream );
|
||||
wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size ) MALLOC_LIKE( FS_FreeSound, 1 ) WARN_UNUSED_RESULT;
|
||||
stream_t *FS_OpenStream( const char *filename ) MALLOC_LIKE( FS_FreeStream, 1 ) WARN_UNUSED_RESULT;
|
||||
wavdata_t *FS_StreamInfo( stream_t *stream );
|
||||
int FS_ReadStream( stream_t *stream, int bytes, void *buffer );
|
||||
int FS_SetStreamPos( stream_t *stream, int newpos );
|
||||
int FS_GetStreamPos( stream_t *stream );
|
||||
void FS_FreeStream( stream_t *stream );
|
||||
qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint flags );
|
||||
uint Sound_GetApproxWavePlayLen( const char *filepath );
|
||||
qboolean Sound_SupportedFileFormat( const char *fileext );
|
||||
@@ -561,7 +580,7 @@ qboolean SV_Active( void );
|
||||
char *COM_MemFgets( byte *pMemFile, int fileSize, int *filePos, char *pBuffer, int bufferSize );
|
||||
void COM_HexConvert( const char *pszInput, int nInputLength, byte *pOutput );
|
||||
int COM_SaveFile( const char *filename, const void *data, int len );
|
||||
byte* COM_LoadFileForMe( const char *filename, int *pLength );
|
||||
byte *COM_LoadFileForMe( const char *filename, int *pLength ) MALLOC_LIKE( free, 1 );
|
||||
qboolean COM_IsSafeFileToDownload( const char *filename );
|
||||
cvar_t *pfnCVarGetPointer( const char *szVarName );
|
||||
int pfnDrawConsoleString( int x, int y, char *string );
|
||||
@@ -651,6 +670,15 @@ void HPAK_FlushHostQueue( void );
|
||||
#define INPUT_DEVICE_JOYSTICK (1<<2)
|
||||
#define INPUT_DEVICE_VR (1<<3)
|
||||
|
||||
|
||||
typedef enum connprotocol_e
|
||||
{
|
||||
PROTO_CURRENT = 0, // Xash3D 49
|
||||
PROTO_LEGACY, // Xash3D 48
|
||||
PROTO_QUAKE, // Quake 15
|
||||
PROTO_GOLDSRC, // GoldSrc 48
|
||||
} connprotocol_t;
|
||||
|
||||
// shared calls
|
||||
struct physent_s;
|
||||
struct sv_client_s;
|
||||
@@ -661,10 +689,9 @@ qboolean CL_IsThirdPerson( void );
|
||||
qboolean CL_IsIntermission( void );
|
||||
qboolean CL_Initialized( void );
|
||||
char *CL_Userinfo( void );
|
||||
void CL_LegacyUpdateInfo( void );
|
||||
void CL_CharEvent( int key );
|
||||
qboolean CL_DisableVisibility( void );
|
||||
byte *COM_LoadFile( const char *filename, int usehunk, int *pLength );
|
||||
byte *COM_LoadFile( const char *filename, int usehunk, int *pLength ) MALLOC_LIKE( free, 1 );
|
||||
struct cmd_s *Cmd_GetFirstFunctionHandle( void );
|
||||
struct cmd_s *Cmd_GetNextFunctionHandle( struct cmd_s *cmd );
|
||||
struct cmdalias_s *Cmd_AliasGetList( void );
|
||||
@@ -749,6 +776,15 @@ int COM_CompareFileTime( const char *filename1, const char *filename2, int *iCom
|
||||
char *va( const char *format, ... ) _format( 1 );
|
||||
qboolean CRC32_MapFile( dword *crcvalue, const char *filename, qboolean multiplayer );
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
connprotocol_t CL_Protocol( void );
|
||||
#else
|
||||
static inline connprotocol_t CL_Protocol( void )
|
||||
{
|
||||
return PROTO_CURRENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline qboolean Host_IsLocalGame( void )
|
||||
{
|
||||
if( SV_Active( ))
|
||||
@@ -798,6 +834,16 @@ void NET_MasterClear( void );
|
||||
void NET_MasterShutdown( void );
|
||||
qboolean NET_GetMaster( netadr_t from, uint *challenge, double *last_heartbeat );
|
||||
|
||||
//
|
||||
// munge.c
|
||||
//
|
||||
void COM_Munge( byte *data, size_t len, int seq );
|
||||
void COM_UnMunge( byte *data, size_t len, int seq );
|
||||
void COM_Munge2( byte *data, size_t len, int seq );
|
||||
void COM_UnMunge2( byte *data, size_t len, int seq );
|
||||
void COM_Munge3( byte *data, size_t len, int seq );
|
||||
void COM_UnMunge3( byte *data, size_t len, int seq );
|
||||
|
||||
//
|
||||
// sounds.c
|
||||
//
|
||||
|
||||
@@ -70,15 +70,14 @@ find the specified variable by name
|
||||
*/
|
||||
convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group )
|
||||
{
|
||||
// TODO: ignore group for cvar
|
||||
#if defined(XASH_HASHED_VARS)
|
||||
return (convar_t *)BaseCmd_Find( HM_CVAR, var_name );
|
||||
#else
|
||||
convar_t *var;
|
||||
convar_t *var;
|
||||
|
||||
if( !var_name )
|
||||
return NULL;
|
||||
|
||||
#if defined(XASH_HASHED_VARS) // TODO: ignore_group
|
||||
var = BaseCmd_Find( HM_CVAR, var_name );
|
||||
#else
|
||||
for( var = cvar_vars; var; var = var->next )
|
||||
{
|
||||
if( ignore_group && FBitSet( ignore_group, var->flags ))
|
||||
@@ -87,9 +86,13 @@ convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group )
|
||||
if( !Q_stricmp( var_name, var->name ))
|
||||
return var;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
// HACKHACK: HL25 compatibility
|
||||
if( !var && !Q_stricmp( var_name, "gl_widescreen_yfov" ))
|
||||
var = Cvar_FindVarExt( "r_adjust_fov", ignore_group );
|
||||
|
||||
return var;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -272,6 +275,15 @@ static qboolean Cvar_ValidateVarName( const char *s, qboolean isvalue )
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Cvar_Free( convar_t *var )
|
||||
{
|
||||
freestring( var->name );
|
||||
freestring( var->string );
|
||||
freestring( var->def_string );
|
||||
freestring( var->desc );
|
||||
Mem_Free( var );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_UnlinkVar
|
||||
@@ -311,17 +323,13 @@ static int Cvar_UnlinkVar( const char *var_name, int group )
|
||||
#endif
|
||||
|
||||
// unlink variable from list
|
||||
freestring( var->string );
|
||||
*prev = var->next;
|
||||
|
||||
// only allocated cvars can throw these fields
|
||||
if( FBitSet( var->flags, FCVAR_ALLOCATED ))
|
||||
{
|
||||
freestring( var->name );
|
||||
freestring( var->def_string );
|
||||
freestring( var->desc );
|
||||
Mem_Free( var );
|
||||
}
|
||||
Cvar_Free( var );
|
||||
else
|
||||
freestring( var->string );
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -1217,6 +1225,20 @@ static void Cvar_List_f( void )
|
||||
Con_Printf( "\n%i cvars\n", count );
|
||||
}
|
||||
|
||||
static qboolean Cvar_ValidateUnlinkGroup( int group )
|
||||
{
|
||||
if( FBitSet( group, FCVAR_EXTDLL ) && !Cvar_VariableInteger( "host_gameloaded" ))
|
||||
return false;
|
||||
|
||||
if( FBitSet( group, FCVAR_CLIENTDLL ) && !Cvar_VariableInteger( "host_clientloaded" ))
|
||||
return false;
|
||||
|
||||
if( FBitSet( group, FCVAR_GAMEUIDLL ) && !Cvar_VariableInteger( "host_gameuiloaded" ))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_Unlink
|
||||
@@ -1228,19 +1250,95 @@ void Cvar_Unlink( int group )
|
||||
{
|
||||
int count;
|
||||
|
||||
if( Cvar_VariableInteger( "host_gameloaded" ) && FBitSet( group, FCVAR_EXTDLL ))
|
||||
return;
|
||||
|
||||
if( Cvar_VariableInteger( "host_clientloaded" ) && FBitSet( group, FCVAR_CLIENTDLL ))
|
||||
return;
|
||||
|
||||
if( Cvar_VariableInteger( "host_gameuiloaded" ) && FBitSet( group, FCVAR_GAMEUIDLL ))
|
||||
if( !Cvar_ValidateUnlinkGroup( group ))
|
||||
return;
|
||||
|
||||
count = Cvar_UnlinkVar( NULL, group );
|
||||
Con_Reportf( "unlink %i cvars\n", count );
|
||||
}
|
||||
|
||||
pending_cvar_t *Cvar_PrepareToUnlink( int group )
|
||||
{
|
||||
pending_cvar_t *list = NULL;
|
||||
pending_cvar_t *tail = NULL;
|
||||
convar_t *cv;
|
||||
|
||||
for( cv = cvar_vars; cv != NULL; cv = cv->next )
|
||||
{
|
||||
size_t namelen;
|
||||
pending_cvar_t *p;
|
||||
|
||||
if( !FBitSet( cv->flags, group ))
|
||||
continue;
|
||||
|
||||
namelen = Q_strlen( cv->name ) + 1;
|
||||
p = Mem_Malloc( host.mempool, sizeof( *list ) + namelen );
|
||||
p->next = NULL;
|
||||
p->cv_cur = cv;
|
||||
p->cv_next = cv->next;
|
||||
p->cv_allocated = FBitSet( cv->flags, FCVAR_ALLOCATED ) ? true : false;
|
||||
Q_strncpy( p->cv_name, cv->name, namelen );
|
||||
|
||||
if( list == NULL )
|
||||
list = p;
|
||||
else
|
||||
tail->next = p;
|
||||
|
||||
tail = p;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void Cvar_UnlinkPendingCvars( pending_cvar_t *list )
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
while( list != NULL )
|
||||
{
|
||||
pending_cvar_t *next = list->next;
|
||||
convar_t *cv_prev, *cv;
|
||||
|
||||
for( cv_prev = NULL, cv = cvar_vars; cv != NULL; cv_prev = cv, cv = cv->next )
|
||||
{
|
||||
if( cv == list->cv_cur )
|
||||
break;
|
||||
}
|
||||
|
||||
if( cv == NULL )
|
||||
{
|
||||
Con_Reportf( "%s: can't find %s in variable list\n", __func__, list->cv_name );
|
||||
Mem_Free( list );
|
||||
list = next;
|
||||
continue;
|
||||
}
|
||||
|
||||
// unlink cvar from list
|
||||
BaseCmd_Remove( HM_CVAR, list->cv_name );
|
||||
if( cv_prev != NULL )
|
||||
cv_prev->next = list->cv_next;
|
||||
else cvar_vars = list->cv_next;
|
||||
|
||||
if( list->cv_allocated )
|
||||
Cvar_Free( list->cv_cur );
|
||||
else
|
||||
{
|
||||
// TODO: can't free cvar string here because
|
||||
// it's not safe to access cv_cur and
|
||||
// can't save string pointer because it could've been changed
|
||||
// and pointer to it is already lost
|
||||
// freestring( list->cv_string );
|
||||
}
|
||||
|
||||
// now free pending cvar
|
||||
Mem_Free( list );
|
||||
list = next;
|
||||
count++;
|
||||
}
|
||||
|
||||
Con_Reportf( "unlink %i cvars\n", count );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_Init
|
||||
|
||||
@@ -18,6 +18,18 @@ GNU General Public License for more details.
|
||||
|
||||
#include "cvardef.h"
|
||||
|
||||
// As some mods dynamically allocate cvars and free them without notifying the engine
|
||||
// let's construct a list of cvars that must be removed
|
||||
typedef struct pending_cvar_s
|
||||
{
|
||||
struct pending_cvar_s *next;
|
||||
|
||||
convar_t *cv_cur; // preserve the data that might get freed
|
||||
convar_t *cv_next;
|
||||
qboolean cv_allocated; // if it's allocated by us, it's safe to access cv_cur
|
||||
char cv_name[];
|
||||
} pending_cvar_t;
|
||||
|
||||
cvar_t *Cvar_GetList( void );
|
||||
#define Cvar_FindVar( name ) Cvar_FindVarExt( name, 0 )
|
||||
convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group );
|
||||
@@ -43,4 +55,7 @@ void Cvar_Init( void );
|
||||
void Cvar_PostFSInit( void );
|
||||
void Cvar_Unlink( int group );
|
||||
|
||||
pending_cvar_t *Cvar_PrepareToUnlink( int group );
|
||||
void Cvar_UnlinkPendingCvars( pending_cvar_t *pending_cvars );
|
||||
|
||||
#endif//CVAR_H
|
||||
|
||||
@@ -134,11 +134,6 @@ void GAME_EXPORT S_StopSound(int entnum, int channel, const char *soundname)
|
||||
|
||||
}
|
||||
|
||||
int S_GetCurrentStaticSounds( soundlist_t *pout, int size )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GAME_EXPORT CL_GetMaxClients( void )
|
||||
{
|
||||
return 0;
|
||||
|
||||
@@ -27,6 +27,31 @@ fs_globals_t *FI;
|
||||
static pfnCreateInterface_t fs_pfnCreateInterface;
|
||||
static HINSTANCE fs_hInstance;
|
||||
|
||||
search_t *FS_Search( const char *pattern, int caseinsensitive, int gamedironly )
|
||||
{
|
||||
return g_fsapi.Search( pattern, caseinsensitive, gamedironly );
|
||||
}
|
||||
|
||||
int FS_Close( file_t *file )
|
||||
{
|
||||
return g_fsapi.Close( file );
|
||||
}
|
||||
|
||||
file_t *FS_Open( const char *filepath, const char *mode, qboolean gamedironly )
|
||||
{
|
||||
return g_fsapi.Open( filepath, mode, gamedironly );
|
||||
}
|
||||
|
||||
byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly )
|
||||
{
|
||||
return g_fsapi.LoadFile( path, filesizeptr, gamedironly );
|
||||
}
|
||||
|
||||
byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr )
|
||||
{
|
||||
return g_fsapi.LoadDirectFile( path, filesizeptr );
|
||||
}
|
||||
|
||||
static void COM_StripDirectorySlash( char *pname )
|
||||
{
|
||||
size_t len;
|
||||
|
||||
@@ -73,6 +73,7 @@ static feature_message_t bugcomp_features[] =
|
||||
{
|
||||
{ BUGCOMP_PENTITYOFENTINDEX_FLAG, "pfnPEntityOfEntIndex bugfix revert", "peoei" },
|
||||
{ BUGCOMP_MESSAGE_REWRITE_FACILITY_FLAG, "GoldSrc Message Rewrite Facility", "gsmrf" },
|
||||
{ BUGCOMP_SPATIALIZE_SOUND_WITH_ATTN_NONE, "spatialize sounds with zero attenuation", "sp_attn_none" },
|
||||
};
|
||||
|
||||
static feature_message_t engine_features[] =
|
||||
|
||||
@@ -110,7 +110,7 @@ void Image_Reset( void )
|
||||
image.size = 0;
|
||||
}
|
||||
|
||||
static rgbdata_t *ImagePack( void )
|
||||
static MALLOC_LIKE( FS_FreeImage, 1 ) rgbdata_t *ImagePack( void )
|
||||
{
|
||||
rgbdata_t *pack;
|
||||
|
||||
@@ -547,7 +547,7 @@ static void Test_CheckImage( const char *name, rgbdata_t *rgb )
|
||||
TASSERT( load->size == rgb->size )
|
||||
TASSERT( memcmp(load->buffer, rgb->buffer, rgb->size ) == 0 )
|
||||
|
||||
Mem_Free( load );
|
||||
FS_FreeImage( load );
|
||||
}
|
||||
|
||||
void Test_RunImagelib( void )
|
||||
|
||||
@@ -126,20 +126,14 @@ dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath )
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
static void COM_GenerateCommonLibraryName( const char *name, const char *ext, const char *suffix, char *out, size_t size )
|
||||
static void COM_GenerateCommonLibraryName( const char *name, const char *ext, char *out, size_t size )
|
||||
{
|
||||
#if ( XASH_WIN32 || XASH_LINUX || XASH_APPLE ) && XASH_X86
|
||||
if( suffix )
|
||||
Q_snprintf( out, size, "%s_%s.%s", name, suffix, ext );
|
||||
else Q_snprintf( out, size, "%s.%s", name, ext );
|
||||
Q_snprintf( out, size, "%s.%s", name, ext );
|
||||
#elif ( XASH_WIN32 || XASH_LINUX || XASH_APPLE )
|
||||
if( suffix )
|
||||
Q_snprintf( out, size, "%s_%s_%s.%s", name, Q_buildarch(), suffix, ext );
|
||||
else Q_snprintf( out, size, "%s_%s.%s", name, Q_buildarch(), ext );
|
||||
Q_snprintf( out, size, "%s_%s.%s", name, Q_buildarch(), ext );
|
||||
#else
|
||||
if( suffix )
|
||||
Q_snprintf( out, size, "%s_%s_%s_%s.%s", name, Q_buildos(), Q_buildarch(), suffix, ext );
|
||||
else Q_snprintf( out, size, "%s_%s_%s.%s", name, Q_buildos(), Q_buildarch(), ext );
|
||||
Q_snprintf( out, size, "%s_%s_%s.%s", name, Q_buildos(), Q_buildarch(), ext );
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -160,7 +154,7 @@ static void COM_GenerateClientLibraryPath( const char *name, char *out, size_t s
|
||||
// we don't have any library prefixes, so we can safely append dll_path here
|
||||
Q_snprintf( dllpath, sizeof( dllpath ), "%s/%s", GI->dll_path, name );
|
||||
|
||||
COM_GenerateCommonLibraryName( dllpath, OS_LIB_EXT, NULL, out, size );
|
||||
COM_GenerateCommonLibraryName( dllpath, OS_LIB_EXT, out, size );
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -217,13 +211,7 @@ static void COM_GenerateServerLibraryPath( char *out, size_t size )
|
||||
COM_StripExtension( dllpath );
|
||||
COM_StripIntelSuffix( dllpath );
|
||||
|
||||
#if XASH_ARCH_USES_ONLY_ABI2
|
||||
COM_GenerateCommonLibraryName( dllpath, ext, NULL, out, size );
|
||||
#elif XASH_64BIT
|
||||
COM_GenerateCommonLibraryName( dllpath, ext, "st64", out, size );
|
||||
#else
|
||||
COM_GenerateCommonLibraryName( dllpath, ext, NULL, out, size );
|
||||
#endif
|
||||
COM_GenerateCommonLibraryName( dllpath, ext, out, size );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ typedef struct master_s
|
||||
struct master_s *next;
|
||||
qboolean sent; // TODO: get rid of this internal state
|
||||
qboolean save;
|
||||
qboolean v6only;
|
||||
string address;
|
||||
netadr_t adr; // temporary, rewritten after each send
|
||||
|
||||
@@ -45,7 +46,7 @@ NET_GetMasterHostByName
|
||||
*/
|
||||
static net_gai_state_t NET_GetMasterHostByName( master_t *m )
|
||||
{
|
||||
net_gai_state_t res = NET_StringToAdrNB( m->address, &m->adr );
|
||||
net_gai_state_t res = NET_StringToAdrNB( m->address, &m->adr, m->v6only );
|
||||
|
||||
if( res == NET_EAI_OK )
|
||||
return res;
|
||||
@@ -251,7 +252,7 @@ NET_AddMaster
|
||||
Add master to the list
|
||||
========================
|
||||
*/
|
||||
static void NET_AddMaster( const char *addr, qboolean save )
|
||||
static void NET_AddMaster( const char *addr, qboolean save, qboolean v6only )
|
||||
{
|
||||
master_t *master, *last;
|
||||
|
||||
@@ -261,10 +262,11 @@ static void NET_AddMaster( const char *addr, qboolean save )
|
||||
return;
|
||||
}
|
||||
|
||||
master = Mem_Malloc( host.mempool, sizeof( master_t ) );
|
||||
master = Mem_Malloc( host.mempool, sizeof( *master ) );
|
||||
Q_strncpy( master->address, addr, sizeof( master->address ));
|
||||
master->sent = false;
|
||||
master->save = save;
|
||||
master->v6only = v6only;
|
||||
master->next = NULL;
|
||||
master->adr.type = 0;
|
||||
|
||||
@@ -283,7 +285,7 @@ static void NET_AddMaster_f( void )
|
||||
return;
|
||||
}
|
||||
|
||||
NET_AddMaster( Cmd_Argv( 1 ), true ); // save them into config
|
||||
NET_AddMaster( Cmd_Argv( 1 ), true, false ); // save them into config
|
||||
ml.modified = true; // save config
|
||||
}
|
||||
|
||||
@@ -316,15 +318,14 @@ static void NET_ListMasters_f( void )
|
||||
master_t *list;
|
||||
int i;
|
||||
|
||||
Msg( "Master servers\n=============\n" );
|
||||
|
||||
Con_Printf( "Master servers:\n" );
|
||||
|
||||
for( i = 1, list = ml.list; list; i++, list = list->next )
|
||||
{
|
||||
Msg( "%d\t%s", i, list->address );
|
||||
Con_Printf( "%d\t%s", i, list->address );
|
||||
if( list->adr.type != 0 )
|
||||
Msg( "\t%s\n", NET_AdrToString( list->adr ));
|
||||
else Msg( "\n" );
|
||||
Con_Printf( "\t%s\n", NET_AdrToString( list->adr ));
|
||||
else Con_Printf( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,11 +355,15 @@ static void NET_LoadMasters( void )
|
||||
// format: master <addr>\n
|
||||
while( ( pfile = COM_ParseFile( pfile, token, sizeof( token ) ) ) )
|
||||
{
|
||||
if( !Q_strcmp( token, "master" ) ) // load addr
|
||||
if( !Q_strcmp( token, "master" )) // load addr
|
||||
{
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ) );
|
||||
|
||||
NET_AddMaster( token, true );
|
||||
NET_AddMaster( token, true, false );
|
||||
}
|
||||
else if( !Q_strcmp( token, "master6" ))
|
||||
{
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ) );
|
||||
NET_AddMaster( token, true, true );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,7 +401,7 @@ void NET_SaveMasters( void )
|
||||
for( m = ml.list; m; m = m->next )
|
||||
{
|
||||
if( m->save )
|
||||
FS_Printf( f, "master %s\n", m->address );
|
||||
FS_Printf( f, "%s %s\n", m->v6only ? "master6" : "master", m->address );
|
||||
}
|
||||
|
||||
FS_Close( f );
|
||||
@@ -418,10 +423,10 @@ void NET_InitMasters( void )
|
||||
Cvar_RegisterVariable( &sv_verbose_heartbeats );
|
||||
|
||||
// keep main master always there
|
||||
NET_AddMaster( MASTERSERVER_ADR, false );
|
||||
NET_AddMaster( "aaaa.mentality.rip:27010", false ); // IPv6-only
|
||||
NET_AddMaster( "mentality.rip:27011", false ); // testing server, might be offline
|
||||
NET_AddMaster( "aaaa.mentality.rip:27011", false ); // IPv6-only, testing server, might be offline
|
||||
NET_AddMaster( MASTERSERVER_ADR, false, false );
|
||||
NET_AddMaster( "aaaa.mentality.rip:27010", false, true ); // IPv6-only
|
||||
NET_AddMaster( "mentality.rip:27011", false, false ); // testing server, might be offline
|
||||
NET_AddMaster( "aaaa.mentality.rip:27011", false, true ); // IPv6-only, testing server, might be offline
|
||||
|
||||
NET_LoadMasters( );
|
||||
}
|
||||
|
||||
@@ -30,13 +30,6 @@ GNU General Public License for more details.
|
||||
|
||||
#define MIPTEX_CUSTOM_PALETTE_SIZE_BYTES ( sizeof( int16_t ) + 768 )
|
||||
|
||||
typedef struct wadlist_s
|
||||
{
|
||||
char wadnames[MAX_MAP_WADS][32];
|
||||
int wadusage[MAX_MAP_WADS];
|
||||
int count;
|
||||
} wadlist_t;
|
||||
|
||||
typedef struct leaflist_s
|
||||
{
|
||||
int count;
|
||||
@@ -136,7 +129,6 @@ typedef struct
|
||||
dclipnode32_t *clipnodes_out; // temporary 32-bit array to hold clipnodes
|
||||
|
||||
// misc stuff
|
||||
wadlist_t wadlist;
|
||||
int lightmap_samples; // samples per lightmap (1 or 3)
|
||||
int version; // model version
|
||||
qboolean isworld;
|
||||
@@ -1835,7 +1827,7 @@ static void Mod_LoadEntities( model_t *mod, dbspmodel_t *bmod )
|
||||
world.generator[0] = '\0';
|
||||
world.compiler[0] = '\0';
|
||||
world.message[0] = '\0';
|
||||
bmod->wadlist.count = 0;
|
||||
world.wadlist.count = 0;
|
||||
|
||||
// parse all the wads for loading textures in right ordering
|
||||
while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL )
|
||||
@@ -1878,12 +1870,12 @@ static void Mod_LoadEntities( model_t *mod, dbspmodel_t *bmod )
|
||||
// make sure that wad is really exist
|
||||
if( FS_FileExists( va( "%s.wad", token ), false ))
|
||||
{
|
||||
int num = bmod->wadlist.count++;
|
||||
Q_strncpy( bmod->wadlist.wadnames[num], token, sizeof( bmod->wadlist.wadnames[0] ));
|
||||
bmod->wadlist.wadusage[num] = 0;
|
||||
int num = world.wadlist.count++;
|
||||
Q_strncpy( world.wadlist.wadnames[num], token, sizeof( world.wadlist.wadnames[0] ));
|
||||
world.wadlist.wadusage[num] = 0;
|
||||
}
|
||||
|
||||
if( bmod->wadlist.count >= MAX_MAP_WADS )
|
||||
if( world.wadlist.count >= MAX_MAP_WADS )
|
||||
break; // too many wads...
|
||||
}
|
||||
}
|
||||
@@ -2030,24 +2022,35 @@ static void Mod_LoadMarkSurfaces( model_t *mod, dbspmodel_t *bmod )
|
||||
|
||||
if( bmod->version == QBSP2_VERSION )
|
||||
{
|
||||
dmarkface32_t *in = bmod->markfaces32;
|
||||
const dmarkface32_t *in = bmod->markfaces32;
|
||||
|
||||
for( i = 0; i < bmod->nummarkfaces; i++, in++ )
|
||||
for( i = 0; i < bmod->nummarkfaces; i++ )
|
||||
{
|
||||
if( *in < 0 || *in >= mod->numsurfaces )
|
||||
Host_Error( "%s: bad surface number in '%s'\n", __func__, mod->name );
|
||||
out[i] = mod->surfaces + *in;
|
||||
if( in[i] < 0 || in[i] >= mod->numsurfaces )
|
||||
Host_Error( "%s: bad surface number %i at %i (max %i) in '%s'\n", __func__, in[i], i, mod->numsurfaces, mod->name );
|
||||
out[i] = mod->surfaces + in[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dmarkface_t *in = bmod->markfaces;
|
||||
const dmarkface_t *in = bmod->markfaces;
|
||||
|
||||
for( i = 0; i < bmod->nummarkfaces; i++, in++ )
|
||||
for( i = 0; i < bmod->nummarkfaces; i++ )
|
||||
{
|
||||
if( *in < 0 || *in >= mod->numsurfaces )
|
||||
Host_Error( "%s: bad surface number in '%s'\n", __func__, mod->name );
|
||||
out[i] = mod->surfaces + *in;
|
||||
// NOTE: some of the buggy compilers have written a broken BSP file
|
||||
// with marksurface pointing at negative surface, for example darkf6.bsp
|
||||
// and darkf26.bsp in darkfuture mod. GoldSrc straight up writes
|
||||
// invalid pointer to a surface. Try to fix up these cases...
|
||||
if( mod->numsurfaces <= INT16_MAX && (int16_t)in[i] < 0 )
|
||||
{
|
||||
Con_Printf( S_WARN "%s: fixing up bad surface number %i at %i (max %i) in '%s'\n", __func__, in[i], i, mod->numsurfaces, mod->name );
|
||||
out[i] = mod->surfaces;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( in[i] < 0 || in[i] >= mod->numsurfaces )
|
||||
Host_Error( "%s: bad surface number %i at %i (max %i) in '%s'\n", __func__, in[i], i, mod->numsurfaces, mod->name );
|
||||
out[i] = mod->surfaces + in[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2309,9 +2312,9 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
|
||||
}
|
||||
|
||||
// Try WAD texture (force while r_wadtextures is 1)
|
||||
if( !texture->gl_texturenum && (( r_wadtextures.value && bmod->wadlist.count > 0 ) || mipTex->offsets[0] <= 0 ))
|
||||
if( !texture->gl_texturenum && (( r_wadtextures.value && world.wadlist.count > 0 ) || mipTex->offsets[0] <= 0 ))
|
||||
{
|
||||
int wadIndex = Mod_FindTextureInWadList( &bmod->wadlist, mipTex->name, texpath, sizeof( texpath ));
|
||||
int wadIndex = Mod_FindTextureInWadList( &world.wadlist, mipTex->name, texpath, sizeof( texpath ));
|
||||
|
||||
if( wadIndex >= 0 )
|
||||
{
|
||||
@@ -2319,7 +2322,7 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
|
||||
if( !Host_IsDedicated( ))
|
||||
texture->gl_texturenum = ref.dllFuncs.GL_LoadTexture( texpath, NULL, 0, txFlags );
|
||||
#endif // !XASH_DEDICATED
|
||||
bmod->wadlist.wadusage[wadIndex]++;
|
||||
world.wadlist.wadusage[wadIndex]++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2377,12 +2380,12 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
|
||||
// doesn't exist there. The original texture is already loaded, but cannot be modified.
|
||||
// Instead, load the original texture again and convert it to luma.
|
||||
|
||||
wadIndex = Mod_FindTextureInWadList( &bmod->wadlist, texture->name, texpath, sizeof( texpath ));
|
||||
wadIndex = Mod_FindTextureInWadList( &world.wadlist, texture->name, texpath, sizeof( texpath ));
|
||||
|
||||
if( wadIndex >= 0 )
|
||||
{
|
||||
src = FS_LoadFile( texpath, &srcSize, false );
|
||||
bmod->wadlist.wadusage[wadIndex]++;
|
||||
world.wadlist.wadusage[wadIndex]++;
|
||||
}
|
||||
|
||||
// OK, loading it from wad or hi-res version
|
||||
@@ -3415,18 +3418,14 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, const byte *mod_base, qboolea
|
||||
Mod_CalcPHS( mod );
|
||||
}
|
||||
|
||||
for( i = 0; i < bmod->wadlist.count; i++ )
|
||||
for( i = 0; i < world.wadlist.count; i++ )
|
||||
{
|
||||
string wadname;
|
||||
|
||||
if( !bmod->wadlist.wadusage[i] )
|
||||
if( !world.wadlist.wadusage[i] )
|
||||
continue;
|
||||
|
||||
Q_snprintf( wadname, sizeof( wadname ), "%s.wad", bmod->wadlist.wadnames[i] );
|
||||
|
||||
// a1ba: automatically precache used wad files so client will download it
|
||||
if( SV_Active( ))
|
||||
SV_GenericIndex( wadname );
|
||||
Q_snprintf( wadname, sizeof( wadname ), "%s.wad", world.wadlist.wadnames[i] );
|
||||
|
||||
if( !wadlist_warn )
|
||||
{
|
||||
|
||||
@@ -83,6 +83,12 @@ typedef struct
|
||||
uint num_polys;
|
||||
} hull_model_t;
|
||||
|
||||
typedef struct wadlist_s
|
||||
{
|
||||
char wadnames[MAX_MAP_WADS][32];
|
||||
int wadusage[MAX_MAP_WADS];
|
||||
int count;
|
||||
} wadlist_t;
|
||||
|
||||
typedef struct world_static_s
|
||||
{
|
||||
@@ -119,6 +125,8 @@ typedef struct world_static_s
|
||||
// Potentially Hearable Set
|
||||
byte *compressed_phs;
|
||||
size_t *phsofs;
|
||||
|
||||
wadlist_t wadlist;
|
||||
} world_static_t;
|
||||
|
||||
#ifndef REF_DLL
|
||||
|
||||
161
engine/common/munge.c
Normal file
161
engine/common/munge.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
munge.c - protocol mangling for GoldSrc
|
||||
Copyright (C) ReHLDS developers
|
||||
Copyright (C) 2023 Alibek Omarov
|
||||
|
||||
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"
|
||||
|
||||
static const byte mungify_table[] =
|
||||
{
|
||||
0x7A, 0x64, 0x05, 0xF1, 0x1B, 0x9B, 0xA0, 0xB5,
|
||||
0xCA, 0xED, 0x61, 0x0D, 0x4A, 0xDF, 0x8E, 0xC7,
|
||||
};
|
||||
|
||||
static const byte mungify_table2[] =
|
||||
{
|
||||
0x05, 0x61, 0x7A, 0xED, 0x1B, 0xCA, 0x0D, 0x9B,
|
||||
0x4A, 0xF1, 0x64, 0xC7, 0xB5, 0x8E, 0xDF, 0xA0,
|
||||
};
|
||||
|
||||
static const byte mungify_table3[] =
|
||||
{
|
||||
0x20, 0x07, 0x13, 0x61, 0x03, 0x45, 0x17, 0x72,
|
||||
0x0A, 0x2D, 0x48, 0x0C, 0x4A, 0x12, 0xA9, 0xB5,
|
||||
};
|
||||
|
||||
static int COM_SwapLong( int c )
|
||||
{
|
||||
return ((( c >> 0 ) & 0xFF) << 24 ) +
|
||||
((( c >> 8 ) & 0xFF) << 16 ) +
|
||||
((( c >> 16 ) & 0xFF) << 8 ) +
|
||||
((( c >> 24 ) & 0xFF) << 0 );
|
||||
}
|
||||
|
||||
static void COM_GenericMunge( byte *data, const size_t len, const int seq, const byte *table, const qboolean reverse )
|
||||
{
|
||||
const size_t mungelen = len / 4;
|
||||
int i;
|
||||
|
||||
for( i = 0; i < mungelen; i++ )
|
||||
{
|
||||
uint *pc, c;
|
||||
byte *p;
|
||||
int j;
|
||||
|
||||
pc = (uint *)&data[i * 4];
|
||||
c = *pc;
|
||||
c ^= seq;
|
||||
if( !reverse )
|
||||
c = COM_SwapLong( c );
|
||||
|
||||
p = (byte *)&c;
|
||||
for( j = 0; j < 4; j++ )
|
||||
*p++ ^= (0xa5 | (j << j) | j | table[(i + j) & 0x0f]);
|
||||
|
||||
if( reverse )
|
||||
c = COM_SwapLong( c );
|
||||
c ^= ~seq;
|
||||
*pc = c;
|
||||
}
|
||||
}
|
||||
|
||||
// Anti-proxy/aimbot obfuscation code
|
||||
// COM_UnMunge should reversably fixup the data
|
||||
void COM_Munge( byte *data, size_t len, int seq )
|
||||
{
|
||||
COM_GenericMunge( data, len, seq, mungify_table, false );
|
||||
}
|
||||
|
||||
void COM_UnMunge( byte *data, size_t len, int seq )
|
||||
{
|
||||
COM_GenericMunge( data, len, seq, mungify_table, true );
|
||||
}
|
||||
|
||||
void COM_Munge2( byte *data, size_t len, int seq )
|
||||
{
|
||||
COM_GenericMunge( data, len, seq, mungify_table2, false );
|
||||
}
|
||||
|
||||
void COM_UnMunge2( byte *data, size_t len, int seq )
|
||||
{
|
||||
COM_GenericMunge( data, len, seq, mungify_table2, true );
|
||||
}
|
||||
|
||||
void COM_Munge3( byte *data, size_t len, int seq )
|
||||
{
|
||||
COM_GenericMunge( data, len, seq, mungify_table3, false );
|
||||
}
|
||||
|
||||
void COM_UnMunge3( byte *data, size_t len, int seq )
|
||||
{
|
||||
COM_GenericMunge( data, len, seq, mungify_table3, true );
|
||||
}
|
||||
|
||||
#if XASH_ENGINE_TESTS
|
||||
#include "tests.h"
|
||||
|
||||
void Test_RunMunge( void )
|
||||
{
|
||||
const char *msg = "0123456789qwertyuiopasdfghjklzxcvbnmaa";
|
||||
const char *expected[][3] =
|
||||
{
|
||||
{
|
||||
"\x33\x2a\x61\x30\x2d\x6e\x35\x74\x2d\x79\x79\x78\x73\x34\x32\x25\x30\x2f\x39\x35\x26\x3c\x33\x61\x31\x22\x78\x67\x29\x68\x6a\x6c\x7d\x7e\x72\x36\x61\x61",
|
||||
"\x69\x2a\x31\x30\x2d\x36\x25\x74\x77\x61\x79\x38\x6b\x34\x62\x25\x30\x7f\x39\x35\x76\x34\x33\x61\x39\x2a\x78\x67\x23\x68\x7a\x6c\x7d\x66\x72\x76\x61\x61",
|
||||
"\x69\x6a\x71\x30\x6f\x7e\x25\x74\x3f\x69\x69\x38\x63\x2c\x62\x25\x28\x77\x29\x75\x7c\x2c\x73\x21\x23\x62\x38\x27\x6b\x28\x2a\x6c\x3d\x3e\x72\x36\x61\x61",
|
||||
}, {
|
||||
"\x32\x2a\x61\x31\x2c\x6e\x35\x75\x2c\x79\x79\x79\x72\x34\x32\x24\x31\x2f\x39\x34\x27\x3c\x33\x60\x30\x22\x78\x66\x28\x68\x6a\x6d\x7c\x7e\x72\x37\x61\x61",
|
||||
"\x68\x2a\x31\x31\x2c\x36\x25\x75\x76\x61\x79\x39\x6a\x34\x62\x24\x31\x7f\x39\x34\x77\x34\x33\x60\x38\x2a\x78\x66\x22\x68\x7a\x6d\x7c\x66\x72\x77\x61\x61",
|
||||
"\x68\x6a\x71\x31\x6e\x7e\x25\x75\x3e\x69\x69\x39\x62\x2c\x62\x24\x29\x77\x29\x74\x7d\x2c\x73\x20\x22\x62\x38\x26\x6a\x28\x2a\x6d\x3c\x3e\x72\x37\x61\x61",
|
||||
}
|
||||
};
|
||||
string buf;
|
||||
size_t msglen = Q_strlen( msg ) + 1;
|
||||
int i;
|
||||
|
||||
Q_strncpy( buf, msg, msglen );
|
||||
|
||||
for( i = 0; i < 0xFF; i++ )
|
||||
{
|
||||
COM_Munge( buf, msglen, i );
|
||||
if( i < sizeof( expected ) / sizeof( expected[0] ))
|
||||
{
|
||||
//for( int j = 0; j < msglen; j++ )
|
||||
// printf( "\\x%02x", buf[j] );
|
||||
//printf( "\n" );
|
||||
TASSERT( !memcmp( buf, expected[i][0], msglen ));
|
||||
}
|
||||
COM_UnMunge( buf, msglen, i );
|
||||
|
||||
TASSERT( !Q_strcmp( buf, msg ));
|
||||
|
||||
COM_Munge2( buf, msglen, i );
|
||||
if( i < sizeof( expected ) / sizeof( expected[0] ))
|
||||
{
|
||||
TASSERT( !memcmp( buf, expected[i][1], msglen ));
|
||||
}
|
||||
COM_UnMunge2( buf, msglen, i );
|
||||
|
||||
TASSERT( !Q_strcmp( buf, msg ));
|
||||
|
||||
COM_Munge3( buf, msglen, i );
|
||||
if( i < sizeof( expected ) / sizeof( expected[0] ))
|
||||
{
|
||||
TASSERT( !memcmp( buf, expected[i][2], msglen ));
|
||||
}
|
||||
COM_UnMunge3( buf, msglen, i );
|
||||
|
||||
TASSERT( !Q_strcmp( buf, msg ));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -81,7 +81,7 @@ const char *svc_strings[svc_lastmsg+1] =
|
||||
"svc_director",
|
||||
"svc_voiceinit",
|
||||
"svc_voicedata",
|
||||
"svc_deltapacketbones",
|
||||
"svc_unused54",
|
||||
"svc_unused55",
|
||||
"svc_resourcelocation",
|
||||
"svc_querycvarvalue",
|
||||
@@ -213,17 +213,25 @@ void MSG_WriteSBitLong( sizebuf_t *sb, int data, int numbits )
|
||||
// do we have a valid # of bits to encode with?
|
||||
Assert( numbits >= 1 && numbits <= 32 );
|
||||
|
||||
// NOTE: it does this wierdness here so it's bit-compatible with regular integer data in the buffer.
|
||||
// (Some old code writes direct integers right into the buffer).
|
||||
if( data < 0 )
|
||||
{
|
||||
if( sb->iAlternateSign )
|
||||
MSG_WriteOneBit( sb, 1 );
|
||||
|
||||
MSG_WriteUBitLong( sb, (uint)( 0x80000000 + data ), numbits - 1 );
|
||||
MSG_WriteOneBit( sb, 1 );
|
||||
|
||||
if( !sb->iAlternateSign )
|
||||
MSG_WriteOneBit( sb, 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( sb->iAlternateSign )
|
||||
MSG_WriteOneBit( sb, 0 );
|
||||
|
||||
MSG_WriteUBitLong( sb, (uint)data, numbits - 1 );
|
||||
MSG_WriteOneBit( sb, 0 );
|
||||
|
||||
if( !sb->iAlternateSign )
|
||||
MSG_WriteOneBit( sb, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,12 +541,22 @@ int MSG_ReadSBitLong( sizebuf_t *sb, int numbits )
|
||||
{
|
||||
int r, sign;
|
||||
|
||||
r = MSG_ReadUBitLong( sb, numbits - 1 );
|
||||
if( sb->iAlternateSign )
|
||||
{
|
||||
sign = MSG_ReadOneBit( sb );
|
||||
r = MSG_ReadUBitLong( sb, numbits - 1 );
|
||||
|
||||
// NOTE: it does this wierdness here so it's bit-compatible with regular integer data in the buffer.
|
||||
// (Some old code writes direct integers right into the buffer).
|
||||
sign = MSG_ReadOneBit( sb );
|
||||
if( sign ) r = -( BIT( numbits - 1 ) - r );
|
||||
if( sign )
|
||||
r = -r;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = MSG_ReadUBitLong( sb, numbits - 1 );
|
||||
sign = MSG_ReadOneBit( sb );
|
||||
|
||||
if( sign )
|
||||
r = -( BIT( numbits - 1 ) - r );
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -569,7 +587,13 @@ int MSG_ReadCmd( sizebuf_t *sb, netsrc_t type )
|
||||
|
||||
int MSG_ReadChar( sizebuf_t *sb )
|
||||
{
|
||||
return MSG_ReadSBitLong( sb, sizeof( int8_t ) << 3 );
|
||||
int alt = sb->iAlternateSign, ret;
|
||||
|
||||
sb->iAlternateSign = 0;
|
||||
ret = MSG_ReadSBitLong( sb, sizeof( int8_t ) << 3 );
|
||||
sb->iAlternateSign = alt;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int MSG_ReadByte( sizebuf_t *sb )
|
||||
@@ -579,7 +603,13 @@ int MSG_ReadByte( sizebuf_t *sb )
|
||||
|
||||
int MSG_ReadShort( sizebuf_t *sb )
|
||||
{
|
||||
return MSG_ReadSBitLong( sb, sizeof( int16_t ) << 3 );
|
||||
int alt = sb->iAlternateSign, ret;
|
||||
|
||||
sb->iAlternateSign = 0;
|
||||
ret = MSG_ReadSBitLong( sb, sizeof( int16_t ) << 3 );
|
||||
sb->iAlternateSign = alt;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int MSG_ReadWord( sizebuf_t *sb )
|
||||
@@ -611,7 +641,13 @@ void MSG_ReadVec3Angles( sizebuf_t *sb, vec3_t fa )
|
||||
|
||||
int MSG_ReadLong( sizebuf_t *sb )
|
||||
{
|
||||
return MSG_ReadSBitLong( sb, sizeof( int32_t ) << 3 );
|
||||
int alt = sb->iAlternateSign, ret;
|
||||
|
||||
sb->iAlternateSign = 0;
|
||||
ret = MSG_ReadSBitLong( sb, sizeof( int32_t ) << 3 );
|
||||
sb->iAlternateSign = alt;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint MSG_ReadDword( sizebuf_t *sb )
|
||||
|
||||
@@ -42,6 +42,9 @@ struct sizebuf_s
|
||||
int iCurBit;
|
||||
int nDataBits;
|
||||
const char *pDebugName; // buffer name (pointer to const name)
|
||||
|
||||
// to support GoldSrc broken signed integers
|
||||
int iAlternateSign;
|
||||
};
|
||||
|
||||
#define MSG_StartReading MSG_StartWriting
|
||||
@@ -71,6 +74,7 @@ static inline void MSG_InitExt( sizebuf_t *sb, const char *pDebugName, void *pDa
|
||||
sb->nDataBits = nBits;
|
||||
|
||||
sb->pDebugName = pDebugName;
|
||||
sb->iAlternateSign = 0;
|
||||
}
|
||||
|
||||
static inline void MSG_StartWriting( sizebuf_t *sb, void *pData, int nBytes, int iStartBit, int nBits )
|
||||
@@ -169,6 +173,25 @@ static inline qboolean MSG_Overflow( sizebuf_t *sb, int nBits )
|
||||
return sb->bOverflow;
|
||||
}
|
||||
|
||||
static inline void MSG_EndBitWriting( sizebuf_t *sb )
|
||||
{
|
||||
sb->iAlternateSign--;
|
||||
|
||||
if( sb->iAlternateSign < 0 )
|
||||
{
|
||||
Con_Printf( "%s: non-even MSG_Start/EndBitWriting\n", __func__ );
|
||||
sb->iAlternateSign = 0;
|
||||
}
|
||||
|
||||
// we have native bit ops here, just pad to closest byte
|
||||
MSG_SeekToBit( sb, MSG_GetNumBytesWritten( sb ) << 3, SEEK_SET );
|
||||
}
|
||||
|
||||
static inline void MSG_StartBitWriting( sizebuf_t *sb )
|
||||
{
|
||||
sb->iAlternateSign++;
|
||||
}
|
||||
|
||||
void MSG_InitMasks( void ); // called once at startup engine
|
||||
void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove );
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@ GNU General Public License for more details.
|
||||
#include "xash3d_mathlib.h"
|
||||
#include "net_encode.h"
|
||||
#include "protocol.h"
|
||||
#if !XASH_DEDICATED
|
||||
#include <bzlib.h>
|
||||
#endif // !XASH_DEDICATED
|
||||
|
||||
#define MAKE_FRAGID( id, count ) ((( id & 0xffff ) << 16 ) | ( count & 0xffff ))
|
||||
#define FRAG_GETID( fragid ) (( fragid >> 16 ) & 0xffff )
|
||||
@@ -265,7 +268,7 @@ Netchan_Setup
|
||||
called to open a channel to a remote system
|
||||
==============
|
||||
*/
|
||||
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, void *client, int (*pfnBlockSize)(void *, fragsize_t mode ))
|
||||
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, void *client, int (*pfnBlockSize)(void *, fragsize_t mode ), uint flags )
|
||||
{
|
||||
Netchan_Clear( chan );
|
||||
|
||||
@@ -281,6 +284,10 @@ void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, voi
|
||||
chan->qport = qport;
|
||||
chan->client = client;
|
||||
chan->pfnBlockSize = pfnBlockSize;
|
||||
chan->split = FBitSet( flags, NETCHAN_USE_LEGACY_SPLIT ) ? true : false;
|
||||
chan->use_munge = FBitSet( flags, NETCHAN_USE_MUNGE ) ? true : false;
|
||||
chan->use_bz2 = FBitSet( flags, NETCHAN_USE_BZIP2 ) ? true : false;
|
||||
chan->gs_netchan = FBitSet( flags, NETCHAN_GOLDSRC ) ? true : false;
|
||||
|
||||
MSG_Init( &chan->message, "NetData", chan->message_buf, sizeof( chan->message_buf ));
|
||||
}
|
||||
@@ -687,7 +694,19 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg )
|
||||
|
||||
wait = (fragbufwaiting_t *)Mem_Calloc( net_mempool, sizeof( fragbufwaiting_t ));
|
||||
|
||||
if( !LZSS_IsCompressed( MSG_GetData( msg )))
|
||||
if( chan->use_bz2 && memcmp( MSG_GetData( msg ), "BZ2", 4 ))
|
||||
{
|
||||
byte pbOut[0x10000];
|
||||
uint uCompressedSize = MSG_GetNumBytesWritten( msg ) - 4;
|
||||
if( !BZ2_bzBuffToBuffCompress( pbOut, &uCompressedSize, MSG_GetData( msg ), MSG_GetNumBytesWritten( msg ), 9, 0, 30 ))
|
||||
{
|
||||
Con_Reportf( "Compressing split packet with BZip2 (%d -> %d bytes)\n", MSG_GetNumBytesWritten( msg ), uCompressedSize );
|
||||
memcpy( msg->pData, "BZ2", 4 );
|
||||
memcpy( msg->pData + 4, pbOut, uCompressedSize );
|
||||
MSG_SeekToBit( msg, uCompressedSize << 3, SEEK_SET );
|
||||
}
|
||||
}
|
||||
else if( !chan->use_bz2 && !LZSS_IsCompressed( MSG_GetData( msg )))
|
||||
{
|
||||
uint uCompressedSize = 0;
|
||||
uint uSourceSize = MSG_GetNumBytesWritten( msg );
|
||||
@@ -695,7 +714,7 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg )
|
||||
|
||||
if( pbOut && uCompressedSize > 0 && uCompressedSize < uSourceSize )
|
||||
{
|
||||
Con_Reportf( "Compressing split packet (%d -> %d bytes)\n", uSourceSize, uCompressedSize );
|
||||
Con_Reportf( "Compressing split packet with LZSS (%d -> %d bytes)\n", uSourceSize, uCompressedSize );
|
||||
memcpy( msg->pData, pbOut, uCompressedSize );
|
||||
MSG_SeekToBit( msg, uCompressedSize << 3, SEEK_SET );
|
||||
}
|
||||
@@ -1098,7 +1117,16 @@ qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *l
|
||||
p = n;
|
||||
}
|
||||
|
||||
if( LZSS_IsCompressed( MSG_GetData( msg )))
|
||||
if( chan->use_bz2 && !memcmp( MSG_GetData( msg ), "BZ2", 4 ) )
|
||||
{
|
||||
byte buf[0x10000];
|
||||
uint uDecompressedLen = sizeof( buf );
|
||||
|
||||
BZ2_bzBuffToBuffDecompress( buf, &uDecompressedLen, MSG_GetData( msg ) + 4, MSG_GetNumBytesWritten( msg ) - 4, 1, 0 );
|
||||
memcpy( msg->pData, buf, uDecompressedLen );
|
||||
size = uDecompressedLen;
|
||||
}
|
||||
else if( !chan->use_bz2 && LZSS_IsCompressed( MSG_GetData( msg )))
|
||||
{
|
||||
uint uDecompressedLen = LZSS_GetActualSize( MSG_GetData( msg ));
|
||||
byte buf[NET_MAX_MESSAGE];
|
||||
@@ -1135,7 +1163,8 @@ Netchan_CopyFileFragments
|
||||
*/
|
||||
qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
|
||||
{
|
||||
char filename[MAX_OSPATH];
|
||||
char filename[MAX_OSPATH], compressor[32];
|
||||
uint uncompressedSize;
|
||||
int nsize, pos;
|
||||
byte *buffer;
|
||||
fragbuf_t *p, *n;
|
||||
@@ -1158,6 +1187,12 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
|
||||
MSG_Clear( msg );
|
||||
|
||||
Q_strncpy( filename, MSG_ReadString( msg ), sizeof( filename ));
|
||||
compressor[0] = 0;
|
||||
if( chan->gs_netchan )
|
||||
{
|
||||
Q_strncpy( compressor, MSG_ReadString( msg ), sizeof( compressor ));
|
||||
uncompressedSize = MSG_ReadLong( msg );
|
||||
}
|
||||
|
||||
if( !COM_CheckString( filename ))
|
||||
{
|
||||
@@ -1228,10 +1263,25 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
|
||||
p = n;
|
||||
}
|
||||
|
||||
if( LZSS_IsCompressed( buffer ))
|
||||
if( chan->gs_netchan && chan->use_bz2 )
|
||||
{
|
||||
uint uncompressedSize = LZSS_GetActualSize( buffer ) + 1;
|
||||
byte *uncompressedBuffer = Mem_Calloc( net_mempool, uncompressedSize );
|
||||
if( !Q_stricmp( compressor, "bz2" ))
|
||||
{
|
||||
byte *uncompressedBuffer = Mem_Calloc( net_mempool, uncompressedSize );
|
||||
|
||||
Con_DPrintf( "Decompressing file %s (%d -> %d bytes)\n", filename, nsize, uncompressedSize );
|
||||
BZ2_bzBuffToBuffDecompress( uncompressedBuffer, &uncompressedSize, buffer, nsize, 1, 0 );
|
||||
Mem_Free( buffer );
|
||||
nsize = uncompressedSize;
|
||||
buffer = uncompressedBuffer;
|
||||
}
|
||||
}
|
||||
else if( LZSS_IsCompressed( buffer ))
|
||||
{
|
||||
byte *uncompressedBuffer;
|
||||
|
||||
uncompressedSize = LZSS_GetActualSize( buffer ) + 1;
|
||||
uncompressedBuffer = Mem_Calloc( net_mempool, uncompressedSize );
|
||||
|
||||
nsize = LZSS_Decompress( buffer, uncompressedBuffer );
|
||||
Mem_Free( buffer );
|
||||
@@ -1593,7 +1643,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
|
||||
MSG_WriteLong( &send, w2 );
|
||||
|
||||
// send the qport if we are a client
|
||||
if( chan->sock == NS_CLIENT )
|
||||
if( chan->sock == NS_CLIENT && !chan->gs_netchan )
|
||||
{
|
||||
MSG_WriteWord( &send, (int)net_qport.value );
|
||||
}
|
||||
@@ -1606,8 +1656,16 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
|
||||
{
|
||||
MSG_WriteByte( &send, 1 );
|
||||
MSG_WriteLong( &send, chan->reliable_fragid[i] );
|
||||
MSG_WriteLong( &send, chan->frag_startpos[i] );
|
||||
MSG_WriteLong( &send, chan->frag_length[i] );
|
||||
if( chan->gs_netchan )
|
||||
{
|
||||
MSG_WriteShort( &send, chan->frag_startpos[i] >> 3 );
|
||||
MSG_WriteShort( &send, chan->frag_length[i] >> 3 );
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_WriteLong( &send, chan->frag_startpos[i] );
|
||||
MSG_WriteLong( &send, chan->frag_length[i] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1664,6 +1722,10 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
|
||||
int splitsize = 0;
|
||||
if( chan->pfnBlockSize )
|
||||
splitsize = chan->pfnBlockSize( chan->client, FRAGSIZE_SPLIT );
|
||||
|
||||
if( chan->use_munge )
|
||||
COM_Munge2( send.pData + 8, MSG_GetNumBytesWritten( &send ) - 8, (byte)( chan->outgoing_sequence - 1 ));
|
||||
|
||||
NET_SendPacketEx( chan->sock, MSG_GetNumBytesWritten( &send ), MSG_GetData( &send ), chan->remote_address, splitsize );
|
||||
}
|
||||
|
||||
@@ -1712,6 +1774,9 @@ qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg )
|
||||
sequence = MSG_ReadLong( msg );
|
||||
sequence_ack = MSG_ReadLong( msg );
|
||||
|
||||
if( chan->use_munge )
|
||||
COM_UnMunge2( msg->pData + 8, ( msg->nDataBits >> 3 ) - 8, sequence & 0xFF );
|
||||
|
||||
// read the qport if we are a server
|
||||
if( chan->sock == NS_SERVER )
|
||||
qport = MSG_ReadShort( msg );
|
||||
@@ -1729,8 +1794,16 @@ qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg )
|
||||
{
|
||||
frag_message[i] = true;
|
||||
fragid[i] = MSG_ReadLong( msg );
|
||||
frag_offset[i] = MSG_ReadLong( msg );
|
||||
frag_length[i] = MSG_ReadLong( msg );
|
||||
if( chan->gs_netchan )
|
||||
{
|
||||
frag_offset[i] = MSG_ReadShort( msg ) << 3;
|
||||
frag_length[i] = MSG_ReadShort( msg ) << 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
frag_offset[i] = MSG_ReadLong( msg );
|
||||
frag_length[i] = MSG_ReadLong( msg );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ GNU General Public License for more details.
|
||||
#define DT_TIMEWINDOW_BIG BIT( 6 ) // and re-encoded on the client relative to the client's clock
|
||||
#define DT_STRING BIT( 7 ) // A null terminated string, sent as 8 byte chars
|
||||
#define DT_SIGNED BIT( 8 ) // sign modificator
|
||||
#define DT_SIGNED_GS BIT( 31 ) // GoldSrc-specific sign modificator
|
||||
|
||||
#define NUM_FIELDS( x ) ((sizeof( x ) / sizeof( x[0] )) - 1)
|
||||
|
||||
@@ -47,6 +48,7 @@ GNU General Public License for more details.
|
||||
#define PHYS_DEF( x ) #x, offsetof( movevars_t, x ), sizeof( ((movevars_t *)0)->x )
|
||||
#define CLDT_DEF( x ) #x, offsetof( clientdata_t, x ), sizeof( ((clientdata_t *)0)->x )
|
||||
#define WPDT_DEF( x ) #x, offsetof( weapon_data_t, x ), sizeof( ((weapon_data_t *)0)->x )
|
||||
#define DESC_DEF( x ) #x, offsetof( goldsrc_delta_t, x ), sizeof( ((goldsrc_delta_t *)0)->x )
|
||||
|
||||
static qboolean delta_init = false;
|
||||
|
||||
@@ -315,6 +317,18 @@ static const delta_field_t ent_fields[] =
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
static const delta_field_t meta_fields[] =
|
||||
{
|
||||
{ DESC_DEF( fieldType ), },
|
||||
{ DESC_DEF( fieldName ), },
|
||||
{ DESC_DEF( fieldOffset ), },
|
||||
{ DESC_DEF( fieldSize ), },
|
||||
{ DESC_DEF( significant_bits ), },
|
||||
{ DESC_DEF( premultiply ), },
|
||||
{ DESC_DEF( postmultiply ), },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
#if XASH_ENGINE_TESTS
|
||||
typedef struct delta_test_struct_t
|
||||
{
|
||||
@@ -352,22 +366,6 @@ static const delta_field_t test_fields[] =
|
||||
};
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
DT_EVENT_T = 0,
|
||||
DT_MOVEVARS_T,
|
||||
DT_USERCMD_T,
|
||||
DT_CLIENTDATA_T,
|
||||
DT_WEAPONDATA_T,
|
||||
DT_ENTITY_STATE_T,
|
||||
DT_ENTITY_STATE_PLAYER_T,
|
||||
DT_CUSTOM_ENTITY_STATE_T,
|
||||
#if XASH_ENGINE_TESTS
|
||||
DT_DELTA_TEST_STRUCT_T,
|
||||
#endif
|
||||
DT_STRUCT_COUNT
|
||||
};
|
||||
|
||||
static delta_info_t dt_info[] =
|
||||
{
|
||||
[DT_EVENT_T] = { "event_t", ev_fields, NUM_FIELDS( ev_fields ) },
|
||||
@@ -375,9 +373,10 @@ static delta_info_t dt_info[] =
|
||||
[DT_USERCMD_T] = { "usercmd_t", cmd_fields, NUM_FIELDS( cmd_fields ) },
|
||||
[DT_CLIENTDATA_T] = { "clientdata_t", cd_fields, NUM_FIELDS( cd_fields ) },
|
||||
[DT_WEAPONDATA_T] = { "weapon_data_t", wd_fields, NUM_FIELDS( wd_fields ) },
|
||||
[DT_ENTITY_STATE_T] = { "entity_state_t", ent_fields, NUM_FIELDS( ent_fields ) },
|
||||
[DT_ENTITY_STATE_T] = { "entity_state_t", ent_fields, NUM_FIELDS( ent_fields ) },
|
||||
[DT_ENTITY_STATE_PLAYER_T] = { "entity_state_player_t", ent_fields, NUM_FIELDS( ent_fields ) },
|
||||
[DT_CUSTOM_ENTITY_STATE_T] = { "custom_entity_state_t", ent_fields, NUM_FIELDS( ent_fields ) },
|
||||
[DT_GOLDSRC_DELTA_T] = { "goldsrc_delta_t", meta_fields, NUM_FIELDS( meta_fields ) },
|
||||
#if XASH_ENGINE_TESTS
|
||||
[DT_DELTA_TEST_STRUCT_T] = { "delta_test_struct_t", test_fields, NUM_FIELDS( test_fields ) },
|
||||
#endif
|
||||
@@ -493,7 +492,7 @@ static qboolean Delta_AddField( delta_info_t *dt, const char *pName, int flags,
|
||||
int i;
|
||||
|
||||
// check for coexisting field
|
||||
for( i = 0, pField = dt->pFields; i < dt->numFields; i++, pField++ )
|
||||
for( i = 0, pField = dt->pFields; i < dt->numFields && pField; i++, pField++ )
|
||||
{
|
||||
if( !Q_strcmp( pField->name, pName ))
|
||||
{
|
||||
@@ -621,6 +620,64 @@ void Delta_ParseTableField( sizebuf_t *msg )
|
||||
Delta_AddField( dt, pName, flags, bits, mul, post_mul );
|
||||
}
|
||||
|
||||
void Delta_InitMeta( void )
|
||||
{
|
||||
delta_info_t *dt = Delta_FindStructByIndex( DT_GOLDSRC_DELTA_T );
|
||||
|
||||
if( dt->bInitialized )
|
||||
return;
|
||||
|
||||
Delta_AddField( dt, "fieldType", DT_INTEGER, 32, 1.0f, 1.0f );
|
||||
Delta_AddField( dt, "fieldName", DT_STRING, 1, 1.0f, 1.0f );
|
||||
Delta_AddField( dt, "fieldOffset", DT_INTEGER, 16, 1.0f, 1.0f );
|
||||
Delta_AddField( dt, "fieldSize", DT_INTEGER, 8, 1.0f, 1.0f );
|
||||
Delta_AddField( dt, "significant_bits", DT_INTEGER, 8, 1.0f, 1.0f );
|
||||
Delta_AddField( dt, "premultiply", DT_FLOAT, 32, 4000.0f, 1.0f );
|
||||
Delta_AddField( dt, "postmultiply", DT_FLOAT, 32, 4000.0f, 1.0f );
|
||||
dt->numFields = dt->maxFields;
|
||||
dt->bInitialized = true;
|
||||
}
|
||||
|
||||
void Delta_ParseTableField_GS( sizebuf_t *msg )
|
||||
{
|
||||
const char *s = MSG_ReadString( msg );
|
||||
delta_info_t *dt = Delta_FindStruct( s );
|
||||
goldsrc_delta_t null = { 0 };
|
||||
int i, num_fields;
|
||||
|
||||
|
||||
// delta encoders it's already initialized on this machine (local game)
|
||||
if( delta_init )
|
||||
{
|
||||
Delta_Shutdown();
|
||||
Delta_InitMeta();
|
||||
}
|
||||
|
||||
if( !dt )
|
||||
Host_Error( "%s: not initialized", __func__ );
|
||||
|
||||
num_fields = MSG_ReadShort( msg );
|
||||
if( num_fields > dt->maxFields )
|
||||
Host_Error( "%s: numFields > maxFields", __func__ );
|
||||
|
||||
MSG_StartBitWriting( msg );
|
||||
|
||||
for( i = 0; i < num_fields; i++ )
|
||||
{
|
||||
goldsrc_delta_t to;
|
||||
|
||||
Delta_ReadGSFields( msg, DT_GOLDSRC_DELTA_T, &null, &to, 0.0f );
|
||||
|
||||
// patch our DT_SIGNED flag
|
||||
if( FBitSet( to.fieldType, DT_SIGNED_GS ))
|
||||
SetBits( to.fieldType, DT_SIGNED );
|
||||
|
||||
Delta_AddField( dt, to.fieldName, to.fieldType, to.significant_bits, to.premultiply, to.postmultiply );
|
||||
}
|
||||
|
||||
MSG_EndBitWriting( msg );
|
||||
}
|
||||
|
||||
static qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delta_t *pField, qboolean bPost )
|
||||
{
|
||||
string token;
|
||||
@@ -988,7 +1045,7 @@ compare fields by offsets
|
||||
assume from and to is valid
|
||||
=====================
|
||||
*/
|
||||
static qboolean Delta_CompareField( delta_t *pField, void *from, void *to, double timebase )
|
||||
static qboolean Delta_CompareField( delta_t *pField, const void *from, const void *to )
|
||||
{
|
||||
int signbit = ( pField->flags & DT_SIGNED ) ? 1 : 0;
|
||||
float val_a, val_b;
|
||||
@@ -1109,7 +1166,7 @@ Delta_TestBaseline
|
||||
compare baselines to find optimal
|
||||
=====================
|
||||
*/
|
||||
int Delta_TestBaseline( entity_state_t *from, entity_state_t *to, qboolean player, double timebase )
|
||||
int Delta_TestBaseline( const entity_state_t *from, const entity_state_t *to, qboolean player, double timebase )
|
||||
{
|
||||
delta_info_t *dt = NULL;
|
||||
delta_t *pField;
|
||||
@@ -1145,7 +1202,7 @@ int Delta_TestBaseline( entity_state_t *from, entity_state_t *to, qboolean playe
|
||||
// flag about field change (sets always)
|
||||
countBits++;
|
||||
|
||||
if( !Delta_CompareField( pField, from, to, timebase ))
|
||||
if( !Delta_CompareField( pField, from, to ))
|
||||
{
|
||||
// strings are handled differently
|
||||
if( FBitSet( pField->flags, DT_STRING ))
|
||||
@@ -1166,7 +1223,7 @@ write fields by offsets
|
||||
assume from and to is valid
|
||||
=====================
|
||||
*/
|
||||
static qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to, double timebase )
|
||||
static void Delta_WriteField_( sizebuf_t *msg, delta_t *pField, const void *from, const void *to, double timebase )
|
||||
{
|
||||
int signbit = FBitSet( pField->flags, DT_SIGNED ) ? 1 : 0;
|
||||
float flValue, flAngle;
|
||||
@@ -1174,14 +1231,6 @@ static qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, v
|
||||
int dt;
|
||||
const char *pStr;
|
||||
|
||||
if( Delta_CompareField( pField, from, to, timebase ))
|
||||
{
|
||||
MSG_WriteOneBit( msg, 0 ); // unchanged
|
||||
return false;
|
||||
}
|
||||
|
||||
MSG_WriteOneBit( msg, 1 ); // changed
|
||||
|
||||
if( pField->flags & DT_BYTE )
|
||||
{
|
||||
if( signbit )
|
||||
@@ -1255,6 +1304,21 @@ static qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, v
|
||||
pStr = (char *)((byte *)to + pField->offset );
|
||||
MSG_WriteString( msg, pStr );
|
||||
}
|
||||
}
|
||||
|
||||
static qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, const void *from, const void *to, double timebase )
|
||||
{
|
||||
if( Delta_CompareField( pField, from, to ))
|
||||
{
|
||||
MSG_WriteOneBit( msg, 0 ); // unchanged
|
||||
return false;
|
||||
}
|
||||
|
||||
MSG_WriteOneBit( msg, 1 ); // changed
|
||||
|
||||
Delta_WriteField_( msg, pField, from, to, timebase );
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1264,7 +1328,7 @@ Delta_CopyField
|
||||
|
||||
====================
|
||||
*/
|
||||
static void Delta_CopyField( delta_t *pField, void *from, void *to, double timebase )
|
||||
static void Delta_CopyField( delta_t *pField, const void *from, void *to, double timebase )
|
||||
{
|
||||
qboolean bSigned = FBitSet( pField->flags, DT_SIGNED );
|
||||
uint8_t *to_field = (uint8_t *)to + pField->offset;
|
||||
@@ -1313,7 +1377,7 @@ read fields by offsets
|
||||
assume 'from' and 'to' is valid
|
||||
=====================
|
||||
*/
|
||||
static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, void *to, double timebase )
|
||||
static void Delta_ReadField_( sizebuf_t *msg, delta_t *pField, void *to, double timebase )
|
||||
{
|
||||
qboolean bSigned = ( pField->flags & DT_SIGNED ) ? true : false;
|
||||
float flValue, flAngle, flTime;
|
||||
@@ -1321,12 +1385,6 @@ static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, vo
|
||||
const char *pStr;
|
||||
char *pOut;
|
||||
|
||||
if( !MSG_ReadOneBit( msg ) )
|
||||
{
|
||||
Delta_CopyField( pField, from, to, timebase );
|
||||
return false;
|
||||
}
|
||||
|
||||
Assert( pField->multiplier != 0.0f );
|
||||
|
||||
if( pField->flags & DT_BYTE )
|
||||
@@ -1410,9 +1468,80 @@ static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, vo
|
||||
pOut = (char *)((byte *)to + pField->offset );
|
||||
Q_strncpy( pOut, pStr, pField->size );
|
||||
}
|
||||
}
|
||||
|
||||
static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, const void *from, void *to, double timebase )
|
||||
{
|
||||
if( !MSG_ReadOneBit( msg ))
|
||||
{
|
||||
Delta_CopyField( pField, from, to, timebase );
|
||||
return false;
|
||||
}
|
||||
|
||||
Delta_ReadField_( msg, pField, to, timebase );
|
||||
return true;
|
||||
}
|
||||
|
||||
void Delta_ReadGSFields( sizebuf_t *msg, int index, void *from, void *to, double timebase )
|
||||
{
|
||||
delta_info_t *dt = Delta_FindStructByIndex( index );
|
||||
uint8_t bits[8] = { 0 };
|
||||
delta_t *pField;
|
||||
byte c;
|
||||
int i;
|
||||
|
||||
c = MSG_ReadUBitLong( msg, 3 );
|
||||
|
||||
for( i = 0; i < c; i++ )
|
||||
bits[i] = MSG_ReadByte( msg );
|
||||
|
||||
for( i = 0, pField = dt->pFields; i < dt->numFields; i++, pField++ )
|
||||
{
|
||||
int b = i >> 3;
|
||||
int n = 1 << ( i & 7 );
|
||||
|
||||
if( FBitSet( bits[b], n ))
|
||||
Delta_ReadField_( msg, pField, to, timebase );
|
||||
else Delta_CopyField( pField, from, to, timebase );
|
||||
}
|
||||
}
|
||||
|
||||
void Delta_WriteGSFields( sizebuf_t *msg, int index, void *from, void *to, double timebase )
|
||||
{
|
||||
delta_info_t *dt = Delta_FindStructByIndex( index );
|
||||
delta_t *pField;
|
||||
uint8_t bits[8] = { 0 };
|
||||
uint c = 0;
|
||||
int i;
|
||||
|
||||
Delta_CustomEncode( dt, from, to );
|
||||
|
||||
for( i = 0, pField = dt->pFields; i < dt->numFields; i++, pField++ )
|
||||
{
|
||||
if( !Delta_CompareField( pField, from, to ))
|
||||
{
|
||||
int b = i >> 3;
|
||||
int n = 1 << ( i & 7 );
|
||||
|
||||
SetBits( bits[b], n );
|
||||
c = b + 1;
|
||||
}
|
||||
}
|
||||
|
||||
MSG_WriteUBitLong( msg, c, 3 );
|
||||
for( i = 0; i < c; i++ )
|
||||
MSG_WriteByte( msg, bits[i] );
|
||||
|
||||
for( i = 0, pField = dt->pFields; i < dt->numFields; i++, pField++ )
|
||||
{
|
||||
int b = i >> 3;
|
||||
int n = 1 << ( i & 7 );
|
||||
|
||||
if( FBitSet( bits[b], n ))
|
||||
Delta_WriteField_( msg, pField, from, to, timebase );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
@@ -1425,7 +1554,7 @@ usercmd_t communication
|
||||
MSG_WriteDeltaUsercmd
|
||||
=====================
|
||||
*/
|
||||
void MSG_WriteDeltaUsercmd( sizebuf_t *msg, usercmd_t *from, usercmd_t *to )
|
||||
void MSG_WriteDeltaUsercmd( sizebuf_t *msg, const usercmd_t *from, const usercmd_t *to )
|
||||
{
|
||||
delta_t *pField;
|
||||
delta_info_t *dt;
|
||||
@@ -1452,7 +1581,7 @@ void MSG_WriteDeltaUsercmd( sizebuf_t *msg, usercmd_t *from, usercmd_t *to )
|
||||
MSG_ReadDeltaUsercmd
|
||||
=====================
|
||||
*/
|
||||
void MSG_ReadDeltaUsercmd( sizebuf_t *msg, usercmd_t *from, usercmd_t *to )
|
||||
void MSG_ReadDeltaUsercmd( sizebuf_t *msg, const usercmd_t *from, usercmd_t *to )
|
||||
{
|
||||
delta_t *pField;
|
||||
delta_info_t *dt;
|
||||
@@ -1487,7 +1616,7 @@ event_args_t communication
|
||||
MSG_WriteDeltaEvent
|
||||
=====================
|
||||
*/
|
||||
void MSG_WriteDeltaEvent( sizebuf_t *msg, event_args_t *from, event_args_t *to )
|
||||
void MSG_WriteDeltaEvent( sizebuf_t *msg, const event_args_t *from, const event_args_t *to )
|
||||
{
|
||||
delta_t *pField;
|
||||
delta_info_t *dt;
|
||||
@@ -1514,7 +1643,7 @@ void MSG_WriteDeltaEvent( sizebuf_t *msg, event_args_t *from, event_args_t *to )
|
||||
MSG_ReadDeltaEvent
|
||||
=====================
|
||||
*/
|
||||
void MSG_ReadDeltaEvent( sizebuf_t *msg, event_args_t *from, event_args_t *to )
|
||||
void MSG_ReadDeltaEvent( sizebuf_t *msg, const event_args_t *from, event_args_t *to )
|
||||
{
|
||||
delta_t *pField;
|
||||
delta_info_t *dt;
|
||||
@@ -1542,7 +1671,7 @@ movevars_t communication
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
qboolean MSG_WriteDeltaMovevars( sizebuf_t *msg, movevars_t *from, movevars_t *to )
|
||||
qboolean MSG_WriteDeltaMovevars( sizebuf_t *msg, const movevars_t *from, const movevars_t *to )
|
||||
{
|
||||
delta_t *pField;
|
||||
delta_info_t *dt;
|
||||
@@ -1578,7 +1707,7 @@ qboolean MSG_WriteDeltaMovevars( sizebuf_t *msg, movevars_t *from, movevars_t *t
|
||||
return true;
|
||||
}
|
||||
|
||||
void MSG_ReadDeltaMovevars( sizebuf_t *msg, movevars_t *from, movevars_t *to )
|
||||
void MSG_ReadDeltaMovevars( sizebuf_t *msg, const movevars_t *from, movevars_t *to )
|
||||
{
|
||||
delta_t *pField;
|
||||
delta_info_t *dt;
|
||||
@@ -1614,7 +1743,7 @@ Writes current client data only for local client
|
||||
Other clients can grab the client state from entity_state_t
|
||||
==================
|
||||
*/
|
||||
void MSG_WriteClientData( sizebuf_t *msg, clientdata_t *from, clientdata_t *to, double timebase )
|
||||
void MSG_WriteClientData( sizebuf_t *msg, const clientdata_t *from, const clientdata_t *to, double timebase )
|
||||
{
|
||||
delta_t *pField;
|
||||
delta_info_t *dt;
|
||||
@@ -1654,7 +1783,7 @@ MSG_ReadClientData
|
||||
Read the clientdata
|
||||
==================
|
||||
*/
|
||||
void MSG_ReadClientData( sizebuf_t *msg, clientdata_t *from, clientdata_t *to, double timebase )
|
||||
void MSG_ReadClientData( sizebuf_t *msg, const clientdata_t *from, clientdata_t *to, double timebase )
|
||||
{
|
||||
#if !XASH_DEDICATED
|
||||
delta_t *pField;
|
||||
@@ -1695,7 +1824,7 @@ Writes current client data only for local client
|
||||
Other clients can grab the client state from entity_state_t
|
||||
==================
|
||||
*/
|
||||
void MSG_WriteWeaponData( sizebuf_t *msg, weapon_data_t *from, weapon_data_t *to, double timebase, int index )
|
||||
void MSG_WriteWeaponData( sizebuf_t *msg, const weapon_data_t *from, const weapon_data_t *to, double timebase, int index )
|
||||
{
|
||||
delta_t *pField;
|
||||
delta_info_t *dt;
|
||||
@@ -1734,7 +1863,7 @@ MSG_ReadWeaponData
|
||||
Read the clientdata
|
||||
==================
|
||||
*/
|
||||
void MSG_ReadWeaponData( sizebuf_t *msg, weapon_data_t *from, weapon_data_t *to, double timebase )
|
||||
void MSG_ReadWeaponData( sizebuf_t *msg, const weapon_data_t *from, weapon_data_t *to, double timebase )
|
||||
{
|
||||
delta_t *pField;
|
||||
delta_info_t *dt;
|
||||
@@ -1771,7 +1900,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.
|
||||
==================
|
||||
*/
|
||||
void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, int delta_type, double timebase, int baseline )
|
||||
void MSG_WriteDeltaEntity( const entity_state_t *from, const entity_state_t *to, sizebuf_t *msg, qboolean force, int delta_type, double timebase, int baseline )
|
||||
{
|
||||
delta_info_t *dt = NULL;
|
||||
delta_t *pField;
|
||||
@@ -1873,7 +2002,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
|
||||
==================
|
||||
*/
|
||||
qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state_t *to, int number, int delta_type, double timebase )
|
||||
qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, const entity_state_t *from, entity_state_t *to, int number, int delta_type, double timebase )
|
||||
{
|
||||
#if !XASH_DEDICATED
|
||||
delta_info_t *dt = NULL;
|
||||
@@ -1882,7 +2011,10 @@ qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state
|
||||
int baseline_offset = 0;
|
||||
|
||||
if( number < 0 || number >= clgame.maxEntities )
|
||||
Host_Error( "%s: bad delta entity number: %i\n", __func__, number );
|
||||
{
|
||||
Con_Printf( S_ERROR "%s: bad delta entity number: %i\n", __func__, number );
|
||||
return false;
|
||||
}
|
||||
|
||||
fRemoveType = MSG_ReadUBitLong( msg, 2 );
|
||||
|
||||
@@ -1904,7 +2036,8 @@ qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state
|
||||
return false;
|
||||
}
|
||||
|
||||
Host_Error( "%s: unknown update type %i\n", __func__, fRemoveType );
|
||||
Con_Printf( S_ERROR "%s: unknown update type %i\n", __func__, fRemoveType );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !cls.legacymode )
|
||||
@@ -1952,7 +2085,11 @@ qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state
|
||||
dt = Delta_FindStructByIndex( DT_ENTITY_STATE_T );
|
||||
}
|
||||
|
||||
Assert( dt && dt->bInitialized );
|
||||
if( !dt || !dt->bInitialized )
|
||||
{
|
||||
Con_Printf( S_ERROR "%s: broken delta\n", __func__ );
|
||||
return true;
|
||||
}
|
||||
|
||||
pField = dt->pFields;
|
||||
Assert( pField != NULL );
|
||||
|
||||
@@ -33,6 +33,23 @@ enum
|
||||
DELTA_STATIC,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
DT_EVENT_T = 0,
|
||||
DT_MOVEVARS_T,
|
||||
DT_USERCMD_T,
|
||||
DT_CLIENTDATA_T,
|
||||
DT_WEAPONDATA_T,
|
||||
DT_ENTITY_STATE_T,
|
||||
DT_ENTITY_STATE_PLAYER_T,
|
||||
DT_CUSTOM_ENTITY_STATE_T,
|
||||
DT_GOLDSRC_DELTA_T,
|
||||
#if XASH_ENGINE_TESTS
|
||||
DT_DELTA_TEST_STRUCT_T,
|
||||
#endif
|
||||
DT_STRUCT_COUNT
|
||||
};
|
||||
|
||||
// struct info (filled by engine)
|
||||
typedef struct
|
||||
{
|
||||
@@ -54,6 +71,17 @@ struct delta_s
|
||||
qboolean bInactive; // unsetted by user request
|
||||
};
|
||||
|
||||
typedef struct goldsrc_delta_s
|
||||
{
|
||||
int fieldType;
|
||||
char fieldName[32];
|
||||
int fieldOffset;
|
||||
short fieldSize;
|
||||
int significant_bits;
|
||||
float premultiply;
|
||||
float postmultiply;
|
||||
} goldsrc_delta_t;
|
||||
|
||||
typedef void (*pfnDeltaEncode)( struct delta_s *pFields, const byte *from, const byte *to );
|
||||
|
||||
typedef struct
|
||||
@@ -76,6 +104,7 @@ typedef struct
|
||||
//
|
||||
void Delta_Init( void );
|
||||
void Delta_InitClient( void );
|
||||
void Delta_InitMeta( void );
|
||||
void Delta_Shutdown( void );
|
||||
void Delta_AddEncoder( char *name, pfnDeltaEncode encodeFunc );
|
||||
int Delta_FindField( delta_t *pFields, const char *fieldname );
|
||||
@@ -87,6 +116,7 @@ void Delta_UnsetFieldByIndex( delta_t *pFields, int fieldNumber );
|
||||
// send table over network
|
||||
void Delta_WriteDescriptionToClient( sizebuf_t *msg );
|
||||
void Delta_ParseTableField( sizebuf_t *msg );
|
||||
void Delta_ParseTableField_GS( sizebuf_t *msg );
|
||||
|
||||
|
||||
// encode routines
|
||||
@@ -96,18 +126,20 @@ struct event_args_s;
|
||||
struct movevars_s;
|
||||
struct clientdata_s;
|
||||
struct weapon_data_s;
|
||||
void MSG_WriteDeltaUsercmd( sizebuf_t *msg, struct usercmd_s *from, struct usercmd_s *to );
|
||||
void MSG_ReadDeltaUsercmd( sizebuf_t *msg, struct usercmd_s *from, struct usercmd_s *to );
|
||||
void MSG_WriteDeltaEvent( sizebuf_t *msg, struct event_args_s *from, struct event_args_s *to );
|
||||
void MSG_ReadDeltaEvent( sizebuf_t *msg, struct event_args_s *from, struct event_args_s *to );
|
||||
qboolean MSG_WriteDeltaMovevars( sizebuf_t *msg, struct movevars_s *from, struct movevars_s *to );
|
||||
void MSG_ReadDeltaMovevars( sizebuf_t *msg, struct movevars_s *from, struct movevars_s *to );
|
||||
void MSG_WriteClientData( sizebuf_t *msg, struct clientdata_s *from, struct clientdata_s *to, double timebase );
|
||||
void MSG_ReadClientData( sizebuf_t *msg, struct clientdata_s *from, struct clientdata_s *to, double timebase );
|
||||
void MSG_WriteWeaponData( sizebuf_t *msg, struct weapon_data_s *from, struct weapon_data_s *to, double timebase, int index );
|
||||
void MSG_ReadWeaponData( sizebuf_t *msg, struct weapon_data_s *from, struct weapon_data_s *to, double timebase );
|
||||
void MSG_WriteDeltaEntity( struct entity_state_s *from, struct entity_state_s *to, sizebuf_t *msg, qboolean force, int type, double timebase, int ofs );
|
||||
qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, struct entity_state_s *from, struct entity_state_s *to, int num, int type, double timebase );
|
||||
int Delta_TestBaseline( struct entity_state_s *from, struct entity_state_s *to, qboolean player, double timebase );
|
||||
void MSG_WriteDeltaUsercmd( sizebuf_t *msg, const struct usercmd_s *from, const struct usercmd_s *to );
|
||||
void MSG_ReadDeltaUsercmd( sizebuf_t *msg, const struct usercmd_s *from, struct usercmd_s *to );
|
||||
void MSG_WriteDeltaEvent( sizebuf_t *msg, const struct event_args_s *from, const struct event_args_s *to );
|
||||
void MSG_ReadDeltaEvent( sizebuf_t *msg, const struct event_args_s *from, struct event_args_s *to );
|
||||
qboolean MSG_WriteDeltaMovevars( sizebuf_t *msg, const struct movevars_s *from, const struct movevars_s *to );
|
||||
void MSG_ReadDeltaMovevars( sizebuf_t *msg, const struct movevars_s *from, struct movevars_s *to );
|
||||
void MSG_WriteClientData( sizebuf_t *msg, const struct clientdata_s *from, const struct clientdata_s *to, double timebase );
|
||||
void MSG_ReadClientData( sizebuf_t *msg, const struct clientdata_s *from, struct clientdata_s *to, double timebase );
|
||||
void MSG_WriteWeaponData( sizebuf_t *msg, const struct weapon_data_s *from, const struct weapon_data_s *to, double timebase, int index );
|
||||
void MSG_ReadWeaponData( sizebuf_t *msg, const struct weapon_data_s *from, struct weapon_data_s *to, double timebase );
|
||||
void MSG_WriteDeltaEntity( const struct entity_state_s *from, const struct entity_state_s *to, sizebuf_t *msg, qboolean force, int type, double timebase, int ofs );
|
||||
qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, const struct entity_state_s *from, struct entity_state_s *to, int num, int type, double timebase );
|
||||
int Delta_TestBaseline( const struct entity_state_s *from, const struct entity_state_s *to, qboolean player, double timebase );
|
||||
void Delta_ReadGSFields( sizebuf_t *msg, int index, void *from, void *to, double timebase );
|
||||
void Delta_WriteGSFields( sizebuf_t *msg, int index, void *from, void *to, double timebase );
|
||||
|
||||
#endif//NET_ENCODE_H
|
||||
|
||||
@@ -18,16 +18,20 @@ GNU General Public License for more details.
|
||||
#include "netchan.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
#include "ipv6text.h"
|
||||
#if XASH_WIN32
|
||||
#include "platform/win32/net.h"
|
||||
#elif defined XASH_NO_NETWORK
|
||||
|
||||
#if XASH_NO_NETWORK
|
||||
#include "platform/stub/net_stub.h"
|
||||
#elif XASH_WIN32
|
||||
#include "platform/win32/net.h"
|
||||
#elif XASH_PSVITA
|
||||
#include "platform/psvita/net_psvita.h"
|
||||
static const struct in6_addr in6addr_any;
|
||||
#else
|
||||
#include "platform/posix/net.h"
|
||||
#endif
|
||||
#if XASH_PSVITA
|
||||
#include "platform/psvita/net_psvita.h"
|
||||
static const struct in6_addr in6addr_any;
|
||||
|
||||
#if XASH_SDL == 2
|
||||
#include <SDL_thread.h>
|
||||
#endif
|
||||
|
||||
#define NET_USE_FRAGMENTS
|
||||
@@ -83,6 +87,13 @@ typedef struct
|
||||
int sequence_number;
|
||||
short packet_id;
|
||||
} SPLITPACKET;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int net_id;
|
||||
int sequence_number;
|
||||
unsigned char packet_id;
|
||||
} SPLITPACKETGS;
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct
|
||||
@@ -115,6 +126,7 @@ static CVAR_DEFINE( net_ipclientport, "ip_clientport", "0", FCVAR_READ_ONLY, "ne
|
||||
static CVAR_DEFINE( net_clientport, "clientport", "0", FCVAR_READ_ONLY, "network default client port" );
|
||||
static CVAR_DEFINE( net_fakelag, "fakelag", "0", FCVAR_PRIVILEGED, "lag all incoming network data (including loopback) by xxx ms." );
|
||||
static CVAR_DEFINE( net_fakeloss, "fakeloss", "0", FCVAR_PRIVILEGED, "act like we dropped the packet this % of the time." );
|
||||
static CVAR_DEFINE_AUTO( net_resolve_debug, "0", FCVAR_PRIVILEGED, "print resolve thread debug messages" );
|
||||
CVAR_DEFINE( net_clockwindow, "clockwindow", "0.5", FCVAR_PRIVILEGED, "timewindow to execute client moves" );
|
||||
|
||||
netadr_t net_local;
|
||||
@@ -126,6 +138,8 @@ static CVAR_DEFINE( net_ip6hostport, "ip6_hostport", "0", FCVAR_READ_ONLY, "netw
|
||||
static CVAR_DEFINE( net_ip6clientport, "ip6_clientport", "0", FCVAR_READ_ONLY, "network ip6 client port" );
|
||||
static CVAR_DEFINE_AUTO( net6_address, "0", FCVAR_PRIVILEGED|FCVAR_READ_ONLY, "contain local IPv6 address of current client" );
|
||||
|
||||
static void NET_ClearLagData( qboolean bClient, qboolean bServer );
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_ErrorString
|
||||
@@ -192,7 +206,7 @@ static char *NET_ErrorString( void )
|
||||
#endif
|
||||
}
|
||||
|
||||
_inline socklen_t NET_SockAddrLen( const struct sockaddr_storage *addr )
|
||||
static inline socklen_t NET_SockAddrLen( const struct sockaddr_storage *addr )
|
||||
{
|
||||
switch ( addr->ss_family )
|
||||
{
|
||||
@@ -205,7 +219,7 @@ _inline socklen_t NET_SockAddrLen( const struct sockaddr_storage *addr )
|
||||
}
|
||||
}
|
||||
|
||||
_inline qboolean NET_IsSocketError( int retval )
|
||||
static inline qboolean NET_IsSocketError( int retval )
|
||||
{
|
||||
#if XASH_WIN32 || XASH_DOS4GW
|
||||
return retval == SOCKET_ERROR ? true : false;
|
||||
@@ -214,7 +228,7 @@ _inline qboolean NET_IsSocketError( int retval )
|
||||
#endif
|
||||
}
|
||||
|
||||
_inline qboolean NET_IsSocketValid( int socket )
|
||||
static inline qboolean NET_IsSocketValid( int socket )
|
||||
{
|
||||
#if XASH_WIN32 || XASH_DOS4GW
|
||||
return socket != INVALID_SOCKET;
|
||||
@@ -249,40 +263,27 @@ static void NET_NetadrToSockadr( netadr_t *a, struct sockaddr_storage *s )
|
||||
|
||||
if( a->type == NA_BROADCAST )
|
||||
{
|
||||
((struct sockaddr_in *)s)->sin_family = AF_INET;
|
||||
s->ss_family = AF_INET;
|
||||
((struct sockaddr_in *)s)->sin_port = a->port;
|
||||
((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST;
|
||||
}
|
||||
else if( a->type == NA_IP )
|
||||
{
|
||||
((struct sockaddr_in *)s)->sin_family = AF_INET;
|
||||
s->ss_family = AF_INET;
|
||||
((struct sockaddr_in *)s)->sin_port = a->port;
|
||||
((struct sockaddr_in *)s)->sin_addr.s_addr = a->ip4;
|
||||
}
|
||||
else if( a->type6 == NA_IP6 )
|
||||
{
|
||||
struct in6_addr ip6;
|
||||
|
||||
NET_NetadrToIP6Bytes( ip6.s6_addr, a );
|
||||
|
||||
if( IN6_IS_ADDR_V4MAPPED( &ip6 ))
|
||||
{
|
||||
((struct sockaddr_in *)s)->sin_family = AF_INET;
|
||||
((struct sockaddr_in *)s)->sin_addr.s_addr = *(uint32_t *)(ip6.s6_addr + 12);
|
||||
((struct sockaddr_in *)s)->sin_port = a->port;
|
||||
}
|
||||
else
|
||||
{
|
||||
((struct sockaddr_in6 *)s)->sin6_family = AF_INET6;
|
||||
memcpy( &((struct sockaddr_in6 *)s)->sin6_addr, &ip6, sizeof( struct in6_addr ));
|
||||
((struct sockaddr_in6 *)s)->sin6_port = a->port;
|
||||
}
|
||||
s->ss_family = AF_INET6;
|
||||
((struct sockaddr_in6 *)s)->sin6_port = a->port;
|
||||
NET_NetadrToIP6Bytes(((struct sockaddr_in6 *)s)->sin6_addr.s6_addr, a );
|
||||
}
|
||||
else if( a->type6 == NA_MULTICAST_IP6 )
|
||||
{
|
||||
((struct sockaddr_in6 *)s)->sin6_family = AF_INET6;
|
||||
memcpy(((struct sockaddr_in6 *)s)->sin6_addr.s6_addr, k_ipv6Bytes_LinkLocalAllNodes, sizeof( struct in6_addr ));
|
||||
s->ss_family = AF_INET6;
|
||||
((struct sockaddr_in6 *)s)->sin6_port = a->port;
|
||||
memcpy(((struct sockaddr_in6 *)s)->sin6_addr.s6_addr, k_ipv6Bytes_LinkLocalAllNodes, sizeof( struct in6_addr ));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,13 +302,8 @@ static void NET_SockadrToNetadr( const struct sockaddr_storage *s, netadr_t *a )
|
||||
}
|
||||
else if( s->ss_family == AF_INET6 )
|
||||
{
|
||||
a->type6 = NA_IP6;
|
||||
NET_IP6BytesToNetadr( a, ((struct sockaddr_in6 *)s)->sin6_addr.s6_addr );
|
||||
|
||||
if( IN6_IS_ADDR_V4MAPPED( &((struct sockaddr_in6 *)s)->sin6_addr ))
|
||||
a->type = NA_IP;
|
||||
else
|
||||
a->type6 = NA_IP6;
|
||||
|
||||
a->port = ((struct sockaddr_in6 *)s)->sin6_port;
|
||||
}
|
||||
}
|
||||
@@ -324,6 +320,11 @@ static qboolean NET_GetHostByName( const char *hostname, int family, struct sock
|
||||
struct addrinfo hints;
|
||||
qboolean ret = false;
|
||||
|
||||
#if XASH_NO_IPV6_RESOLVE
|
||||
if( family == AF_INET6 )
|
||||
return false;
|
||||
#endif
|
||||
|
||||
memset( &hints, 0, sizeof( hints ));
|
||||
hints.ai_family = family;
|
||||
|
||||
@@ -346,6 +347,12 @@ static qboolean NET_GetHostByName( const char *hostname, int family, struct sock
|
||||
return ret;
|
||||
#else
|
||||
struct hostent *h;
|
||||
|
||||
#if XASH_NO_IPV6_RESOLVE
|
||||
if( family == AF_INET6 )
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if(!( h = gethostbyname( hostname )))
|
||||
return false;
|
||||
|
||||
@@ -363,27 +370,44 @@ static qboolean NET_GetHostByName( const char *hostname, int family, struct sock
|
||||
#ifdef CAN_ASYNC_NS_RESOLVE
|
||||
static void NET_ResolveThread( void );
|
||||
|
||||
#if !XASH_WIN32
|
||||
#if XASH_SDL == 2
|
||||
#define mutex_create( x ) (( x ) = SDL_CreateMutex() )
|
||||
#define mutex_destroy( x ) SDL_DestroyMutex(( x ))
|
||||
#define mutex_lock( x ) SDL_LockMutex(( x ))
|
||||
#define mutex_unlock( x ) SDL_UnlockMutex(( x ))
|
||||
#define create_thread( thread, pfn ) (( thread ) = SDL_CreateThread(( pfn ), "DNS resolver thread", NULL ))
|
||||
#define detach_thread( x ) SDL_DetachThread(( x ))
|
||||
typedef SDL_mutex *mutex_t;
|
||||
typedef SDL_Thread *thread_t;
|
||||
static int NET_ThreadStart( void *ununsed )
|
||||
{
|
||||
NET_ResolveThread();
|
||||
return 0;
|
||||
}
|
||||
#elif !XASH_WIN32
|
||||
#include <pthread.h>
|
||||
#define mutex_lock pthread_mutex_lock
|
||||
#define mutex_unlock pthread_mutex_unlock
|
||||
#define exit_thread( x ) pthread_exit(x)
|
||||
#define create_thread( pfn ) !pthread_create( &nsthread.thread, NULL, (pfn), NULL )
|
||||
#define detach_thread( x ) pthread_detach(x)
|
||||
#define mutex_t pthread_mutex_t
|
||||
#define thread_t pthread_t
|
||||
#define mutex_create( x ) pthread_mutex_init( &( x ), NULL )
|
||||
#define mutex_destroy( x ) pthread_mutex_destroy( &( x ))
|
||||
#define mutex_lock( x ) pthread_mutex_lock( &( x ))
|
||||
#define mutex_unlock( x ) pthread_mutex_unlock( &( x ))
|
||||
#define create_thread( thread, pfn ) !pthread_create( &( thread ), NULL, ( pfn ), NULL )
|
||||
#define detach_thread( x ) pthread_detach( x )
|
||||
typedef pthread_mutex_t mutex_t;
|
||||
typedef pthread_t thread_t;
|
||||
static void *NET_ThreadStart( void *unused )
|
||||
{
|
||||
NET_ResolveThread();
|
||||
return NULL;
|
||||
}
|
||||
#else // WIN32
|
||||
#define mutex_lock EnterCriticalSection
|
||||
#define mutex_unlock LeaveCriticalSection
|
||||
#define detach_thread( x ) CloseHandle(x)
|
||||
#define create_thread( pfn ) ( nsthread.thread = CreateThread( NULL, 0, pfn, NULL, 0, NULL ))
|
||||
#define mutex_t CRITICAL_SECTION
|
||||
#define thread_t HANDLE
|
||||
#define mutex_create( x ) InitializeCriticalSection( &( x ))
|
||||
#define mutex_destroy( x ) DeleteCriticalSection( &( x ))
|
||||
#define mutex_lock( x ) EnterCriticalSection( &( x ))
|
||||
#define mutex_unlock( x ) LeaveCriticalSection( &( x ))
|
||||
#define create_thread( thread, pfn ) (( thread ) = CreateThread( NULL, 0, ( pfn ), NULL, 0, NULL ))
|
||||
#define detach_thread( x ) CloseHandle(( x ))
|
||||
typedef CRITICAL_SECTION mutex_t;
|
||||
typedef HANDLE thread_t;
|
||||
DWORD WINAPI NET_ThreadStart( LPVOID unused )
|
||||
{
|
||||
NET_ResolveThread();
|
||||
@@ -392,38 +416,42 @@ DWORD WINAPI NET_ThreadStart( LPVOID unused )
|
||||
}
|
||||
#endif // !_WIN32
|
||||
|
||||
#ifdef DEBUG_RESOLVE
|
||||
#define RESOLVE_DBG(x) Sys_PrintLog(x)
|
||||
#else
|
||||
#define RESOLVE_DBG(x)
|
||||
#endif // DEBUG_RESOLVE
|
||||
#define RESOLVE_DBG( x ) do { if( net_resolve_debug.value ) Sys_PrintLog(( x )); } while( 0 )
|
||||
|
||||
static struct nsthread_s
|
||||
{
|
||||
mutex_t mutexns;
|
||||
mutex_t mutexres;
|
||||
mutex_t mutexns;
|
||||
mutex_t mutexres;
|
||||
thread_t thread;
|
||||
int result;
|
||||
string hostname;
|
||||
int family;
|
||||
int result;
|
||||
string hostname;
|
||||
int family;
|
||||
struct sockaddr_storage addr;
|
||||
qboolean busy;
|
||||
} nsthread
|
||||
#if !XASH_WIN32
|
||||
= { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER }
|
||||
#endif
|
||||
;
|
||||
} nsthread;
|
||||
|
||||
static void NET_InitializeCriticalSections( void )
|
||||
{
|
||||
net.threads_initialized = true;
|
||||
#if XASH_WIN32
|
||||
InitializeCriticalSection( &nsthread.mutexns );
|
||||
InitializeCriticalSection( &nsthread.mutexres );
|
||||
#endif
|
||||
|
||||
mutex_create( nsthread.mutexns );
|
||||
mutex_create( nsthread.mutexres );
|
||||
}
|
||||
|
||||
void NET_ResolveThread( void )
|
||||
static void NET_DeleteCriticalSections( void )
|
||||
{
|
||||
if( net.threads_initialized )
|
||||
{
|
||||
mutex_destroy( nsthread.mutexns );
|
||||
mutex_destroy( nsthread.mutexres );
|
||||
|
||||
net.threads_initialized = false;
|
||||
}
|
||||
|
||||
memset( &nsthread, 0, sizeof( nsthread ));
|
||||
}
|
||||
|
||||
static void NET_ResolveThread( void )
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
qboolean res;
|
||||
@@ -440,12 +468,12 @@ void NET_ResolveThread( void )
|
||||
RESOLVE_DBG( "[resolve thread] success\n" );
|
||||
else
|
||||
RESOLVE_DBG( "[resolve thread] failed\n" );
|
||||
mutex_lock( &nsthread.mutexres );
|
||||
mutex_lock( nsthread.mutexres );
|
||||
nsthread.addr = addr;
|
||||
nsthread.busy = false;
|
||||
nsthread.result = res ? NET_EAI_OK : NET_EAI_NONAME;
|
||||
RESOLVE_DBG( "[resolve thread] returning result\n" );
|
||||
mutex_unlock( &nsthread.mutexres );
|
||||
mutex_unlock( nsthread.mutexres );
|
||||
RESOLVE_DBG( "[resolve thread] exiting thread\n" );
|
||||
}
|
||||
#endif // CAN_ASYNC_NS_RESOLVE
|
||||
@@ -510,11 +538,11 @@ static net_gai_state_t NET_StringToSockaddr( const char *s, struct sockaddr_stor
|
||||
#ifdef CAN_ASYNC_NS_RESOLVE
|
||||
if( net.threads_initialized && nonblocking )
|
||||
{
|
||||
mutex_lock( &nsthread.mutexres );
|
||||
mutex_lock( nsthread.mutexres );
|
||||
|
||||
if( nsthread.busy )
|
||||
{
|
||||
mutex_unlock( &nsthread.mutexres );
|
||||
mutex_unlock( nsthread.mutexres );
|
||||
return NET_EAI_AGAIN;
|
||||
}
|
||||
|
||||
@@ -535,28 +563,24 @@ static net_gai_state_t NET_StringToSockaddr( const char *s, struct sockaddr_stor
|
||||
Q_strncpy( nsthread.hostname, copy, sizeof( nsthread.hostname ));
|
||||
nsthread.family = family;
|
||||
nsthread.busy = true;
|
||||
mutex_unlock( &nsthread.mutexres );
|
||||
mutex_unlock( nsthread.mutexres );
|
||||
|
||||
if( create_thread( NET_ThreadStart ))
|
||||
if( create_thread( nsthread.thread, NET_ThreadStart ))
|
||||
{
|
||||
asyncfailed = false;
|
||||
return NET_EAI_AGAIN;
|
||||
}
|
||||
else // failed to create thread
|
||||
{
|
||||
Con_Reportf( S_ERROR "%s: failed to create thread!\n", __func__ );
|
||||
nsthread.busy = false;
|
||||
}
|
||||
|
||||
Con_Reportf( S_ERROR "%s: failed to create thread!\n", __func__ );
|
||||
nsthread.busy = false;
|
||||
}
|
||||
|
||||
mutex_unlock( &nsthread.mutexres );
|
||||
mutex_unlock( nsthread.mutexres );
|
||||
}
|
||||
#endif // CAN_ASYNC_NS_RESOLVE
|
||||
|
||||
if( asyncfailed )
|
||||
{
|
||||
ret = NET_GetHostByName( copy, family, &temp );
|
||||
}
|
||||
|
||||
if( !ret )
|
||||
{
|
||||
@@ -570,16 +594,9 @@ static net_gai_state_t NET_StringToSockaddr( const char *s, struct sockaddr_stor
|
||||
sadr->ss_family = temp.ss_family;
|
||||
|
||||
if( temp.ss_family == AF_INET )
|
||||
{
|
||||
((struct sockaddr_in *)sadr)->sin_addr =
|
||||
((struct sockaddr_in*)&temp)->sin_addr;
|
||||
}
|
||||
((struct sockaddr_in *)sadr)->sin_addr = ((struct sockaddr_in*)&temp)->sin_addr;
|
||||
else if( temp.ss_family == AF_INET6 )
|
||||
{
|
||||
memcpy(&((struct sockaddr_in6 *)sadr)->sin6_addr,
|
||||
&((struct sockaddr_in6*)&temp)->sin6_addr,
|
||||
sizeof( struct in6_addr ));
|
||||
}
|
||||
((struct sockaddr_in6 *)sadr)->sin6_addr = ((struct sockaddr_in6*)&temp)->sin6_addr;
|
||||
}
|
||||
|
||||
return NET_EAI_OK;
|
||||
@@ -1042,19 +1059,20 @@ qboolean NET_StringToAdr( const char *string, netadr_t *adr )
|
||||
return NET_StringToAdrEx( string, adr, AF_UNSPEC );
|
||||
}
|
||||
|
||||
net_gai_state_t NET_StringToAdrNB( const char *string, netadr_t *adr )
|
||||
net_gai_state_t NET_StringToAdrNB( const char *string, netadr_t *adr, qboolean v6only )
|
||||
{
|
||||
struct sockaddr_storage s;
|
||||
net_gai_state_t res;
|
||||
|
||||
memset( adr, 0, sizeof( netadr_t ));
|
||||
|
||||
if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" ))
|
||||
{
|
||||
adr->type = NA_LOOPBACK;
|
||||
return NET_EAI_OK;
|
||||
}
|
||||
|
||||
res = NET_StringToSockaddr( string, &s, true, AF_UNSPEC );
|
||||
res = NET_StringToSockaddr( string, &s, true, v6only ? AF_INET6 : AF_UNSPEC );
|
||||
|
||||
if( res == NET_EAI_OK )
|
||||
NET_SockadrToNetadr( &s, adr );
|
||||
@@ -1339,28 +1357,42 @@ NET_GetLong
|
||||
receive long packet from network
|
||||
==================
|
||||
*/
|
||||
static qboolean NET_GetLong( byte *pData, int size, size_t *outSize, int splitsize )
|
||||
static qboolean NET_GetLong( byte *pData, int size, size_t *outSize, int splitsize, connprotocol_t proto )
|
||||
{
|
||||
int i, sequence_number, offset;
|
||||
SPLITPACKET *pHeader = (SPLITPACKET *)pData;
|
||||
int packet_number;
|
||||
int packet_count;
|
||||
short packet_id;
|
||||
int body_size = splitsize - sizeof( SPLITPACKET );
|
||||
size_t header_size = proto == PROTO_GOLDSRC ? sizeof( SPLITPACKETGS ) : sizeof( SPLITPACKET );
|
||||
int body_size = splitsize - header_size;
|
||||
|
||||
if( body_size < 0 )
|
||||
return false;
|
||||
|
||||
if( size < sizeof( SPLITPACKET ))
|
||||
if( size < header_size )
|
||||
{
|
||||
Con_Printf( S_ERROR "invalid split packet length %i\n", size );
|
||||
return false;
|
||||
}
|
||||
|
||||
sequence_number = pHeader->sequence_number;
|
||||
packet_id = pHeader->packet_id;
|
||||
packet_count = ( packet_id & 0xFF );
|
||||
packet_number = ( packet_id >> 8 );
|
||||
if( proto == PROTO_GOLDSRC )
|
||||
{
|
||||
SPLITPACKETGS *pHeader = (SPLITPACKETGS *)pData;
|
||||
|
||||
sequence_number = pHeader->sequence_number;
|
||||
packet_id = pHeader->packet_id;
|
||||
packet_count = ( packet_id & 0xF );
|
||||
packet_number = ( packet_id >> 4 );
|
||||
}
|
||||
else
|
||||
{
|
||||
SPLITPACKET *pHeader = (SPLITPACKET *)pData;
|
||||
|
||||
sequence_number = pHeader->sequence_number;
|
||||
packet_id = pHeader->packet_id;
|
||||
packet_count = ( packet_id & 0xFF );
|
||||
packet_number = ( packet_id >> 8 );
|
||||
}
|
||||
|
||||
if( packet_number >= NET_MAX_FRAGMENTS || packet_count > NET_MAX_FRAGMENTS )
|
||||
{
|
||||
@@ -1382,7 +1414,7 @@ static qboolean NET_GetLong( byte *pData, int size, size_t *outSize, int splitsi
|
||||
Con_Printf( "<-- Split packet restart %i count %i seq\n", net.split.split_count, sequence_number );
|
||||
}
|
||||
|
||||
size -= sizeof( SPLITPACKET );
|
||||
size -= header_size;
|
||||
|
||||
if( net.split_flags[packet_number] != sequence_number )
|
||||
{
|
||||
@@ -1401,7 +1433,7 @@ static qboolean NET_GetLong( byte *pData, int size, size_t *outSize, int splitsi
|
||||
}
|
||||
|
||||
offset = (packet_number * body_size);
|
||||
memcpy( net.split.buffer + offset, pData + sizeof( SPLITPACKET ), size );
|
||||
memcpy( net.split.buffer + offset, pData + header_size, size );
|
||||
|
||||
// have we received all of the pieces to the packet?
|
||||
if( net.split.split_count <= 0 )
|
||||
@@ -1464,13 +1496,15 @@ static qboolean NET_QueuePacket( netsrc_t sock, netadr_t *from, byte *data, size
|
||||
memcpy( data, buf, ret );
|
||||
*length = ret;
|
||||
#if !XASH_DEDICATED
|
||||
if( CL_LegacyMode( ))
|
||||
return NET_LagPacket( true, sock, from, length, data );
|
||||
|
||||
// check for split message
|
||||
if( sock == NS_CLIENT && *(int *)data == NET_HEADER_SPLITPACKET )
|
||||
{
|
||||
return NET_GetLong( data, ret, length, CL_GetSplitSize( ));
|
||||
connprotocol_t proto = CL_Protocol();
|
||||
|
||||
if( proto == PROTO_LEGACY )
|
||||
return NET_LagPacket( true, sock, from, length, data );
|
||||
|
||||
// check for split message
|
||||
if( sock == NS_CLIENT && *(int *)data == NET_HEADER_SPLITPACKET )
|
||||
return NET_GetLong( data, ret, length, CL_GetSplitSize( ), proto );
|
||||
}
|
||||
#endif
|
||||
// lag the packet, if needed
|
||||
@@ -1735,7 +1769,7 @@ static int NET_IPSocket( const char *net_iface, int port, int family )
|
||||
|
||||
if( COM_CheckStringEmpty( net_iface ) && Q_stricmp( net_iface, "localhost" ))
|
||||
NET_StringToSockaddr( net_iface, &addr, false, AF_INET6 );
|
||||
else memcpy(((struct sockaddr_in6 *)&addr)->sin6_addr.s6_addr, &in6addr_any, sizeof( struct in6_addr ));
|
||||
else ((struct sockaddr_in6 *)&addr)->sin6_addr = in6addr_any;
|
||||
|
||||
if( port == PORT_ANY ) ((struct sockaddr_in6 *)&addr)->sin6_port = 0;
|
||||
else ((struct sockaddr_in6 *)&addr)->sin6_port = htons((short)port);
|
||||
@@ -2068,7 +2102,7 @@ NET_ClearLagData
|
||||
clear fakelag list
|
||||
====================
|
||||
*/
|
||||
void NET_ClearLagData( qboolean bClient, qboolean bServer )
|
||||
static void NET_ClearLagData( qboolean bClient, qboolean bServer )
|
||||
{
|
||||
if( bClient ) NET_ClearLaggedList( &net.lagdata[NS_CLIENT] );
|
||||
if( bServer ) NET_ClearLaggedList( &net.lagdata[NS_SERVER] );
|
||||
@@ -2094,6 +2128,7 @@ void NET_Init( void )
|
||||
Cvar_RegisterVariable( &net_clientport );
|
||||
Cvar_RegisterVariable( &net_fakelag );
|
||||
Cvar_RegisterVariable( &net_fakeloss );
|
||||
Cvar_RegisterVariable( &net_resolve_debug );
|
||||
|
||||
Q_snprintf( cmd, sizeof( cmd ), "%i", PORT_SERVER );
|
||||
Cvar_FullSet( "hostport", cmd, FCVAR_READ_ONLY );
|
||||
@@ -2167,6 +2202,11 @@ void NET_Shutdown( void )
|
||||
NET_ClearLagData( true, true );
|
||||
|
||||
NET_Config( false, false );
|
||||
|
||||
#ifdef CAN_ASYNC_NS_RESOLVE
|
||||
NET_DeleteCriticalSections();
|
||||
#endif
|
||||
|
||||
#if XASH_WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
|
||||
@@ -66,7 +66,7 @@ qboolean NET_IsReservedAdr( netadr_t a );
|
||||
qboolean NET_CompareClassBAdr( const netadr_t a, const netadr_t b );
|
||||
qboolean NET_StringToAdr( const char *string, netadr_t *adr );
|
||||
qboolean NET_StringToFilterAdr( const char *s, netadr_t *adr, uint *prefixlen );
|
||||
net_gai_state_t NET_StringToAdrNB( const char *string, netadr_t *adr );
|
||||
net_gai_state_t NET_StringToAdrNB( const char *string, netadr_t *adr, qboolean v6only );
|
||||
int NET_CompareAdrSort( const void *_a, const void *_b );
|
||||
qboolean NET_CompareAdr( const netadr_t a, const netadr_t b );
|
||||
qboolean NET_CompareBaseAdr( const netadr_t a, const netadr_t b );
|
||||
@@ -74,12 +74,10 @@ qboolean NET_CompareAdrByMask( const netadr_t a, const netadr_t b, uint prefixle
|
||||
qboolean NET_GetPacket( netsrc_t sock, netadr_t *from, byte *data, size_t *length );
|
||||
void NET_SendPacket( netsrc_t sock, size_t length, const void *data, netadr_t to );
|
||||
void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t to, size_t splitsize );
|
||||
void NET_ClearLagData( qboolean bClient, qboolean bServer );
|
||||
void NET_IP6BytesToNetadr( netadr_t *adr, const uint8_t *ip6 );
|
||||
void NET_NetadrToIP6Bytes( uint8_t *ip6, const netadr_t *adr );
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
qboolean CL_LegacyMode( void );
|
||||
int CL_GetSplitSize( void );
|
||||
#endif
|
||||
|
||||
|
||||
@@ -208,6 +208,14 @@ typedef enum fragsize_e
|
||||
FRAGSIZE_UNRELIABLE
|
||||
} fragsize_t;
|
||||
|
||||
typedef enum netchan_flags_e
|
||||
{
|
||||
NETCHAN_USE_LEGACY_SPLIT = BIT( 0 ),
|
||||
NETCHAN_USE_MUNGE = BIT( 1 ),
|
||||
NETCHAN_USE_BZIP2 = BIT( 2 ),
|
||||
NETCHAN_GOLDSRC = BIT( 3 ),
|
||||
} netchan_flags_t;
|
||||
|
||||
// Network Connection Channel
|
||||
typedef struct netchan_s
|
||||
{
|
||||
@@ -270,10 +278,14 @@ typedef struct netchan_s
|
||||
// added for net_speeds
|
||||
size_t total_sended;
|
||||
size_t total_received;
|
||||
qboolean split;
|
||||
unsigned int maxpacket;
|
||||
unsigned int splitid;
|
||||
netsplit_t netsplit;
|
||||
netsplit_t netsplit;
|
||||
|
||||
qboolean split;
|
||||
qboolean use_munge;
|
||||
qboolean use_bz2;
|
||||
qboolean gs_netchan;
|
||||
} netchan_t;
|
||||
|
||||
extern netadr_t net_from;
|
||||
@@ -287,7 +299,7 @@ extern int net_drop;
|
||||
|
||||
void Netchan_Init( void );
|
||||
void Netchan_Shutdown( void );
|
||||
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, void *client, int (*pfnBlockSize)(void *, fragsize_t mode ) );
|
||||
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, void *client, int (*pfnBlockSize)(void *, fragsize_t mode ), uint flags );
|
||||
void Netchan_CreateFileFragmentsFromBuffer( netchan_t *chan, const char *filename, byte *pbuf, int size );
|
||||
qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *length );
|
||||
qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg );
|
||||
|
||||
@@ -73,7 +73,7 @@ GNU General Public License for more details.
|
||||
#define svc_director 51 // <variable sized>
|
||||
#define svc_voiceinit 52 // <see code>
|
||||
#define svc_voicedata 53 // [byte][short][...]
|
||||
#define svc_deltapacketbones 54 // [short][byte][...]
|
||||
// reserved
|
||||
// reserved
|
||||
#define svc_resourcelocation 56 // [string]
|
||||
#define svc_querycvarvalue 57 // [string]
|
||||
@@ -320,8 +320,7 @@ extern const char *clc_strings[clc_lastmsg+1];
|
||||
#define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0" // TODO: implement IP filter
|
||||
|
||||
// GoldSrc protocol definitions
|
||||
#define PROTOCOL_GOLDSRC_VERSION_REAL 48
|
||||
#define PROTOCOL_GOLDSRC_VERSION (PROTOCOL_GOLDSRC_VERSION_REAL | (BIT( 7 ))) // should be 48, only to differentiate it from PROTOCOL_LEGACY_VERSION
|
||||
#define PROTOCOL_GOLDSRC_VERSION 48
|
||||
|
||||
#define svc_goldsrc_version svc_changing
|
||||
#define svc_goldsrc_serverinfo svc_serverdata
|
||||
@@ -349,6 +348,7 @@ extern const char *clc_strings[clc_lastmsg+1];
|
||||
#define S2C_CHALLENGE "A00000000"
|
||||
#define S2C_CONNECTION "B"
|
||||
|
||||
#define MAX_GOLDSRC_MODEL_BITS 10
|
||||
#define MAX_GOLDSRC_RESOURCE_BITS 12
|
||||
#define MAX_GOLDSRC_ENTITY_BITS 11
|
||||
// #define MAX_GOLDSRC_EDICTS BIT( MAX_ENTITY_BITS )
|
||||
|
||||
@@ -30,7 +30,7 @@ static void Sound_Reset( void )
|
||||
sound.size = 0;
|
||||
}
|
||||
|
||||
static wavdata_t *SoundPack( void )
|
||||
static MALLOC_LIKE( FS_FreeSound, 1 ) wavdata_t *SoundPack( void )
|
||||
{
|
||||
wavdata_t *pack = Mem_Calloc( host.soundpool, sizeof( wavdata_t ));
|
||||
|
||||
|
||||
@@ -230,13 +230,20 @@ static void Sys_PrintLogfile( const int fd, const char *logtime, const char *msg
|
||||
|
||||
if( p == NULL )
|
||||
{
|
||||
write( fd, msg, Q_strlen( msg ));
|
||||
if( write( fd, msg, Q_strlen( msg )) < 0 )
|
||||
{
|
||||
// don't call engine Msg, might cause recursion
|
||||
fprintf( stderr, "%s: write failed: %s\n", __func__, strerror( errno ));
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if( IsColorString( p ))
|
||||
{
|
||||
if( p != msg )
|
||||
write( fd, msg, p - msg );
|
||||
{
|
||||
if( write( fd, msg, p - msg ) < 0 )
|
||||
fprintf( stderr, "%s: write failed: %s\n", __func__, strerror( errno ));
|
||||
}
|
||||
msg = p + 2;
|
||||
|
||||
if( colorize )
|
||||
@@ -244,7 +251,8 @@ static void Sys_PrintLogfile( const int fd, const char *logtime, const char *msg
|
||||
}
|
||||
else
|
||||
{
|
||||
write( fd, msg, p - msg + 1 );
|
||||
if( write( fd, msg, p - msg + 1 ) < 0 )
|
||||
fprintf( stderr, "%s: write failed: %s\n", __func__, strerror( errno ));
|
||||
msg = p + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,8 @@ void Test_RunBuffer( void );
|
||||
Test_RunCvar(); \
|
||||
Test_RunIPFilter(); \
|
||||
Test_RunBuffer(); \
|
||||
Test_RunDelta();
|
||||
Test_RunDelta(); \
|
||||
Test_RunMunge();
|
||||
|
||||
#define TEST_LIST_0_CLIENT \
|
||||
Test_RunCon(); \
|
||||
|
||||
@@ -125,7 +125,7 @@ typedef struct enginefuncs_s
|
||||
void (*pfnAngleVectors)( const float *rgflVector, float *forward, float *right, float *up );
|
||||
edict_t* (*pfnCreateEntity)( void );
|
||||
void (*pfnRemoveEntity)( edict_t* e );
|
||||
edict_t* (*pfnCreateNamedEntity)( string_t className );
|
||||
edict_t* (*pfnCreateNamedEntity)( int className );
|
||||
void (*pfnMakeStatic)( edict_t *ent );
|
||||
int (*pfnEntIsOnFloor)( edict_t *e );
|
||||
int (*pfnDropToFloor)( edict_t* e );
|
||||
@@ -168,8 +168,8 @@ typedef struct enginefuncs_s
|
||||
void* (*pfnPvAllocEntPrivateData)( edict_t *pEdict, long cb );
|
||||
void* (*pfnPvEntPrivateData)( edict_t *pEdict );
|
||||
void (*pfnFreeEntPrivateData)( edict_t *pEdict );
|
||||
const char *(*pfnSzFromIndex)( string_t iString );
|
||||
string_t (*pfnAllocString)( const char *szValue );
|
||||
const char *(*pfnSzFromIndex)( int iString );
|
||||
int (*pfnAllocString)( const char *szValue );
|
||||
struct entvars_s *(*pfnGetVarsOfEnt)( edict_t *pEdict );
|
||||
edict_t* (*pfnPEntityOfEntOffset)( int iEntOffset );
|
||||
int (*pfnEntOffsetOfPEntity)( const edict_t *pEdict );
|
||||
|
||||
@@ -18,8 +18,10 @@ GNU General Public License for more details.
|
||||
#define NET_PSVITA_H
|
||||
|
||||
#include <vitasdk.h>
|
||||
#include "platform/posix/net.h"
|
||||
|
||||
/* we're missing IPv6 support; define some trash */
|
||||
#define XASH_NO_IPV6_RESOLVE 1
|
||||
|
||||
#ifndef IN6_IS_ADDR_V4MAPPED
|
||||
#define IN6_IS_ADDR_V4MAPPED( p ) ( 0 )
|
||||
|
||||
@@ -85,8 +85,8 @@ typedef struct entvars_s
|
||||
int modelindex;
|
||||
|
||||
string_t model;
|
||||
string_t viewmodel; // player's viewmodel
|
||||
string_t weaponmodel; // what other players see
|
||||
int viewmodel; // player's viewmodel
|
||||
int weaponmodel; // what other players see
|
||||
|
||||
vec3_t absmin; // BB max translated to world coord
|
||||
vec3_t absmax; // BB max translated to world coord
|
||||
@@ -144,7 +144,7 @@ typedef struct entvars_s
|
||||
int flags;
|
||||
|
||||
int colormap; // lowbyte topcolor, highbyte bottomcolor
|
||||
string_t team;
|
||||
int team;
|
||||
|
||||
float max_health;
|
||||
float teleport_time;
|
||||
|
||||
@@ -389,10 +389,13 @@ typedef struct ref_api_s
|
||||
int (*pfnGetStudioModelInterface)( int version, struct r_studio_interface_s **ppinterface, struct engine_studio_api_s *pstudio );
|
||||
|
||||
// memory
|
||||
poolhandle_t (*_Mem_AllocPool)( const char *name, const char *filename, int fileline );
|
||||
poolhandle_t (*_Mem_AllocPool)( const char *name, const char *filename, int fileline )
|
||||
WARN_UNUSED_RESULT;
|
||||
void (*_Mem_FreePool)( poolhandle_t *poolptr, const char *filename, int fileline );
|
||||
void *(*_Mem_Alloc)( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline ) ALLOC_CHECK( 2 );
|
||||
void *(*_Mem_Realloc)( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline ) ALLOC_CHECK( 3 );
|
||||
void *(*_Mem_Alloc)( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
ALLOC_CHECK( 2 ) WARN_UNUSED_RESULT;
|
||||
void *(*_Mem_Realloc)( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
ALLOC_CHECK( 3 ) WARN_UNUSED_RESULT;
|
||||
void (*_Mem_Free)( void *data, const char *filename, int fileline );
|
||||
|
||||
// library management
|
||||
|
||||
@@ -444,7 +444,7 @@ static void SV_ConnectClient( netadr_t from )
|
||||
newcl->listeners = -1;
|
||||
|
||||
// initailize netchan
|
||||
Netchan_Setup( NS_SERVER, &newcl->netchan, from, qport, newcl, SV_GetFragmentSize );
|
||||
Netchan_Setup( NS_SERVER, &newcl->netchan, from, qport, newcl, SV_GetFragmentSize, 0 );
|
||||
MSG_Init( &newcl->datagram, "Datagram", newcl->datagram_buf, sizeof( newcl->datagram_buf )); // datagram buf
|
||||
|
||||
Q_strncpy( newcl->hashedcdkey, Info_ValueForKey( protinfo, "uuid" ), 32 );
|
||||
|
||||
@@ -643,12 +643,16 @@ Write ambient sounds into demo
|
||||
*/
|
||||
void SV_RestartAmbientSounds( void )
|
||||
{
|
||||
// TODO: we don't know sounds state on remote server
|
||||
// as it's used only for demos, maybe this could be implemented on client side?
|
||||
#if !XASH_DEDICATED
|
||||
soundlist_t soundInfo[256];
|
||||
string curtrack, looptrack;
|
||||
int i, nSounds;
|
||||
int position;
|
||||
|
||||
if( !SV_Active( )) return;
|
||||
if( !SV_Active( ) || Host_IsDedicated( ))
|
||||
return;
|
||||
|
||||
nSounds = S_GetCurrentStaticSounds( soundInfo, 256 );
|
||||
|
||||
@@ -663,13 +667,12 @@ void SV_RestartAmbientSounds( void )
|
||||
SV_StartSound( SV_PEntityOfEntIndex( si->entnum, true ), CHAN_STATIC, si->name, si->volume, si->attenuation, 0, si->pitch );
|
||||
}
|
||||
|
||||
#if !XASH_DEDICATED // TODO: ???
|
||||
// restart soundtrack
|
||||
if( S_StreamGetCurrentState( curtrack, sizeof( curtrack ), looptrack, sizeof( looptrack ), &position ))
|
||||
{
|
||||
SV_StartMusic( curtrack, looptrack, position );
|
||||
}
|
||||
#endif
|
||||
#endif // !XASH_DEDICATED
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -681,31 +684,25 @@ Write all the decals into demo
|
||||
*/
|
||||
void SV_RestartDecals( void )
|
||||
{
|
||||
// TODO: similar to SV_RestartAmbientSounds, this is only used for demo recording
|
||||
// and better be reimplemented on client side
|
||||
#if !XASH_DEDICATED
|
||||
decallist_t *list;
|
||||
int decalIndex;
|
||||
int modelIndex;
|
||||
sizebuf_t *msg;
|
||||
int i, numdecals;
|
||||
|
||||
if( !SV_Active( )) return;
|
||||
if( !SV_Active( ) || Host_IsDedicated( ))
|
||||
return;
|
||||
|
||||
// g-cont. add space for studiodecals if present
|
||||
list = (decallist_t *)Z_Calloc( sizeof( decallist_t ) * MAX_RENDER_DECALS * 2 );
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
if( !Host_IsDedicated() )
|
||||
{
|
||||
numdecals = ref.dllFuncs.R_CreateDecalList( list );
|
||||
numdecals = ref.dllFuncs.R_CreateDecalList( list );
|
||||
|
||||
// remove decals from map
|
||||
ref.dllFuncs.R_ClearAllDecals();
|
||||
}
|
||||
else
|
||||
#endif // XASH_DEDICATED
|
||||
{
|
||||
// we probably running a dedicated server
|
||||
numdecals = 0;
|
||||
}
|
||||
// remove decals from map
|
||||
ref.dllFuncs.R_ClearAllDecals();
|
||||
|
||||
// write decals into reliable datagram
|
||||
msg = SV_GetReliableDatagram();
|
||||
@@ -728,6 +725,7 @@ void SV_RestartDecals( void )
|
||||
}
|
||||
|
||||
Z_Free( list );
|
||||
#endif // !XASH_DEDICATED
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3000,6 +2998,25 @@ static void *GAME_EXPORT pfnPvEntPrivateData( edict_t *pEdict )
|
||||
}
|
||||
|
||||
|
||||
#ifdef XASH_64BIT
|
||||
static struct str64_s
|
||||
{
|
||||
size_t maxstringarray;
|
||||
qboolean allowdup;
|
||||
char *staticstringarray;
|
||||
char *pstringarray;
|
||||
char *pstringarraystatic;
|
||||
char *pstringbase;
|
||||
char *poldstringbase;
|
||||
char *plast;
|
||||
qboolean dynamic;
|
||||
size_t maxalloc;
|
||||
size_t numdups;
|
||||
size_t numoverflows;
|
||||
size_t totalalloc;
|
||||
} str64;
|
||||
#endif
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_EmptyStringPool
|
||||
@@ -3009,7 +3026,17 @@ Free strings on server stop. Reset string pointer on 64 bits
|
||||
*/
|
||||
void SV_EmptyStringPool( void )
|
||||
{
|
||||
#ifdef XASH_64BIT
|
||||
if( str64.dynamic ) // switch only after array fill (more space for multiplayer games)
|
||||
str64.pstringbase = str64.pstringarray;
|
||||
else
|
||||
{
|
||||
str64.pstringbase = str64.poldstringbase = str64.pstringarraystatic;
|
||||
str64.plast = str64.pstringbase + 1;
|
||||
}
|
||||
#else
|
||||
Mem_EmptyPool( svgame.stringspool );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3023,8 +3050,23 @@ this helps not to lose strings that belongs to static game part
|
||||
*/
|
||||
void SV_SetStringArrayMode( qboolean dynamic )
|
||||
{
|
||||
#ifdef XASH_64BIT
|
||||
Con_Reportf( "%s(%d) %d\n", __func__, dynamic, str64.dynamic );
|
||||
|
||||
if( dynamic == str64.dynamic )
|
||||
return;
|
||||
|
||||
str64.dynamic = dynamic;
|
||||
|
||||
SV_EmptyStringPool();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if XASH_AMD64 && XASH_LINUX && !XASH_ANDROID
|
||||
#define USE_MMAP
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_AllocStringPool
|
||||
@@ -3037,13 +3079,104 @@ this case need patched game dll with MAKE_STRING checking ptrdiff size
|
||||
*/
|
||||
static void SV_AllocStringPool( void )
|
||||
{
|
||||
#ifdef XASH_64BIT
|
||||
void *ptr = NULL;
|
||||
string lenstr;
|
||||
|
||||
Con_Reportf( "%s()\n", __func__ );
|
||||
if( Sys_GetParmFromCmdLine( "-str64alloc", lenstr ) )
|
||||
{
|
||||
str64.maxstringarray = Q_atoi( lenstr );
|
||||
if( str64.maxstringarray < 1024 || str64.maxstringarray >= INT_MAX )
|
||||
str64.maxstringarray = 65536;
|
||||
}
|
||||
else str64.maxstringarray = 65536;
|
||||
if( Sys_CheckParm( "-str64dup" ) )
|
||||
str64.allowdup = true;
|
||||
|
||||
#ifdef USE_MMAP
|
||||
{
|
||||
uint flags;
|
||||
size_t pagesize = sysconf( _SC_PAGESIZE );
|
||||
int arrlen = (str64.maxstringarray * 2) & ~(pagesize - 1);
|
||||
void *base = svgame.dllFuncs.pfnGameInit;
|
||||
void *start = svgame.hInstance - arrlen;
|
||||
|
||||
#if defined(MAP_ANON)
|
||||
flags = MAP_ANON | MAP_PRIVATE;
|
||||
#elif defined(MAP_ANONYMOUS)
|
||||
flags = MAP_ANONYMOUS | MAP_PRIVATE;
|
||||
#endif
|
||||
|
||||
while( start - base > INT_MIN )
|
||||
{
|
||||
void *mapptr = mmap((void*)((unsigned long)start & ~(pagesize - 1)), arrlen, PROT_READ | PROT_WRITE, flags, 0, 0 );
|
||||
if( mapptr && mapptr != (void*)-1 && mapptr - base > INT_MIN && mapptr - base < INT_MAX )
|
||||
{
|
||||
ptr = mapptr;
|
||||
break;
|
||||
}
|
||||
if( mapptr ) munmap( mapptr, arrlen );
|
||||
start -= arrlen;
|
||||
}
|
||||
|
||||
if( !ptr )
|
||||
{
|
||||
start = base;
|
||||
while( start - base < INT_MAX )
|
||||
{
|
||||
void *mapptr = mmap((void*)((unsigned long)start & ~(pagesize - 1)), arrlen, PROT_READ | PROT_WRITE, flags, 0, 0 );
|
||||
if( mapptr && mapptr != (void*)-1 && mapptr - base > INT_MIN && mapptr - base < INT_MAX )
|
||||
{
|
||||
ptr = mapptr;
|
||||
break;
|
||||
}
|
||||
if( mapptr ) munmap( mapptr, arrlen );
|
||||
start += arrlen;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( ptr )
|
||||
{
|
||||
Con_Reportf( "%s: Allocated string array near the server library: %p %p\n", __func__, base, ptr );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Reportf( "%s: Failed to allocate string array near the server library!\n", __func__ );
|
||||
ptr = str64.staticstringarray = Mem_Calloc( host.mempool, str64.maxstringarray * 2 );
|
||||
}
|
||||
}
|
||||
#else
|
||||
ptr = str64.staticstringarray = Mem_Calloc( host.mempool, str64.maxstringarray * 2 );
|
||||
#endif
|
||||
|
||||
str64.pstringarray = ptr;
|
||||
str64.pstringarraystatic = (byte*)ptr + str64.maxstringarray;
|
||||
str64.pstringbase = str64.poldstringbase = ptr;
|
||||
str64.plast = (byte*)ptr + 1;
|
||||
svgame.globals->pStringBase = ptr;
|
||||
#else
|
||||
svgame.stringspool = Mem_AllocPool( "Server Strings" );
|
||||
svgame.globals->pStringBase = "";
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SV_FreeStringPool( void )
|
||||
{
|
||||
#ifdef XASH_64BIT
|
||||
Con_Reportf( "%s()\n", __func__ );
|
||||
|
||||
#ifdef USE_MMAP
|
||||
if( str64.pstringarray != str64.staticstringarray )
|
||||
munmap( str64.pstringarray, (str64.maxstringarray * 2) & ~(sysconf( _SC_PAGESIZE ) - 1) );
|
||||
else
|
||||
#endif
|
||||
Mem_Free( str64.staticstringarray );
|
||||
#else
|
||||
Mem_FreePool( &svgame.stringspool );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3114,6 +3247,9 @@ string_t GAME_EXPORT SV_AllocString( const char *szValue )
|
||||
{
|
||||
char *newString = NULL;
|
||||
uint len;
|
||||
#ifdef XASH_64BIT
|
||||
int cmp;
|
||||
#endif
|
||||
|
||||
if( svgame.physFuncs.pfnAllocString != NULL )
|
||||
{
|
||||
@@ -3129,16 +3265,67 @@ string_t GAME_EXPORT SV_AllocString( const char *szValue )
|
||||
return i;
|
||||
}
|
||||
|
||||
#ifdef XASH_64BIT
|
||||
cmp = 1;
|
||||
|
||||
if( !str64.allowdup )
|
||||
{
|
||||
for( newString = str64.poldstringbase + 1;
|
||||
newString < str64.plast && ( cmp = Q_strcmp( newString, szValue ) );
|
||||
newString += Q_strlen( newString ) + 1 );
|
||||
}
|
||||
|
||||
if( cmp )
|
||||
{
|
||||
uint len = SV_ProcessString( NULL, szValue );
|
||||
|
||||
if( str64.plast - str64.poldstringbase + len + 1 > str64.maxstringarray )
|
||||
{
|
||||
str64.plast = str64.pstringbase + 1;
|
||||
str64.poldstringbase = str64.pstringbase;
|
||||
str64.numoverflows++;
|
||||
}
|
||||
|
||||
//MsgDev( D_NOTE, "SV_AllocString: %ld %s\n", str64.plast - svgame.globals->pStringBase, szValue );
|
||||
SV_ProcessString( str64.plast, szValue );
|
||||
str64.totalalloc += len;
|
||||
|
||||
newString = str64.plast;
|
||||
str64.plast += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
str64.numdups++;
|
||||
//MsgDev( D_NOTE, "SV_AllocString: dup %ld %s\n", newString - svgame.globals->pStringBase, szValue );
|
||||
}
|
||||
|
||||
if( newString - str64.pstringarray > str64.maxalloc )
|
||||
str64.maxalloc = newString - str64.pstringarray;
|
||||
|
||||
return newString - svgame.globals->pStringBase;
|
||||
#else
|
||||
len = SV_ProcessString( NULL, szValue );
|
||||
newString = Mem_Malloc( svgame.stringspool, len );
|
||||
SV_ProcessString( newString, szValue );
|
||||
|
||||
return newString - svgame.globals->pStringBase;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SV_PrintStr64Stats_f( void )
|
||||
{
|
||||
#ifdef XASH_64BIT
|
||||
Con_Printf( "====================\n" );
|
||||
Con_Printf( "64 bit string pool statistics\n" );
|
||||
Con_Printf( "====================\n" );
|
||||
Con_Printf( "string array size: %lu\n", str64.maxstringarray );
|
||||
Con_Printf( "total alloc %lu\n", str64.totalalloc );
|
||||
Con_Printf( "maximum array usage: %lu\n", str64.maxalloc );
|
||||
Con_Printf( "overflow counter: %lu\n", str64.numoverflows );
|
||||
Con_Printf( "dup string counter: %lu\n", str64.numdups );
|
||||
#else
|
||||
Con_Printf( "Not implemented\n" );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3152,8 +3339,17 @@ string_t SV_MakeString( const char *szValue )
|
||||
{
|
||||
if( svgame.physFuncs.pfnMakeString != NULL )
|
||||
return svgame.physFuncs.pfnMakeString( szValue );
|
||||
|
||||
#ifdef XASH_64BIT
|
||||
{
|
||||
long long ptrdiff = szValue - svgame.globals->pStringBase;
|
||||
if( ptrdiff > INT_MAX || ptrdiff < INT_MIN )
|
||||
return SV_AllocString(szValue);
|
||||
else
|
||||
return (int)ptrdiff;
|
||||
}
|
||||
#else
|
||||
return szValue - svgame.globals->pStringBase;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4917,6 +5113,8 @@ void SV_SpawnEntities( const char *mapname )
|
||||
|
||||
void SV_UnloadProgs( void )
|
||||
{
|
||||
pending_cvar_t *pending_cvars_list;
|
||||
|
||||
if( !svgame.hInstance )
|
||||
return;
|
||||
|
||||
@@ -4926,6 +5124,8 @@ void SV_UnloadProgs( void )
|
||||
/// SV_UnloadProgs will be disabled
|
||||
//Mod_ClearUserData ();
|
||||
|
||||
pending_cvars_list = Cvar_PrepareToUnlink( FCVAR_EXTDLL );
|
||||
|
||||
if( svgame.dllFuncs2.pfnGameShutdown != NULL )
|
||||
svgame.dllFuncs2.pfnGameShutdown ();
|
||||
|
||||
@@ -4943,7 +5143,7 @@ void SV_UnloadProgs( void )
|
||||
|
||||
// must unlink all game cvars,
|
||||
// before pointers on them will be lost...
|
||||
Cvar_Unlink( FCVAR_EXTDLL );
|
||||
Cvar_UnlinkPendingCvars( pending_cvars_list );
|
||||
Cmd_Unlink( CMD_SERVERDLL );
|
||||
|
||||
SV_FreeStringPool();
|
||||
|
||||
@@ -363,6 +363,7 @@ loads external resource list
|
||||
static void SV_CreateGenericResources( void )
|
||||
{
|
||||
string filename;
|
||||
int i;
|
||||
|
||||
Q_strncpy( filename, sv.model_precache[1], sizeof( filename ));
|
||||
COM_ReplaceExtension( filename, ".res", sizeof( filename ));
|
||||
@@ -370,6 +371,16 @@ static void SV_CreateGenericResources( void )
|
||||
|
||||
SV_ReadResourceList( filename );
|
||||
SV_ReadResourceList( "reslist.txt" );
|
||||
|
||||
for( i = 0; i < world.wadlist.count; i++ )
|
||||
{
|
||||
if( world.wadlist.wadusage[i] > 0 )
|
||||
{
|
||||
string wadname;
|
||||
Q_snprintf( wadname, sizeof( wadname ), "%s.wad", world.wadlist.wadnames[i] );
|
||||
SV_GenericIndex( wadname );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -92,9 +92,9 @@ static CVAR_DEFINE_AUTO( sv_waterfriction, "1", FCVAR_SERVER|FCVAR_MOVEVARS, "ho
|
||||
static CVAR_DEFINE_AUTO( sv_bounce, "1", FCVAR_SERVER|FCVAR_MOVEVARS, "bounce factor for entities with MOVETYPE_BOUNCE" );
|
||||
static CVAR_DEFINE_AUTO( sv_stepsize, "18", FCVAR_SERVER|FCVAR_MOVEVARS, "how high you and NPS's can step up" );
|
||||
CVAR_DEFINE_AUTO( sv_maxvelocity, "2000", FCVAR_MOVEVARS|FCVAR_UNLOGGED, "max velocity for all things in the world" );
|
||||
static CVAR_DEFINE_AUTO( sv_zmax, "4096", FCVAR_SERVER|FCVAR_MOVEVARS|FCVAR_SPONLY, "maximum viewable distance" );
|
||||
static CVAR_DEFINE_AUTO( sv_zmax, "4096", FCVAR_MOVEVARS|FCVAR_SPONLY, "maximum viewable distance" );
|
||||
CVAR_DEFINE_AUTO( sv_wateramp, "0", FCVAR_MOVEVARS|FCVAR_UNLOGGED, "world waveheight factor" );
|
||||
static CVAR_DEFINE( sv_footsteps, "mp_footsteps", "1", FCVAR_SERVER|FCVAR_MOVEVARS, "world gravity value" );
|
||||
static CVAR_DEFINE( sv_footsteps, "mp_footsteps", "1", FCVAR_SERVER|FCVAR_MOVEVARS, "play foot steps for players" );
|
||||
CVAR_DEFINE_AUTO( sv_skyname, "desert", FCVAR_MOVEVARS|FCVAR_UNLOGGED, "skybox name (can be dynamically changed in-game)" );
|
||||
static CVAR_DEFINE_AUTO( sv_rollangle, "0", FCVAR_MOVEVARS|FCVAR_UNLOGGED|FCVAR_ARCHIVE, "how much to tilt the view when strafing" );
|
||||
static CVAR_DEFINE_AUTO( sv_rollspeed, "200", FCVAR_MOVEVARS|FCVAR_UNLOGGED, "how much strafing is necessary to tilt the view" );
|
||||
@@ -189,6 +189,9 @@ void SV_UpdateMovevars( qboolean initialize )
|
||||
if( !initialize && !host.movevars_changed )
|
||||
return;
|
||||
|
||||
// NOTE: this breaks Natural Selection mod on ns_machina map that uses model as sky
|
||||
// it sets the value to 4000000 that even exceeds the coord limit
|
||||
#if 0
|
||||
// check range
|
||||
if( sv_zmax.value < 256.0f ) Cvar_SetValue( "sv_zmax", 256.0f );
|
||||
|
||||
@@ -203,6 +206,7 @@ void SV_UpdateMovevars( qboolean initialize )
|
||||
if( sv_zmax.value > 32767.0f )
|
||||
Cvar_SetValue( "sv_zmax", 32767.0f );
|
||||
}
|
||||
#endif
|
||||
|
||||
svgame.movevars.gravity = sv_gravity.value;
|
||||
svgame.movevars.stopspeed = sv_stopspeed.value;
|
||||
|
||||
@@ -1170,41 +1170,36 @@ static void SaveClientState( SAVERESTOREDATA *pSaveData, const char *level, int
|
||||
char name[MAX_QPATH];
|
||||
int i, id, version;
|
||||
char *pTokenData;
|
||||
decallist_t *decalList;
|
||||
SAVE_CLIENT header;
|
||||
decallist_t *decalList = NULL;
|
||||
SAVE_CLIENT header = { 0 };
|
||||
file_t *pFile;
|
||||
|
||||
// clearing the saving buffer to reuse
|
||||
SaveClear( pSaveData );
|
||||
|
||||
memset( &header, 0, sizeof( header ));
|
||||
|
||||
// g-cont. add space for studiodecals if present
|
||||
decalList = (decallist_t *)Z_Calloc( sizeof( decallist_t ) * MAX_RENDER_DECALS * 2 );
|
||||
header.entityCount = sv.num_static_entities;
|
||||
|
||||
// initialize client header
|
||||
#if !XASH_DEDICATED
|
||||
if( !Host_IsDedicated() )
|
||||
if( !Host_IsDedicated( ))
|
||||
{
|
||||
header.decalCount = ref.dllFuncs.R_CreateDecalList( decalList );
|
||||
}
|
||||
else
|
||||
#endif // XASH_DEDICATED
|
||||
{
|
||||
// we probably running a dedicated server
|
||||
header.decalCount = 0;
|
||||
}
|
||||
header.entityCount = sv.num_static_entities;
|
||||
// g-cont. add space for studiodecals if present
|
||||
decalList = (decallist_t *)Mem_Calloc( host.mempool, sizeof( decallist_t ) * MAX_RENDER_DECALS * 2 );
|
||||
|
||||
if( !changelevel )
|
||||
{
|
||||
// sounds won't going across transition
|
||||
header.soundCount = S_GetCurrentDynamicSounds( soundInfo, MAX_CHANNELS );
|
||||
#if !XASH_DEDICATED
|
||||
// music not reqiured to save position: it's just continue playing on a next level
|
||||
S_StreamGetCurrentState( header.introTrack, sizeof( header.introTrack ), header.mainTrack, sizeof( header.mainTrack ), &header.trackPosition );
|
||||
#endif
|
||||
header.decalCount = ref.dllFuncs.R_CreateDecalList( decalList );
|
||||
|
||||
if( !changelevel ) // sounds won't going across transition
|
||||
{
|
||||
header.soundCount = S_GetCurrentDynamicSounds( soundInfo, MAX_CHANNELS );
|
||||
|
||||
// music not reqiured to save position: it's just continue playing on a next level
|
||||
S_StreamGetCurrentState(
|
||||
header.introTrack, sizeof( header.introTrack ),
|
||||
header.mainTrack, sizeof( header.mainTrack ),
|
||||
&header.trackPosition );
|
||||
}
|
||||
}
|
||||
#endif // XASH_DEDICATED
|
||||
|
||||
// save viewentity to allow camera works after save\restore
|
||||
if( SV_IsValidEdict( cl->pViewEntity ) && cl->pViewEntity != cl->edict )
|
||||
@@ -1217,7 +1212,7 @@ static void SaveClientState( SAVERESTOREDATA *pSaveData, const char *level, int
|
||||
svgame.dllFuncs.pfnSaveWriteFields( pSaveData, "ClientHeader", &header, gSaveClient, ARRAYSIZE( gSaveClient ));
|
||||
|
||||
// store decals
|
||||
for( i = 0; i < header.decalCount; i++ )
|
||||
for( i = 0; decalList != NULL && i < header.decalCount; i++ )
|
||||
{
|
||||
// NOTE: apply landmark offset only for brush entities without origin brushes
|
||||
if( pSaveData->fUseLandmark && FBitSet( decalList[i].flags, FDECAL_USE_LANDMARK ))
|
||||
@@ -1225,7 +1220,9 @@ static void SaveClientState( SAVERESTOREDATA *pSaveData, const char *level, int
|
||||
|
||||
svgame.dllFuncs.pfnSaveWriteFields( pSaveData, "DECALLIST", &decalList[i], gDecalEntry, ARRAYSIZE( gDecalEntry ));
|
||||
}
|
||||
Z_Free( decalList );
|
||||
|
||||
if( decalList )
|
||||
Mem_Free( decalList );
|
||||
|
||||
// write client entities
|
||||
for( i = 0; i < header.entityCount; i++ )
|
||||
|
||||
@@ -222,7 +222,7 @@ def build(bld):
|
||||
'client/*.c',
|
||||
'client/vgui/*.c',
|
||||
'client/avi/*.c'])
|
||||
libs += ['opus']
|
||||
libs += ['opus', 'bzip2']
|
||||
|
||||
includes = ['server', 'client', 'client/vgui' ]
|
||||
|
||||
|
||||
@@ -125,6 +125,16 @@ static void FS_BackupFileName( file_t *file, const char *path, uint options ) {}
|
||||
static void FS_InitMemory( void );
|
||||
static void FS_Purge( file_t* file );
|
||||
|
||||
void _Mem_Free( void *data, const char *filename, int fileline )
|
||||
{
|
||||
g_engfuncs._Mem_Free( data, filename, fileline );
|
||||
}
|
||||
|
||||
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
{
|
||||
return g_engfuncs._Mem_Alloc( poolptr, size, clear, filename, fileline );
|
||||
}
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
@@ -1412,34 +1422,34 @@ static qboolean FS_FindLibrary( const char *dllname, qboolean directpath, fs_dll
|
||||
return true;
|
||||
}
|
||||
|
||||
static poolhandle_t _Mem_AllocPool( const char *name, const char *filename, int fileline )
|
||||
static poolhandle_t Mem_AllocPoolStub( const char *name, const char *filename, int fileline )
|
||||
{
|
||||
return (poolhandle_t)0xDEADC0DE;
|
||||
}
|
||||
|
||||
static void _Mem_FreePool( poolhandle_t *poolptr, const char *filename, int fileline )
|
||||
static void Mem_FreePoolStub( poolhandle_t *poolptr, const char *filename, int fileline )
|
||||
{
|
||||
// stub
|
||||
}
|
||||
|
||||
static void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
static void *Mem_AllocStub( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
{
|
||||
void *ptr = malloc( size );
|
||||
if( clear ) memset( ptr, 0, size );
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void *_Mem_Realloc( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
static void *Mem_ReallocStub( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
{
|
||||
return realloc( memptr, size );
|
||||
}
|
||||
|
||||
static void _Mem_Free( void *data, const char *filename, int fileline )
|
||||
static void Mem_FreeStub( void *data, const char *filename, int fileline )
|
||||
{
|
||||
free( data );
|
||||
}
|
||||
|
||||
static void _Con_Printf( const char *fmt, ... )
|
||||
static void Con_PrintfStub( const char *fmt, ... )
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
@@ -1448,7 +1458,7 @@ static void _Con_Printf( const char *fmt, ... )
|
||||
va_end( ap );
|
||||
}
|
||||
|
||||
static void _Sys_Error( const char *fmt, ... )
|
||||
static void Sys_ErrorStub( const char *fmt, ... )
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
@@ -1459,7 +1469,7 @@ static void _Sys_Error( const char *fmt, ... )
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
static void *Sys_GetNativeObject_stub( const char *object )
|
||||
static void *Sys_GetNativeObjectStub( const char *object )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -2524,7 +2534,7 @@ byte *FS_LoadFileMalloc( const char *path, fs_offset_t *filesizeptr, qboolean ga
|
||||
|
||||
byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly )
|
||||
{
|
||||
return FS_LoadFile_( path, filesizeptr, gamedironly, g_engfuncs._Mem_Alloc != _Mem_Alloc );
|
||||
return FS_LoadFile_( path, filesizeptr, gamedironly, true );
|
||||
}
|
||||
|
||||
qboolean CRC32_File( dword *crcvalue, const char *filename )
|
||||
@@ -2936,14 +2946,6 @@ search_t *FS_Search( const char *pattern, int caseinsensitive, int gamedironly )
|
||||
return search;
|
||||
}
|
||||
|
||||
static const char *FS_ArchivePath( file_t *f )
|
||||
{
|
||||
if( f->searchpath )
|
||||
return f->searchpath->filename;
|
||||
|
||||
return "plain";
|
||||
}
|
||||
|
||||
static qboolean FS_IsArchiveExtensionSupported( const char *ext, uint flags )
|
||||
{
|
||||
int i;
|
||||
@@ -2971,16 +2973,16 @@ void FS_InitMemory( void )
|
||||
|
||||
fs_interface_t g_engfuncs =
|
||||
{
|
||||
_Con_Printf,
|
||||
_Con_Printf,
|
||||
_Con_Printf,
|
||||
_Sys_Error,
|
||||
_Mem_AllocPool,
|
||||
_Mem_FreePool,
|
||||
_Mem_Alloc,
|
||||
_Mem_Realloc,
|
||||
_Mem_Free,
|
||||
Sys_GetNativeObject_stub
|
||||
Con_PrintfStub,
|
||||
Con_PrintfStub,
|
||||
Con_PrintfStub,
|
||||
Sys_ErrorStub,
|
||||
Mem_AllocPoolStub,
|
||||
Mem_FreePoolStub,
|
||||
Mem_AllocStub,
|
||||
Mem_ReallocStub,
|
||||
Mem_FreeStub,
|
||||
Sys_GetNativeObjectStub,
|
||||
};
|
||||
|
||||
static qboolean FS_InitInterface( int version, const fs_interface_t *engfuncs )
|
||||
|
||||
@@ -217,8 +217,10 @@ typedef struct fs_interface_t
|
||||
// memory
|
||||
poolhandle_t (*_Mem_AllocPool)( const char *name, const char *filename, int fileline );
|
||||
void (*_Mem_FreePool)( poolhandle_t *poolptr, const char *filename, int fileline );
|
||||
void *(*_Mem_Alloc)( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline ) ALLOC_CHECK( 2 );
|
||||
void *(*_Mem_Realloc)( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline ) ALLOC_CHECK( 3 );
|
||||
void *(*_Mem_Alloc)( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
ALLOC_CHECK( 2 ) WARN_UNUSED_RESULT;
|
||||
void *(*_Mem_Realloc)( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
ALLOC_CHECK( 3 ) WARN_UNUSED_RESULT;
|
||||
void (*_Mem_Free)( void *data, const char *filename, int fileline );
|
||||
|
||||
// platform
|
||||
|
||||
@@ -19,6 +19,7 @@ GNU General Public License for more details.
|
||||
#ifndef FILESYSTEM_INTERNAL_H
|
||||
#define FILESYSTEM_INTERNAL_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "xash3d_types.h"
|
||||
#include "filesystem.h"
|
||||
|
||||
@@ -129,10 +130,10 @@ extern const fs_archive_t g_archives[];
|
||||
|
||||
#define GI FI.GameInfo
|
||||
|
||||
#define Mem_Malloc( pool, size ) g_engfuncs._Mem_Alloc( pool, size, false, __FILE__, __LINE__ )
|
||||
#define Mem_Calloc( pool, size ) g_engfuncs._Mem_Alloc( pool, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Malloc( pool, size ) _Mem_Alloc( pool, size, false, __FILE__, __LINE__ )
|
||||
#define Mem_Calloc( pool, size ) _Mem_Alloc( pool, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Realloc( pool, ptr, size ) g_engfuncs._Mem_Realloc( pool, ptr, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Free( mem ) g_engfuncs._Mem_Free( mem, __FILE__, __LINE__ )
|
||||
#define Mem_Free( mem ) _Mem_Free( mem, __FILE__, __LINE__ )
|
||||
#define Mem_AllocPool( name ) g_engfuncs._Mem_AllocPool( name, __FILE__, __LINE__ )
|
||||
#define Mem_FreePool( pool ) g_engfuncs._Mem_FreePool( pool, __FILE__, __LINE__ )
|
||||
|
||||
@@ -148,6 +149,9 @@ extern const fs_archive_t g_archives[];
|
||||
qboolean FS_InitStdio( qboolean caseinsensitive, const char *rootdir, const char *basedir, const char *gamedir, const char *rodir );
|
||||
void FS_ShutdownStdio( void );
|
||||
searchpath_t *FS_AddArchive_Fullpath( const fs_archive_t *archive, const char *file, int flags );
|
||||
void _Mem_Free( void *data, const char *filename, int fileline );
|
||||
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
ALLOC_CHECK( 2 ) MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
|
||||
// search path utils
|
||||
void FS_Rescan( void );
|
||||
@@ -155,7 +159,8 @@ void FS_ClearSearchPath( void );
|
||||
void FS_AllowDirectPaths( qboolean enable );
|
||||
void FS_AddGameDirectory( const char *dir, uint flags );
|
||||
void FS_AddGameHierarchy( const char *dir, uint flags );
|
||||
search_t *FS_Search( const char *pattern, int caseinsensitive, int gamedironly );
|
||||
search_t *FS_Search( const char *pattern, int caseinsensitive, int gamedironly )
|
||||
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
int FS_SetCurrentDirectory( const char *path );
|
||||
void FS_Path_f( void );
|
||||
|
||||
@@ -163,14 +168,15 @@ void FS_Path_f( void );
|
||||
void FS_LoadGameInfo( const char *rootfolder );
|
||||
|
||||
// file ops
|
||||
file_t *FS_Open( const char *filepath, const char *mode, qboolean gamedironly );
|
||||
int FS_Close( file_t *file );
|
||||
file_t *FS_Open( const char *filepath, const char *mode, qboolean gamedironly )
|
||||
MALLOC_LIKE( FS_Close, 1 ) WARN_UNUSED_RESULT;
|
||||
fs_offset_t FS_Write( file_t *file, const void *data, size_t datasize );
|
||||
fs_offset_t FS_Read( file_t *file, void *buffer, size_t buffersize );
|
||||
int FS_Seek( file_t *file, fs_offset_t offset, int whence );
|
||||
fs_offset_t FS_Tell( file_t *file );
|
||||
qboolean FS_Eof( file_t *file );
|
||||
int FS_Flush( file_t *file );
|
||||
int FS_Close( file_t *file );
|
||||
int FS_Gets( file_t *file, char *string, size_t bufsize );
|
||||
int FS_UnGetc( file_t *file, char c );
|
||||
int FS_Getc( file_t *file );
|
||||
@@ -181,9 +187,12 @@ fs_offset_t FS_FileLength( file_t *f );
|
||||
qboolean FS_FileCopy( file_t *pOutput, file_t *pInput, int fileSize );
|
||||
|
||||
// file buffer ops
|
||||
byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly );
|
||||
byte *FS_LoadFileMalloc( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly );
|
||||
byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr );
|
||||
byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly )
|
||||
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
byte *FS_LoadFileMalloc( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly )
|
||||
MALLOC_LIKE( free, 1 ) WARN_UNUSED_RESULT;
|
||||
byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr )
|
||||
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
qboolean FS_WriteFile( const char *filename, const void *data, fs_offset_t len );
|
||||
|
||||
// file hashing
|
||||
|
||||
@@ -36,7 +36,9 @@ extern fs_globals_t *FI;
|
||||
#define FS_AllowDirectPaths (*g_fsapi.AllowDirectPaths)
|
||||
#define FS_AddGameDirectory (*g_fsapi.AddGameDirectory)
|
||||
#define FS_AddGameHierarchy (*g_fsapi.AddGameHierarchy)
|
||||
#ifndef FSCALLBACK_OVERRIDE_MALLOC_LIKE
|
||||
#define FS_Search (*g_fsapi.Search)
|
||||
#endif
|
||||
#define FS_SetCurrentDirectory (*g_fsapi.SetCurrentDirectory)
|
||||
#define FS_Path_f (*g_fsapi.Path_f)
|
||||
|
||||
@@ -44,14 +46,16 @@ extern fs_globals_t *FI;
|
||||
#define FS_LoadGameInfo (*g_fsapi.LoadGameInfo)
|
||||
|
||||
// file ops
|
||||
#ifndef FSCALLBACK_OVERRIDE_MALLOC_LIKE
|
||||
#define FS_Open (*g_fsapi.Open)
|
||||
#define FS_Close (*g_fsapi.Close)
|
||||
#endif
|
||||
#define FS_Write (*g_fsapi.Write)
|
||||
#define FS_Read (*g_fsapi.Read)
|
||||
#define FS_Seek (*g_fsapi.Seek)
|
||||
#define FS_Tell (*g_fsapi.Tell)
|
||||
#define FS_Eof (*g_fsapi.Eof)
|
||||
#define FS_Flush (*g_fsapi.Flush)
|
||||
#define FS_Close (*g_fsapi.Close)
|
||||
#define FS_Gets (*g_fsapi.Gets)
|
||||
#define FS_UnGetc (*g_fsapi.UnGetc)
|
||||
#define FS_Getc (*g_fsapi.Getc)
|
||||
@@ -62,8 +66,10 @@ extern fs_globals_t *FI;
|
||||
#define FS_FileCopy (*g_fsapi.FileCopy)
|
||||
|
||||
// file buffer ops
|
||||
#ifndef FSCALLBACK_OVERRIDE_MALLOC_LIKE
|
||||
#define FS_LoadFile (*g_fsapi.LoadFile)
|
||||
#define FS_LoadDirectFile (*g_fsapi.LoadDirectFile)
|
||||
#endif
|
||||
#define FS_WriteFile (*g_fsapi.WriteFile)
|
||||
|
||||
// file hashing
|
||||
|
||||
@@ -299,7 +299,6 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
|
||||
if( error )
|
||||
*error = ZIP_LOAD_BAD_HEADER;
|
||||
|
||||
Mem_Free( info );
|
||||
FS_CloseZIP( zip );
|
||||
return NULL;
|
||||
}
|
||||
@@ -316,7 +315,6 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
|
||||
if( error )
|
||||
*error = ZIP_LOAD_CORRUPTED;
|
||||
|
||||
Mem_Free( info );
|
||||
FS_CloseZIP( zip );
|
||||
return NULL;
|
||||
}
|
||||
@@ -364,7 +362,6 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
|
||||
if( error )
|
||||
*error = ZIP_LOAD_CORRUPTED;
|
||||
|
||||
Mem_Free( info );
|
||||
FS_CloseZIP( zip );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -288,7 +288,6 @@ const char* Q_timestamp( int format )
|
||||
static string timestamp;
|
||||
time_t crt_time;
|
||||
const struct tm *crt_tm;
|
||||
string timestring;
|
||||
|
||||
time( &crt_time );
|
||||
crt_tm = localtime( &crt_time );
|
||||
@@ -297,33 +296,31 @@ const char* Q_timestamp( int format )
|
||||
{
|
||||
case TIME_FULL:
|
||||
// Build the full timestamp (ex: "Apr03 2007 [23:31.55]");
|
||||
strftime( timestring, sizeof( timestring ), "%b%d %Y [%H:%M.%S]", crt_tm );
|
||||
strftime( timestamp, sizeof( timestamp ), "%b%d %Y [%H:%M.%S]", crt_tm );
|
||||
break;
|
||||
case TIME_DATE_ONLY:
|
||||
// Build the date stamp only (ex: "Apr03 2007");
|
||||
strftime( timestring, sizeof( timestring ), "%b%d %Y", crt_tm );
|
||||
strftime( timestamp, sizeof( timestamp ), "%b%d %Y", crt_tm );
|
||||
break;
|
||||
case TIME_TIME_ONLY:
|
||||
// Build the time stamp only (ex: "23:31.55");
|
||||
strftime( timestring, sizeof( timestring ), "%H:%M.%S", crt_tm );
|
||||
strftime( timestamp, sizeof( timestamp ), "%H:%M.%S", crt_tm );
|
||||
break;
|
||||
case TIME_NO_SECONDS:
|
||||
// Build the time stamp exclude seconds (ex: "13:46");
|
||||
strftime( timestring, sizeof( timestring ), "%H:%M", crt_tm );
|
||||
strftime( timestamp, sizeof( timestamp ), "%H:%M", crt_tm );
|
||||
break;
|
||||
case TIME_YEAR_ONLY:
|
||||
// Build the date stamp year only (ex: "2006");
|
||||
strftime( timestring, sizeof( timestring ), "%Y", crt_tm );
|
||||
strftime( timestamp, sizeof( timestamp ), "%Y", crt_tm );
|
||||
break;
|
||||
case TIME_FILENAME:
|
||||
// Build a timestamp that can use for filename (ex: "Nov2006-26 (19.14.28)");
|
||||
strftime( timestring, sizeof( timestring ), "%b%Y-%d_%H.%M.%S", crt_tm );
|
||||
strftime( timestamp, sizeof( timestamp ), "%b%Y-%d_%H.%M.%S", crt_tm );
|
||||
break;
|
||||
default: return NULL;
|
||||
}
|
||||
|
||||
Q_strncpy( timestamp, timestring, sizeof( timestamp ));
|
||||
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,13 +19,6 @@ GNU General Public License for more details.
|
||||
#include "com_model.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
|
||||
const matrix3x4 m_matrix3x4_identity =
|
||||
{
|
||||
{ 1, 0, 0, 0 }, // PITCH [forward], org[0]
|
||||
{ 0, 1, 0, 0 }, // YAW [right] , org[1]
|
||||
{ 0, 0, 1, 0 }, // ROLL [up] , org[2]
|
||||
};
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
@@ -225,14 +218,6 @@ void Matrix3x4_TransformAABB( const matrix3x4 world, const vec3_t mins, const ve
|
||||
VectorAdd( worldCenter, worldExtents, absmax );
|
||||
}
|
||||
|
||||
const matrix4x4 m_matrix4x4_identity =
|
||||
{
|
||||
{ 1, 0, 0, 0 }, // PITCH
|
||||
{ 0, 1, 0, 0 }, // YAW
|
||||
{ 0, 0, 1, 0 }, // ROLL
|
||||
{ 0, 0, 0, 1 }, // ORIGIN
|
||||
};
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "crtlib.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int Test_ExtractFilePath( void )
|
||||
static int Test_ExtractFilePath( void )
|
||||
{
|
||||
char dst[64];
|
||||
const char *strings[] =
|
||||
|
||||
@@ -18,15 +18,14 @@ GNU General Public License for more details.
|
||||
#include "com_model.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
#include "eiface.h"
|
||||
#include "studio.h"
|
||||
|
||||
#define NUM_HULL_ROUNDS ARRAYSIZE( hull_table )
|
||||
#define HULL_PRECISION 4
|
||||
|
||||
vec3_t vec3_origin = { 0, 0, 0 };
|
||||
static const word hull_table[] = { 2, 4, 6, 8, 12, 16, 18, 24, 28, 32, 36, 40, 48, 54, 56, 60, 64, 72, 80, 112, 120, 128, 140, 176 };
|
||||
|
||||
static word hull_table[] = { 2, 4, 6, 8, 12, 16, 18, 24, 28, 32, 36, 40, 48, 54, 56, 60, 64, 72, 80, 112, 120, 128, 140, 176 };
|
||||
|
||||
int boxpnt[6][4] =
|
||||
const int boxpnt[6][4] =
|
||||
{
|
||||
{ 0, 4, 6, 2 }, // +X
|
||||
{ 0, 1, 5, 4 }, // +Y
|
||||
@@ -42,18 +41,7 @@ const float m_bytenormals[NUMVERTEXNORMALS][3] =
|
||||
#include "anorms.h"
|
||||
};
|
||||
|
||||
/*
|
||||
=================
|
||||
anglemod
|
||||
=================
|
||||
*/
|
||||
float anglemod( float a )
|
||||
{
|
||||
a = (360.0f / 65536) * ((int)(a*(65536/360.0f)) & 65535);
|
||||
return a;
|
||||
}
|
||||
|
||||
word FloatToHalf( float v )
|
||||
uint16_t FloatToHalf( float v )
|
||||
{
|
||||
unsigned int i = FloatAsUint( v );
|
||||
unsigned int e = (i >> 23) & 0x00ff;
|
||||
@@ -69,7 +57,7 @@ word FloatToHalf( float v )
|
||||
return h;
|
||||
}
|
||||
|
||||
float HalfToFloat( word h )
|
||||
float HalfToFloat( uint16_t h )
|
||||
{
|
||||
unsigned int f = (h << 16) & 0x80000000;
|
||||
unsigned int em = h & 0x7fff;
|
||||
@@ -151,57 +139,6 @@ void RoundUpHullSize( vec3_t size )
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
SignbitsForPlane
|
||||
|
||||
fast box on planeside test
|
||||
=================
|
||||
*/
|
||||
int SignbitsForPlane( const vec3_t normal )
|
||||
{
|
||||
int bits, i;
|
||||
|
||||
for( bits = i = 0; i < 3; i++ )
|
||||
if( normal[i] < 0.0f ) bits |= 1<<i;
|
||||
return bits;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
PlaneTypeForNormal
|
||||
=================
|
||||
*/
|
||||
int PlaneTypeForNormal( const vec3_t normal )
|
||||
{
|
||||
if( normal[0] == 1.0f )
|
||||
return PLANE_X;
|
||||
if( normal[1] == 1.0f )
|
||||
return PLANE_Y;
|
||||
if( normal[2] == 1.0f )
|
||||
return PLANE_Z;
|
||||
return PLANE_NONAXIAL;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
NearestPOW
|
||||
=================
|
||||
*/
|
||||
int NearestPOW( int value, qboolean roundDown )
|
||||
{
|
||||
int n = 1;
|
||||
|
||||
if( value <= 0 ) return 1;
|
||||
while( n < value ) n <<= 1;
|
||||
|
||||
if( roundDown )
|
||||
{
|
||||
if( n > value ) n >>= 1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
rsqrt
|
||||
@@ -224,43 +161,6 @@ float rsqrt( float number )
|
||||
return y;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
VectorCompareEpsilon
|
||||
|
||||
==============
|
||||
*/
|
||||
qboolean VectorCompareEpsilon( const vec3_t vec1, const vec3_t vec2, vec_t epsilon )
|
||||
{
|
||||
vec_t ax, ay, az;
|
||||
|
||||
ax = fabs( vec1[0] - vec2[0] );
|
||||
ay = fabs( vec1[1] - vec2[1] );
|
||||
az = fabs( vec1[2] - vec2[2] );
|
||||
|
||||
if(( ax <= epsilon ) && ( ay <= epsilon ) && ( az <= epsilon ))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
float VectorNormalizeLength2( const vec3_t v, vec3_t out )
|
||||
{
|
||||
float length, ilength;
|
||||
|
||||
length = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
|
||||
length = sqrt( length );
|
||||
|
||||
if( length )
|
||||
{
|
||||
ilength = 1.0f / length;
|
||||
out[0] = v[0] * ilength;
|
||||
out[1] = v[1] * ilength;
|
||||
out[2] = v[2] * ilength;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
void VectorVectors( const vec3_t forward, vec3_t right, vec3_t up )
|
||||
{
|
||||
float d;
|
||||
@@ -276,42 +176,6 @@ void VectorVectors( const vec3_t forward, vec3_t right, vec3_t up )
|
||||
VectorNormalize( up );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
AngleVectors
|
||||
|
||||
=================
|
||||
*/
|
||||
void GAME_EXPORT AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up )
|
||||
{
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
|
||||
SinCos( DEG2RAD( angles[YAW] ), &sy, &cy );
|
||||
SinCos( DEG2RAD( angles[PITCH] ), &sp, &cp );
|
||||
SinCos( DEG2RAD( angles[ROLL] ), &sr, &cr );
|
||||
|
||||
if( forward )
|
||||
{
|
||||
forward[0] = cp * cy;
|
||||
forward[1] = cp * sy;
|
||||
forward[2] = -sp;
|
||||
}
|
||||
|
||||
if( right )
|
||||
{
|
||||
right[0] = (-1.0f * sr * sp * cy + -1.0f * cr * -sy );
|
||||
right[1] = (-1.0f * sr * sp * sy + -1.0f * cr * cy );
|
||||
right[2] = (-1.0f * sr * cp);
|
||||
}
|
||||
|
||||
if( up )
|
||||
{
|
||||
up[0] = (cr * sp * cy + -sr * -sy );
|
||||
up[1] = (cr * sp * sy + -sr * cy );
|
||||
up[2] = (cr * cp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
VectorAngles
|
||||
@@ -384,39 +248,6 @@ void VectorsAngles( const vec3_t forward, const vec3_t right, const vec3_t up, v
|
||||
//
|
||||
// bounds operations
|
||||
//
|
||||
/*
|
||||
=================
|
||||
AddPointToBounds
|
||||
=================
|
||||
*/
|
||||
void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs )
|
||||
{
|
||||
float val;
|
||||
int i;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
val = v[i];
|
||||
if( val < mins[i] ) mins[i] = val;
|
||||
if( val > maxs[i] ) maxs[i] = val;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
ExpandBounds (not used anywhere?)
|
||||
=================
|
||||
*/
|
||||
void ExpandBounds( vec3_t mins, vec3_t maxs, float offset )
|
||||
{
|
||||
mins[0] -= offset;
|
||||
mins[1] -= offset;
|
||||
mins[2] -= offset;
|
||||
maxs[0] += offset;
|
||||
maxs[1] += offset;
|
||||
maxs[2] += offset;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
SphereIntersect
|
||||
@@ -457,67 +288,9 @@ void PlaneIntersect( const mplane_t *plane, const vec3_t p0, const vec3_t p1, ve
|
||||
VectorMA( p0, sect, p1, out );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
RadiusFromBounds
|
||||
=================
|
||||
*/
|
||||
float RadiusFromBounds( const vec3_t mins, const vec3_t maxs )
|
||||
{
|
||||
vec3_t corner;
|
||||
int i;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
corner[i] = fabs( mins[i] ) > fabs( maxs[i] ) ? fabs( mins[i] ) : fabs( maxs[i] );
|
||||
}
|
||||
return VectorLength( corner );
|
||||
}
|
||||
|
||||
//
|
||||
// studio utils
|
||||
//
|
||||
/*
|
||||
====================
|
||||
AngleQuaternion
|
||||
|
||||
====================
|
||||
*/
|
||||
void AngleQuaternion( const vec3_t angles, vec4_t q, qboolean studio )
|
||||
{
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
|
||||
if( studio )
|
||||
{
|
||||
SinCos( angles[ROLL] * 0.5f, &sy, &cy );
|
||||
SinCos( angles[YAW] * 0.5f, &sp, &cp );
|
||||
SinCos( angles[PITCH] * 0.5f, &sr, &cr );
|
||||
}
|
||||
else
|
||||
{
|
||||
SinCos( DEG2RAD( angles[YAW] ) * 0.5f, &sy, &cy );
|
||||
SinCos( DEG2RAD( angles[PITCH] ) * 0.5f, &sp, &cp );
|
||||
SinCos( DEG2RAD( angles[ROLL] ) * 0.5f, &sr, &cr );
|
||||
}
|
||||
|
||||
q[0] = sr * cp * cy - cr * sp * sy; // X
|
||||
q[1] = cr * sp * cy + sr * cp * sy; // Y
|
||||
q[2] = cr * cp * sy - sr * sp * cy; // Z
|
||||
q[3] = cr * cp * cy + sr * sp * sy; // W
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
QuaternionAngle
|
||||
|
||||
====================
|
||||
*/
|
||||
void QuaternionAngle( const vec4_t q, vec3_t angles )
|
||||
{
|
||||
matrix3x4 mat;
|
||||
Matrix3x4_FromOriginQuat( mat, q, vec3_origin );
|
||||
Matrix3x4_AnglesFromMatrix( mat, angles );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
@@ -680,25 +453,6 @@ int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p )
|
||||
return sides;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
StudioSlerpBones
|
||||
|
||||
====================
|
||||
*/
|
||||
void R_StudioSlerpBones( int numbones, vec4_t q1[], float pos1[][3], const vec4_t q2[], const float pos2[][3], float s )
|
||||
{
|
||||
int i;
|
||||
|
||||
s = bound( 0.0f, s, 1.0f );
|
||||
|
||||
for( i = 0; i < numbones; i++ )
|
||||
{
|
||||
QuaternionSlerp( q1[i], q2[i], s, q1[i] );
|
||||
VectorLerp( pos1[i], s, pos2[i], pos1[i] );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
StudioCalcBoneQuaternion
|
||||
|
||||
@@ -23,74 +23,65 @@ GNU General Public License for more details.
|
||||
|
||||
#include "build.h"
|
||||
#include "xash3d_types.h"
|
||||
#include "const.h"
|
||||
#include "com_model.h"
|
||||
#include "studio.h"
|
||||
|
||||
/*
|
||||
===========================
|
||||
|
||||
CONSTANTS AND HELPER MACROS
|
||||
|
||||
===========================
|
||||
*/
|
||||
|
||||
// euler angle order
|
||||
#define PITCH 0
|
||||
#define YAW 1
|
||||
#define ROLL 2
|
||||
#define PITCH 0
|
||||
#define YAW 1
|
||||
#define ROLL 2
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI (double)3.14159265358979323846
|
||||
#define M_PI (double)3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#ifndef M_PI2
|
||||
#define M_PI2 ((double)(M_PI * 2))
|
||||
#endif
|
||||
#define M_PI2 ((double)(M_PI * 2))
|
||||
#define M_PI_F ((float)(M_PI))
|
||||
#define M_PI2_F ((float)(M_PI2))
|
||||
|
||||
#define M_PI_F ((float)(M_PI))
|
||||
#define M_PI2_F ((float)(M_PI2))
|
||||
#define RAD2DEG( x ) ((double)(x) * (double)(180.0 / M_PI))
|
||||
#define DEG2RAD( x ) ((double)(x) * (double)(M_PI / 180.0))
|
||||
|
||||
#define RAD2DEG( x ) ((double)(x) * (double)(180.0 / M_PI))
|
||||
#define DEG2RAD( x ) ((double)(x) * (double)(M_PI / 180.0))
|
||||
#define NUMVERTEXNORMALS 162
|
||||
|
||||
#define NUMVERTEXNORMALS 162
|
||||
#define BOGUS_RANGE ((vec_t)114032.64) // world.size * 1.74
|
||||
|
||||
#define BOGUS_RANGE ((vec_t)114032.64) // world.size * 1.74
|
||||
#define SIDE_FRONT 0
|
||||
#define SIDE_BACK 1
|
||||
#define SIDE_ON 2
|
||||
#define SIDE_CROSS -2
|
||||
|
||||
#define SIDE_FRONT 0
|
||||
#define SIDE_BACK 1
|
||||
#define SIDE_ON 2
|
||||
#define SIDE_CROSS -2
|
||||
#define PLANE_X 0 // 0 - 2 are axial planes
|
||||
#define PLANE_Y 1 // 3 needs alternate calc
|
||||
#define PLANE_Z 2
|
||||
#define PLANE_NONAXIAL 3
|
||||
|
||||
#define PLANE_X 0 // 0 - 2 are axial planes
|
||||
#define PLANE_Y 1 // 3 needs alternate calc
|
||||
#define PLANE_Z 2
|
||||
#define PLANE_NONAXIAL 3
|
||||
#define EQUAL_EPSILON 0.001f
|
||||
#define STOP_EPSILON 0.1f
|
||||
#define ON_EPSILON 0.1f
|
||||
|
||||
#define EQUAL_EPSILON 0.001f
|
||||
#define STOP_EPSILON 0.1f
|
||||
#define ON_EPSILON 0.1f
|
||||
#define RAD_TO_STUDIO (32768.0 / M_PI)
|
||||
#define STUDIO_TO_RAD (M_PI / 32768.0)
|
||||
|
||||
#define RAD_TO_STUDIO (32768.0 / M_PI)
|
||||
#define STUDIO_TO_RAD (M_PI / 32768.0)
|
||||
#define INV127F ( 1.0f / 127.0f )
|
||||
#define INV255F ( 1.0f / 255.0f )
|
||||
#define MAKE_SIGNED( x ) ((( x ) * INV127F ) - 1.0f )
|
||||
|
||||
#define INV127F ( 1.0f / 127.0f )
|
||||
#define INV255F ( 1.0f / 255.0f )
|
||||
#define MAKE_SIGNED( x ) ((( x ) * INV127F ) - 1.0f )
|
||||
|
||||
#define Q_min( a, b ) (((a) < (b)) ? (a) : (b))
|
||||
#define Q_max( a, b ) (((a) > (b)) ? (a) : (b))
|
||||
#define Q_min( a, b ) (((a) < (b)) ? (a) : (b))
|
||||
#define Q_max( a, b ) (((a) > (b)) ? (a) : (b))
|
||||
#define Q_equal_e( a, b, e ) (((a) >= ((b) - (e))) && ((a) <= ((b) + (e))))
|
||||
#define Q_equal( a, b ) Q_equal_e( a, b, EQUAL_EPSILON )
|
||||
#define Q_recip( a ) ((float)(1.0f / (float)(a)))
|
||||
#define Q_floor( a ) ((float)(int)(a))
|
||||
#define Q_ceil( a ) ((float)(int)((a) + 1))
|
||||
#define Q_round( x, y ) (floor( x / y + 0.5f ) * y )
|
||||
#define Q_rint(x) ((x) < 0.0f ? ((int)((x)-0.5f)) : ((int)((x)+0.5f)))
|
||||
|
||||
#ifdef XASH_IRIX
|
||||
#undef isnan
|
||||
#endif
|
||||
#ifdef isnan // check for C99 isnan
|
||||
#define IS_NAN isnan
|
||||
#else
|
||||
#define IS_NAN(x) (((*(int *)&x) & (255<<23)) == (255<<23))
|
||||
#endif
|
||||
|
||||
#define ALIGN( x, a ) ((( x ) + (( size_t )( a ) - 1 )) & ~(( size_t )( a ) - 1 ))
|
||||
#define Q_floor( a ) ((float)(int)(a))
|
||||
#define Q_ceil( a ) ((float)(int)((a) + 1))
|
||||
#define Q_round( x, y ) (floor( x / y + 0.5f ) * y )
|
||||
#define Q_rint(x) ((x) < 0.0f ? ((int)((x)-0.5f)) : ((int)((x)+0.5f)))
|
||||
#define ALIGN( x, a ) ((( x ) + (( size_t )( a ) - 1 )) & ~(( size_t )( a ) - 1 ))
|
||||
|
||||
#define VectorIsNAN(v) (IS_NAN(v[0]) || IS_NAN(v[1]) || IS_NAN(v[2]))
|
||||
#define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2])
|
||||
@@ -118,8 +109,11 @@ GNU General Public License for more details.
|
||||
#define Vector2Average(a,b,o) ((o)[0]=((a)[0]+(b)[0])*0.5f,(o)[1]=((a)[1]+(b)[1])*0.5f)
|
||||
#define VectorAverage(a,b,o) ((o)[0]=((a)[0]+(b)[0])*0.5f,(o)[1]=((a)[1]+(b)[1])*0.5f,(o)[2]=((a)[2]+(b)[2])*0.5f)
|
||||
#define Vector2Set(v, x, y) ((v)[0]=(x),(v)[1]=(y))
|
||||
#define Vector2Unpack(v, x, y) ((x)=(v)[0],(y)=(v)[1])
|
||||
#define VectorSet(v, x, y, z) ((v)[0]=(x),(v)[1]=(y),(v)[2]=(z))
|
||||
#define Vector4Set(v, a, b, c, d) ((v)[0]=(a),(v)[1]=(b),(v)[2]=(c),(v)[3] = (d))
|
||||
#define VectorUnpack(v, x, y, z) ((x)=(v)[0],(y)=(v)[1],(z)=(v)[2])
|
||||
#define Vector4Set(v, a, b, c, d) ((v)[0]=(a),(v)[1]=(b),(v)[2]=(c),(v)[3]=(d))
|
||||
#define Vector4Unpack(v, a, b, c, d) ((a)=(v)[0],(b)=(v)[1],(c)=(v)[2],(d)=(v)[3])
|
||||
#define VectorClear(x) ((x)[0]=(x)[1]=(x)[2]=0)
|
||||
#define Vector2Lerp( v1, lerp, v2, c ) ((c)[0] = (v1)[0] + (lerp) * ((v2)[0] - (v1)[0]), (c)[1] = (v1)[1] + (lerp) * ((v2)[1] - (v1)[1]))
|
||||
#define VectorLerp( v1, lerp, v2, c ) ((c)[0] = (v1)[0] + (lerp) * ((v2)[0] - (v1)[0]), (c)[1] = (v1)[1] + (lerp) * ((v2)[1] - (v1)[1]), (c)[2] = (v1)[2] + (lerp) * ((v2)[2] - (v1)[2]))
|
||||
@@ -138,9 +132,95 @@ GNU General Public License for more details.
|
||||
#define PlaneDiff(point,plane) (((plane)->type < 3 ? (point)[(plane)->type] : DotProduct((point), (plane)->normal)) - (plane)->dist)
|
||||
#define bound( min, num, max ) ((num) >= (min) ? ((num) < (max) ? (num) : (max)) : (min))
|
||||
|
||||
/*
|
||||
===========================
|
||||
|
||||
CONSTANTS GLOBALS
|
||||
|
||||
===========================
|
||||
*/
|
||||
// a1ba: we never return pointers to these globals
|
||||
// so help compiler optimize constants away
|
||||
#define vec3_origin ((vec3_t){ 0.0f, 0.0f, 0.0f })
|
||||
#define m_matrix3x4_identity ((matrix3x4) { \
|
||||
{ 1.0f, 0.0f, 0.0f, 0.0f }, \
|
||||
{ 0.0f, 1.0f, 0.0f, 0.0f }, \
|
||||
{ 0.0f, 0.0f, 1.0f, 0.0f }} )
|
||||
#define m_matrix4x4_identity ((matrix4x4) { \
|
||||
{ 1.0f, 0.0f, 0.0f, 0.0f }, \
|
||||
{ 0.0f, 1.0f, 0.0f, 0.0f }, \
|
||||
{ 0.0f, 0.0f, 1.0f, 0.0f }, \
|
||||
{ 0.0f, 0.0f, 0.0f, 1.0f }} )
|
||||
|
||||
extern const int boxpnt[6][4];
|
||||
extern const float m_bytenormals[NUMVERTEXNORMALS][3];
|
||||
|
||||
|
||||
/*
|
||||
===========================
|
||||
|
||||
MATH FUNCTIONS
|
||||
|
||||
===========================
|
||||
*/
|
||||
typedef struct mplane_s mplane_t;
|
||||
typedef struct mstudiobone_s mstudiobone_t;
|
||||
typedef struct mstudioanim_s mstudioanim_t;
|
||||
|
||||
float rsqrt( float number );
|
||||
uint16_t FloatToHalf( float v );
|
||||
float HalfToFloat( uint16_t h );
|
||||
void RoundUpHullSize( vec3_t size );
|
||||
void VectorVectors( const vec3_t forward, vec3_t right, vec3_t up );
|
||||
void VectorAngles( const float *forward, float *angles );
|
||||
void VectorsAngles( const vec3_t forward, const vec3_t right, const vec3_t up, vec3_t angles );
|
||||
void PlaneIntersect( const mplane_t *plane, const vec3_t p0, const vec3_t p1, vec3_t out );
|
||||
qboolean SphereIntersect( const vec3_t vSphereCenter, float fSphereRadiusSquared, const vec3_t vLinePt, const vec3_t vLineDir );
|
||||
void QuaternionSlerp( const vec4_t p, const vec4_t q, float t, vec4_t qt );
|
||||
void R_StudioCalcBoneQuaternion( int frame, float s, const mstudiobone_t *pbone, const mstudioanim_t *panim, const float *adj, vec4_t q );
|
||||
void R_StudioCalcBonePosition( int frame, float s, const mstudiobone_t *pbone, const mstudioanim_t *panim, const vec3_t adj, vec3_t pos );
|
||||
int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p );
|
||||
#define BOX_ON_PLANE_SIDE( emins, emaxs, p ) \
|
||||
((( p )->type < 3 ) ? \
|
||||
( \
|
||||
((p)->dist <= (emins)[(p)->type]) ? 1 : \
|
||||
( \
|
||||
((p)->dist >= (emaxs)[(p)->type] ) ? 2 : 3 \
|
||||
) \
|
||||
) : BoxOnPlaneSide(( emins ), ( emaxs ), ( p )))
|
||||
|
||||
//
|
||||
// matrixlib.c
|
||||
//
|
||||
#define Matrix3x4_LoadIdentity( mat ) Matrix3x4_Copy( mat, m_matrix3x4_identity )
|
||||
#define Matrix3x4_Copy( out, in ) memcpy( out, in, sizeof( matrix3x4 ))
|
||||
void Matrix3x4_VectorTransform( const matrix3x4 in, const float v[3], float out[3] );
|
||||
void Matrix3x4_VectorITransform( const matrix3x4 in, const float v[3], float out[3] );
|
||||
void Matrix3x4_VectorRotate( const matrix3x4 in, const float v[3], float out[3] );
|
||||
void Matrix3x4_VectorIRotate( const matrix3x4 in, const float v[3], float out[3] );
|
||||
void Matrix3x4_ConcatTransforms( matrix3x4 out, const matrix3x4 in1, const matrix3x4 in2 );
|
||||
void Matrix3x4_FromOriginQuat( matrix3x4 out, const vec4_t quaternion, const vec3_t origin );
|
||||
void Matrix3x4_CreateFromEntity( matrix3x4 out, const vec3_t angles, const vec3_t origin, float scale );
|
||||
void Matrix3x4_TransformAABB( const matrix3x4 world, const vec3_t mins, const vec3_t maxs, vec3_t absmin, vec3_t absmax );
|
||||
void Matrix3x4_AnglesFromMatrix( const matrix3x4 in, vec3_t out );
|
||||
|
||||
#define Matrix4x4_LoadIdentity( mat ) Matrix4x4_Copy( mat, m_matrix4x4_identity )
|
||||
#define Matrix4x4_Copy( out, in ) memcpy( out, in, sizeof( matrix4x4 ))
|
||||
void Matrix4x4_VectorTransform( const matrix4x4 in, const float v[3], float out[3] );
|
||||
void Matrix4x4_VectorITransform( const matrix4x4 in, const float v[3], float out[3] );
|
||||
void Matrix4x4_VectorRotate( const matrix4x4 in, const float v[3], float out[3] );
|
||||
void Matrix4x4_VectorIRotate( const matrix4x4 in, const float v[3], float out[3] );
|
||||
void Matrix4x4_ConcatTransforms( matrix4x4 out, const matrix4x4 in1, const matrix4x4 in2 );
|
||||
void Matrix4x4_CreateFromEntity( matrix4x4 out, const vec3_t angles, const vec3_t origin, float scale );
|
||||
void Matrix4x4_TransformPositivePlane( const matrix4x4 in, const vec3_t normal, float d, vec3_t out, float *dist );
|
||||
void Matrix4x4_ConvertToEntity( const matrix4x4 in, vec3_t angles, vec3_t origin );
|
||||
void Matrix4x4_Invert_Simple( matrix4x4 out, const matrix4x4 in1 );
|
||||
qboolean Matrix4x4_Invert_Full( matrix4x4 out, const matrix4x4 in1 );
|
||||
|
||||
// horrible cast but helps not breaking strict aliasing in mathlib
|
||||
// as union type punning should be fine in C but not in C++
|
||||
// so don't carry over this to C++ code
|
||||
#ifndef __cplusplus
|
||||
typedef union
|
||||
{
|
||||
float fl;
|
||||
@@ -173,28 +253,98 @@ static inline float UintAsFloat( uint32_t u )
|
||||
bits.u = u;
|
||||
return bits.fl;
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
// isnan implementation is broken on IRIX as reported in https://github.com/FWGS/xash3d-fwgs/pull/1211
|
||||
#if defined( XASH_IRIX ) || !defined( isnan )
|
||||
static inline int IS_NAN( float x )
|
||||
{
|
||||
int32_t i = FloatAsInt( x ); // only C
|
||||
return i & ( 255 << 23 ) == ( 255 << 23 );
|
||||
}
|
||||
#else
|
||||
#define IS_NAN isnan
|
||||
#endif
|
||||
|
||||
static inline float anglemod( float a )
|
||||
{
|
||||
a = (360.0f / 65536) * ((int)(a*(65536/360.0f)) & 65535);
|
||||
return a;
|
||||
}
|
||||
|
||||
static inline void SinCos( float radians, float *sine, float *cosine )
|
||||
{
|
||||
*sine = sin(radians);
|
||||
*cosine = cos(radians);
|
||||
*sine = sin( radians );
|
||||
*cosine = cos( radians );
|
||||
}
|
||||
|
||||
float rsqrt( float number );
|
||||
float anglemod( float a );
|
||||
word FloatToHalf( float v );
|
||||
float HalfToFloat( word h );
|
||||
void RoundUpHullSize( vec3_t size );
|
||||
int SignbitsForPlane( const vec3_t normal );
|
||||
int PlaneTypeForNormal( const vec3_t normal );
|
||||
int NearestPOW( int value, qboolean roundDown );
|
||||
float VectorNormalizeLength2( const vec3_t v, vec3_t out );
|
||||
qboolean VectorCompareEpsilon( const vec3_t vec1, const vec3_t vec2, vec_t epsilon );
|
||||
void VectorVectors( const vec3_t forward, vec3_t right, vec3_t up );
|
||||
void VectorAngles( const float *forward, float *angles );
|
||||
void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up );
|
||||
void VectorsAngles( const vec3_t forward, const vec3_t right, const vec3_t up, vec3_t angles );
|
||||
void PlaneIntersect( const struct mplane_s *plane, const vec3_t p0, const vec3_t p1, vec3_t out );
|
||||
static inline int NearestPOW( int value, qboolean roundDown )
|
||||
{
|
||||
int n = 1;
|
||||
|
||||
if( value <= 0 ) return 1;
|
||||
while( n < value ) n <<= 1;
|
||||
|
||||
if( roundDown )
|
||||
{
|
||||
if( n > value ) n >>= 1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static inline qboolean VectorCompareEpsilon( const vec3_t vec1, const vec3_t vec2, vec_t epsilon )
|
||||
{
|
||||
vec_t ax = fabs( vec1[0] - vec2[0] );
|
||||
vec_t ay = fabs( vec1[1] - vec2[1] );
|
||||
vec_t az = fabs( vec1[2] - vec2[2] );
|
||||
|
||||
return ( ax <= epsilon ) && ( ay <= epsilon ) && ( az <= epsilon ) ? true : false;
|
||||
}
|
||||
|
||||
static inline float VectorNormalizeLength2( const vec3_t v, vec3_t out )
|
||||
{
|
||||
float length = VectorLength( v );
|
||||
|
||||
if( length )
|
||||
{
|
||||
float ilength = 1.0f / length;
|
||||
out[0] = v[0] * ilength;
|
||||
out[1] = v[1] * ilength;
|
||||
out[2] = v[2] * ilength;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static inline void GAME_EXPORT AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up )
|
||||
{
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
|
||||
SinCos( DEG2RAD( angles[YAW] ), &sy, &cy );
|
||||
SinCos( DEG2RAD( angles[PITCH] ), &sp, &cp );
|
||||
SinCos( DEG2RAD( angles[ROLL] ), &sr, &cr );
|
||||
|
||||
if( forward )
|
||||
{
|
||||
forward[0] = cp * cy;
|
||||
forward[1] = cp * sy;
|
||||
forward[2] = -sp;
|
||||
}
|
||||
|
||||
if( right )
|
||||
{
|
||||
right[0] = (-1.0f * sr * sp * cy + -1.0f * cr * -sy );
|
||||
right[1] = (-1.0f * sr * sp * sy + -1.0f * cr * cy );
|
||||
right[2] = (-1.0f * sr * cp);
|
||||
}
|
||||
|
||||
if( up )
|
||||
{
|
||||
up[0] = (cr * sp * cy + -sr * -sy );
|
||||
up[1] = (cr * sp * sy + -sr * cy );
|
||||
up[2] = (cr * cp);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ClearBounds( vec3_t mins, vec3_t maxs )
|
||||
{
|
||||
@@ -221,20 +371,85 @@ static inline qboolean BoundsAndSphereIntersect( const vec3_t mins, const vec3_t
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs );
|
||||
qboolean SphereIntersect( const vec3_t vSphereCenter, float fSphereRadiusSquared, const vec3_t vLinePt, const vec3_t vLineDir );
|
||||
float RadiusFromBounds( const vec3_t mins, const vec3_t maxs );
|
||||
void ExpandBounds( vec3_t mins, vec3_t maxs, float offset );
|
||||
static inline float RadiusFromBounds( const vec3_t mins, const vec3_t maxs )
|
||||
{
|
||||
vec3_t corner;
|
||||
int i;
|
||||
|
||||
void AngleQuaternion( const vec3_t angles, vec4_t q, qboolean studio );
|
||||
void QuaternionAngle( const vec4_t q, vec3_t angles );
|
||||
void QuaternionSlerp( const vec4_t p, const vec4_t q, float t, vec4_t qt );
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
float a = fabs( mins[i] );
|
||||
float b = fabs( maxs[i] );
|
||||
corner[i] = Q_max( a, b );
|
||||
}
|
||||
|
||||
//
|
||||
// matrixlib.c
|
||||
//
|
||||
#define Matrix3x4_LoadIdentity( mat ) Matrix3x4_Copy( mat, m_matrix3x4_identity )
|
||||
#define Matrix3x4_Copy( out, in ) memcpy( out, in, sizeof( matrix3x4 ))
|
||||
return VectorLength( corner );
|
||||
}
|
||||
|
||||
static inline void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
float val = v[i];
|
||||
if( val < mins[i] ) mins[i] = val;
|
||||
if( val > maxs[i] ) maxs[i] = val;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ExpandBounds( vec3_t mins, vec3_t maxs, float offset )
|
||||
{
|
||||
mins[0] -= offset;
|
||||
mins[1] -= offset;
|
||||
mins[2] -= offset;
|
||||
maxs[0] += offset;
|
||||
maxs[1] += offset;
|
||||
maxs[2] += offset;
|
||||
}
|
||||
|
||||
static inline int SignbitsForPlane( const vec3_t normal )
|
||||
{
|
||||
int bits, i;
|
||||
|
||||
for( bits = i = 0; i < 3; i++ )
|
||||
if( normal[i] < 0.0f ) bits |= 1<<i;
|
||||
return bits;
|
||||
}
|
||||
|
||||
static inline int PlaneTypeForNormal( const vec3_t normal )
|
||||
{
|
||||
if( normal[0] == 1.0f )
|
||||
return PLANE_X;
|
||||
if( normal[1] == 1.0f )
|
||||
return PLANE_Y;
|
||||
if( normal[2] == 1.0f )
|
||||
return PLANE_Z;
|
||||
return PLANE_NONAXIAL;
|
||||
}
|
||||
|
||||
static inline void AngleQuaternion( const vec3_t angles, vec4_t q, qboolean studio )
|
||||
{
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
|
||||
if( studio )
|
||||
{
|
||||
SinCos( angles[ROLL] * 0.5f, &sy, &cy );
|
||||
SinCos( angles[YAW] * 0.5f, &sp, &cp );
|
||||
SinCos( angles[PITCH] * 0.5f, &sr, &cr );
|
||||
}
|
||||
else
|
||||
{
|
||||
SinCos( DEG2RAD( angles[YAW] ) * 0.5f, &sy, &cy );
|
||||
SinCos( DEG2RAD( angles[PITCH] ) * 0.5f, &sp, &cp );
|
||||
SinCos( DEG2RAD( angles[ROLL] ) * 0.5f, &sr, &cr );
|
||||
}
|
||||
|
||||
q[0] = sr * cp * cy - cr * sp * sy; // X
|
||||
q[1] = cr * sp * cy + sr * cp * sy; // Y
|
||||
q[2] = cr * cp * sy - sr * sp * cy; // Z
|
||||
q[3] = cr * cp * cy + sr * sp * sy; // W
|
||||
}
|
||||
|
||||
static inline void Matrix3x4_SetOrigin( matrix3x4 out, float x, float y, float z )
|
||||
{
|
||||
@@ -250,56 +465,23 @@ static inline void Matrix3x4_OriginFromMatrix( const matrix3x4 in, float *out )
|
||||
out[2] = in[2][3];
|
||||
}
|
||||
|
||||
void Matrix3x4_VectorTransform( const matrix3x4 in, const float v[3], float out[3] );
|
||||
void Matrix3x4_VectorITransform( const matrix3x4 in, const float v[3], float out[3] );
|
||||
void Matrix3x4_VectorRotate( const matrix3x4 in, const float v[3], float out[3] );
|
||||
void Matrix3x4_VectorIRotate( const matrix3x4 in, const float v[3], float out[3] );
|
||||
void Matrix3x4_ConcatTransforms( matrix3x4 out, const matrix3x4 in1, const matrix3x4 in2 );
|
||||
void Matrix3x4_FromOriginQuat( matrix3x4 out, const vec4_t quaternion, const vec3_t origin );
|
||||
void Matrix3x4_CreateFromEntity( matrix3x4 out, const vec3_t angles, const vec3_t origin, float scale );
|
||||
void Matrix3x4_TransformAABB( const matrix3x4 world, const vec3_t mins, const vec3_t maxs, vec3_t absmin, vec3_t absmax );
|
||||
void Matrix3x4_AnglesFromMatrix( const matrix3x4 in, vec3_t out );
|
||||
static inline void QuaternionAngle( const vec4_t q, vec3_t angles )
|
||||
{
|
||||
matrix3x4 mat;
|
||||
Matrix3x4_FromOriginQuat( mat, q, vec3_origin );
|
||||
Matrix3x4_AnglesFromMatrix( mat, angles );
|
||||
}
|
||||
|
||||
#define Matrix4x4_LoadIdentity( mat ) Matrix4x4_Copy( mat, m_matrix4x4_identity )
|
||||
#define Matrix4x4_Copy( out, in ) memcpy( out, in, sizeof( matrix4x4 ))
|
||||
static inline void R_StudioSlerpBones( int numbones, vec4_t q1[], float pos1[][3], const vec4_t q2[], const float pos2[][3], float s )
|
||||
{
|
||||
int i;
|
||||
s = bound( 0.0f, s, 1.0f );
|
||||
|
||||
void Matrix4x4_VectorTransform( const matrix4x4 in, const float v[3], float out[3] );
|
||||
void Matrix4x4_VectorITransform( const matrix4x4 in, const float v[3], float out[3] );
|
||||
void Matrix4x4_VectorRotate( const matrix4x4 in, const float v[3], float out[3] );
|
||||
void Matrix4x4_VectorIRotate( const matrix4x4 in, const float v[3], float out[3] );
|
||||
void Matrix4x4_ConcatTransforms( matrix4x4 out, const matrix4x4 in1, const matrix4x4 in2 );
|
||||
void Matrix4x4_CreateFromEntity( matrix4x4 out, const vec3_t angles, const vec3_t origin, float scale );
|
||||
void Matrix4x4_TransformPositivePlane( const matrix4x4 in, const vec3_t normal, float d, vec3_t out, float *dist );
|
||||
void Matrix4x4_ConvertToEntity( const matrix4x4 in, vec3_t angles, vec3_t origin );
|
||||
void Matrix4x4_Invert_Simple( matrix4x4 out, const matrix4x4 in1 );
|
||||
qboolean Matrix4x4_Invert_Full( matrix4x4 out, const matrix4x4 in1 );
|
||||
|
||||
void R_StudioSlerpBones( int numbones, vec4_t q1[], float pos1[][3], const vec4_t q2[], const float pos2[][3], float s );
|
||||
void R_StudioCalcBoneQuaternion( int frame, float s, const mstudiobone_t *pbone, const mstudioanim_t *panim, const float *adj, vec4_t q );
|
||||
void R_StudioCalcBonePosition( int frame, float s, const mstudiobone_t *pbone, const mstudioanim_t *panim, const vec3_t adj, vec3_t pos );
|
||||
|
||||
int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p );
|
||||
#define BOX_ON_PLANE_SIDE( emins, emaxs, p ) \
|
||||
((( p )->type < 3 ) ? \
|
||||
( \
|
||||
((p)->dist <= (emins)[(p)->type]) ? \
|
||||
1 \
|
||||
: \
|
||||
( \
|
||||
((p)->dist >= (emaxs)[(p)->type]) ? \
|
||||
2 \
|
||||
: \
|
||||
3 \
|
||||
) \
|
||||
) \
|
||||
: \
|
||||
BoxOnPlaneSide(( emins ), ( emaxs ), ( p )))
|
||||
|
||||
extern vec3_t vec3_origin;
|
||||
extern int boxpnt[6][4];
|
||||
extern const matrix3x4 m_matrix3x4_identity;
|
||||
extern const matrix4x4 m_matrix4x4_identity;
|
||||
extern const float m_bytenormals[NUMVERTEXNORMALS][3];
|
||||
for( i = 0; i < numbones; i++ )
|
||||
{
|
||||
QuaternionSlerp( q1[i], q2[i], s, q1[i] );
|
||||
VectorLerp( pos1[i], s, pos2[i], pos1[i] );
|
||||
}
|
||||
}
|
||||
|
||||
#endif // XASH3D_MATHLIB_H
|
||||
|
||||
|
||||
@@ -27,6 +27,16 @@ ref_globals_t *gpGlobals;
|
||||
ref_client_t *gp_cl;
|
||||
ref_host_t *gp_host;
|
||||
|
||||
void _Mem_Free( void *data, const char *filename, int fileline )
|
||||
{
|
||||
gEngfuncs._Mem_Free( data, filename, fileline );
|
||||
}
|
||||
|
||||
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
{
|
||||
return gEngfuncs._Mem_Alloc( poolptr, size, clear, filename, fileline );
|
||||
}
|
||||
|
||||
static void R_ClearScreen( void )
|
||||
{
|
||||
pglClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
|
||||
|
||||
@@ -782,10 +782,14 @@ DECLARE_ENGINE_SHARED_CVAR_LIST()
|
||||
//
|
||||
#include "crtlib.h"
|
||||
|
||||
#define Mem_Malloc( pool, size ) gEngfuncs._Mem_Alloc( pool, size, false, __FILE__, __LINE__ )
|
||||
#define Mem_Calloc( pool, size ) gEngfuncs._Mem_Alloc( pool, size, true, __FILE__, __LINE__ )
|
||||
void _Mem_Free( void *data, const char *filename, int fileline );
|
||||
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
ALLOC_CHECK( 2 ) MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
|
||||
#define Mem_Malloc( pool, size ) _Mem_Alloc( pool, size, false, __FILE__, __LINE__ )
|
||||
#define Mem_Calloc( pool, size ) _Mem_Alloc( pool, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Realloc( pool, ptr, size ) gEngfuncs._Mem_Realloc( pool, ptr, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Free( mem ) gEngfuncs._Mem_Free( mem, __FILE__, __LINE__ )
|
||||
#define Mem_Free( mem ) _Mem_Free( mem, __FILE__, __LINE__ )
|
||||
#define Mem_AllocPool( name ) gEngfuncs._Mem_AllocPool( name, __FILE__, __LINE__ )
|
||||
#define Mem_FreePool( pool ) gEngfuncs._Mem_FreePool( pool, __FILE__, __LINE__ )
|
||||
#define Mem_EmptyPool( pool ) gEngfuncs._Mem_EmptyPool( pool, __FILE__, __LINE__ )
|
||||
|
||||
@@ -23,6 +23,17 @@ gl_globals_t tr;
|
||||
ref_speeds_t r_stats;
|
||||
poolhandle_t r_temppool;
|
||||
viddef_t vid;
|
||||
|
||||
void _Mem_Free( void *data, const char *filename, int fileline )
|
||||
{
|
||||
gEngfuncs._Mem_Free( data, filename, fileline );
|
||||
}
|
||||
|
||||
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
{
|
||||
return gEngfuncs._Mem_Alloc( poolptr, size, clear, filename, fileline );
|
||||
}
|
||||
|
||||
static void GAME_EXPORT R_ClearScreen( void )
|
||||
{
|
||||
|
||||
|
||||
@@ -1237,10 +1237,14 @@ void R_SetUpWorldTransform (void);
|
||||
#include "crtlib.h"
|
||||
#include "crclib.h"
|
||||
#if 1
|
||||
#define Mem_Malloc( pool, size ) gEngfuncs._Mem_Alloc( pool, size, false, __FILE__, __LINE__ )
|
||||
#define Mem_Calloc( pool, size ) gEngfuncs._Mem_Alloc( pool, size, true, __FILE__, __LINE__ )
|
||||
void _Mem_Free( void *data, const char *filename, int fileline );
|
||||
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
ALLOC_CHECK( 2 ) MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
|
||||
#define Mem_Malloc( pool, size ) _Mem_Alloc( pool, size, false, __FILE__, __LINE__ )
|
||||
#define Mem_Calloc( pool, size ) _Mem_Alloc( pool, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Realloc( pool, ptr, size ) gEngfuncs._Mem_Realloc( pool, ptr, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Free( mem ) gEngfuncs._Mem_Free( mem, __FILE__, __LINE__ )
|
||||
#define Mem_Free( mem ) _Mem_Free( mem, __FILE__, __LINE__ )
|
||||
#define Mem_AllocPool( name ) gEngfuncs._Mem_AllocPool( name, __FILE__, __LINE__ )
|
||||
#define Mem_FreePool( pool ) gEngfuncs._Mem_FreePool( pool, __FILE__, __LINE__ )
|
||||
#define Mem_EmptyPool( pool ) gEngfuncs._Mem_EmptyPool( pool, __FILE__, __LINE__ )
|
||||
|
||||
15
wscript
15
wscript
@@ -79,8 +79,10 @@ SUBDIRS = [
|
||||
Subproject('ref/gl', lambda x: not x.env.DEDICATED and (x.env.GL or x.env.NANOGL or x.env.GLWES or x.env.GL4ES)),
|
||||
Subproject('ref/soft', lambda x: not x.env.DEDICATED and not x.env.SUPPORT_BSP2_FORMAT and x.env.SOFT),
|
||||
Subproject('ref/null', lambda x: not x.env.DEDICATED and x.env.NULL),
|
||||
Subproject('3rdparty/bzip2', lambda x: not x.env.DEDICATED and not x.env.HAVE_SYSTEM_BZ2),
|
||||
Subproject('3rdparty/mainui', lambda x: not x.env.DEDICATED),
|
||||
Subproject('3rdparty/vgui_support', lambda x: not x.env.DEDICATED),
|
||||
# Subproject('3rdparty/freevgui', lambda x: not x.env.DEDICATED),
|
||||
Subproject('stub/client', lambda x: not x.env.DEDICATED),
|
||||
Subproject('game_launch', lambda x: not x.env.DISABLE_LAUNCHER),
|
||||
|
||||
@@ -227,12 +229,10 @@ def configure(conf):
|
||||
elif conf.env.DEST_OS == 'nswitch':
|
||||
conf.options.NO_VGUI = True
|
||||
conf.options.GL = True
|
||||
conf.options.NO_ASYNC_RESOLVE = True
|
||||
conf.options.USE_STBTT = True
|
||||
elif conf.env.DEST_OS == 'psvita':
|
||||
conf.options.NO_VGUI = True
|
||||
conf.options.GL = True
|
||||
conf.options.NO_ASYNC_RESOLVE = True
|
||||
conf.options.USE_STBTT = True
|
||||
# we'll specify -fPIC by hand for shared libraries only
|
||||
enforce_pic = False
|
||||
@@ -307,9 +307,10 @@ def configure(conf):
|
||||
'-Werror=alloc-size',
|
||||
'-Werror=bool-compare',
|
||||
'-Werror=bool-operation',
|
||||
'-Werror=cast-align=strict',
|
||||
# '-Werror=cast-align=strict',
|
||||
'-Werror=duplicated-cond',
|
||||
'-Werror=format-extra-args',
|
||||
'-Werror=free-nonheap-object',
|
||||
'-Werror=implicit-fallthrough=2',
|
||||
'-Werror=logical-op',
|
||||
'-Werror=nonnull',
|
||||
@@ -334,6 +335,7 @@ def configure(conf):
|
||||
'-Wformat=2',
|
||||
'-Winit-self',
|
||||
'-Wmisleading-indentation',
|
||||
'-Wmismatched-dealloc',
|
||||
'-Wstringop-overflow',
|
||||
'-Wunintialized',
|
||||
|
||||
@@ -458,6 +460,13 @@ int main(void) { return !opus_custom_encoder_init((OpusCustomEncoder *)1, (const
|
||||
if conf.check_cc(msg='Checking if opus supports custom modes', defines='CUSTOM_MODES=1', use='opus werror', fragment=frag, mandatory=False):
|
||||
conf.env.HAVE_SYSTEM_OPUS = True
|
||||
|
||||
# search for bzip2
|
||||
BZIP2_CHECK='''#include <bzlib.h>
|
||||
int main(void) { return (int)BZ2_bzlibVersion(); }'''
|
||||
|
||||
if conf.check_cc(lib='bz2', fragment=BZIP2_CHECK, uselib_store='bzip2', mandatory=False):
|
||||
conf.env.HAVE_SYSTEM_BZ2 = True
|
||||
|
||||
conf.define('XASH_LOW_MEMORY', conf.options.LOW_MEMORY)
|
||||
|
||||
for i in SUBDIRS:
|
||||
|
||||
Reference in New Issue
Block a user