mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-18 15:01:41 +00:00
Protocol 666/large map support from FitzQuake.
Alpha and lerping aren't implemented yet, but things seem to be working. I can load and play oms2.bsp (Conflagrant Rodent).
This commit is contained in:
parent
8c4fe2f844
commit
31c13d92a2
25 changed files with 758 additions and 228 deletions
|
@ -41,11 +41,9 @@
|
|||
#define MAX_MAP_ENTSTRING 65536
|
||||
|
||||
#define MAX_MAP_PLANES 32767
|
||||
//#define MAX_MAP_PLANES 8192
|
||||
#define MAX_MAP_NODES 32767 // because negative shorts are contents
|
||||
#define MAX_MAP_CLIPNODES 32767 //
|
||||
#define MAX_MAP_LEAFS 32767 //
|
||||
//#define MAX_MAP_LEAFS 8192
|
||||
#define MAX_MAP_VERTS 65535
|
||||
#define MAX_MAP_FACES 65535
|
||||
#define MAX_MAP_MARKSURFACES 65535
|
||||
|
@ -181,6 +179,7 @@ typedef struct texinfo_s {
|
|||
int32_t flags;
|
||||
} texinfo_t;
|
||||
#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision
|
||||
#define TEX_MISSING 2 // this texinfo does not have a texture
|
||||
|
||||
// note that edge 0 is never used, because negative edge nums are used for
|
||||
// counterclockwise use of the edge in a face
|
||||
|
|
|
@ -46,7 +46,8 @@ void MSG_WriteCoordAngleV (sizebuf_t *sb, const vec3_t coord,
|
|||
const vec3_t angles);
|
||||
void MSG_WriteAngle (sizebuf_t *sb, float angle);
|
||||
void MSG_WriteAngleV (sizebuf_t *sb, const vec3_t angles);
|
||||
void MSG_WriteAngle16 (sizebuf_t *sb, float angle16);
|
||||
void MSG_WriteAngle16 (sizebuf_t *sb, float angle);
|
||||
void MSG_WriteAngle16V (sizebuf_t *sb, const vec3_t angle);
|
||||
void MSG_WriteUTF8 (sizebuf_t *sb, unsigned utf8);
|
||||
|
||||
typedef struct msg_s {
|
||||
|
@ -72,6 +73,7 @@ float MSG_ReadAngle (qmsg_t *msg);
|
|||
void MSG_ReadCoordAngleV (qmsg_t *msg, vec3_t coord, vec3_t angles);
|
||||
void MSG_ReadAngleV (qmsg_t *msg, vec3_t angles);
|
||||
float MSG_ReadAngle16 (qmsg_t *msg);
|
||||
void MSG_ReadAngle16V (qmsg_t *msg, vec3_t angles);
|
||||
int MSG_ReadUTF8 (qmsg_t *msg);
|
||||
|
||||
//@}
|
||||
|
|
|
@ -34,12 +34,9 @@
|
|||
#define MAX_QPATH 64
|
||||
#define MAX_CL_STATS 32
|
||||
#define NUM_CSHIFTS 4
|
||||
#define MAX_MODELS 256
|
||||
#define MAX_SOUNDS 256
|
||||
#define MAX_SCOREBOARD 16
|
||||
#define MAX_SCOREBOARDNAME 32
|
||||
#define MAX_STYLESTRING 64
|
||||
#define MAX_EDICTS 768
|
||||
#define MAX_LIGHTSTYLES 64
|
||||
|
||||
#define clc_stringcmd 4
|
||||
|
|
|
@ -41,7 +41,7 @@ struct qsockaddr
|
|||
|
||||
#define NET_NAMELEN 64
|
||||
|
||||
#define NET_MAXMESSAGE 8192
|
||||
#define NET_MAXMESSAGE 32000
|
||||
#define NET_HEADERSIZE (2 * sizeof(unsigned int))
|
||||
#define NET_DATAGRAMSIZE (MAX_DATAGRAM + NET_HEADERSIZE)
|
||||
|
||||
|
|
|
@ -297,7 +297,7 @@ void SND_SFX_Init (void);
|
|||
*/
|
||||
//@{
|
||||
#define MAX_CHANNELS 512 //!< number of available mixing channels
|
||||
#define MAX_DYNAMIC_CHANNELS 8 //!< number of dynamic channels
|
||||
#define MAX_DYNAMIC_CHANNELS 128 //!< number of dynamic channels
|
||||
#define MAX_STATIC_CHANNELS 256 //!< number of static channels
|
||||
extern channel_t snd_channels[MAX_CHANNELS]; //!< pool of available channels
|
||||
extern int snd_total_channels; //!< number of active channels
|
||||
|
|
|
@ -357,6 +357,18 @@ Mod_LoadSubmodels (bsp_t *bsp)
|
|||
out->firstface = LittleLong (in->firstface);
|
||||
out->numfaces = LittleLong (in->numfaces);
|
||||
}
|
||||
|
||||
out = loadmodel->submodels;
|
||||
|
||||
if (out->visleafs > MAX_MAP_LEAFS) {
|
||||
Sys_Error ("Mod_LoadSubmodels: too many visleafs (%d, max = %d) in %s",
|
||||
out->visleafs, MAX_MAP_LEAFS, loadmodel->name);
|
||||
}
|
||||
|
||||
if (out->visleafs > 8192)
|
||||
Sys_MaskPrintf (SYS_WARN,
|
||||
"%i visleafs exceeds standard limit of 8192.\n",
|
||||
out->visleafs);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -473,8 +485,8 @@ CalcSurfaceExtents (msurface_t *s)
|
|||
|
||||
s->texturemins[i] = bmins[i] * 16;
|
||||
s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
|
||||
// FIXME even 512 is really too small, need a saner test
|
||||
if (!(tex->flags & TEX_SPECIAL) && s->extents[i] > 512)
|
||||
// FIXME even 2000 is really too small, need a saner test
|
||||
if (!(tex->flags & TEX_SPECIAL) && s->extents[i] > 2000)
|
||||
Sys_Error ("Bad surface extents: %d %x %d %d", i, tex->flags,
|
||||
s->extents[i], LongSwap (s->extents[i]));
|
||||
}
|
||||
|
@ -491,6 +503,11 @@ Mod_LoadFaces (bsp_t *bsp)
|
|||
count = bsp->numfaces;
|
||||
out = Hunk_AllocName (count * sizeof (*out), loadname);
|
||||
|
||||
if (count > 32767) {
|
||||
Sys_MaskPrintf (SYS_WARN,
|
||||
"%i faces exceeds standard limit of 32767.\n", count);
|
||||
}
|
||||
|
||||
loadmodel->surfaces = out;
|
||||
loadmodel->numsurfaces = count;
|
||||
|
||||
|
@ -566,6 +583,11 @@ Mod_LoadNodes (bsp_t *bsp)
|
|||
count = bsp->numnodes;
|
||||
out = Hunk_AllocName (count * sizeof (*out), loadname);
|
||||
|
||||
if (count > 32767) {
|
||||
Sys_MaskPrintf (SYS_WARN,
|
||||
"%i nodes exceeds standard limit of 32767.\n", count);
|
||||
}
|
||||
|
||||
loadmodel->nodes = out;
|
||||
loadmodel->numnodes = count;
|
||||
|
||||
|
@ -582,11 +604,22 @@ Mod_LoadNodes (bsp_t *bsp)
|
|||
out->numsurfaces = LittleShort (in->numfaces);
|
||||
|
||||
for (j = 0; j < 2; j++) {
|
||||
p = LittleShort (in->children[j]);
|
||||
if (p >= 0)
|
||||
// handle > 32k nodes. From darkplaces via fitzquake
|
||||
p = (unsigned short) LittleShort (in->children[j]);
|
||||
if (p < count) {
|
||||
out->children[j] = loadmodel->nodes + p;
|
||||
else
|
||||
out->children[j] = (mnode_t *) (loadmodel->leafs + (-1 - p));
|
||||
} else {
|
||||
p = 65535 - p; //NOTE this uses 65535 intentionally, -1 is leaf
|
||||
if (p < loadmodel->numleafs) {
|
||||
out->children[j] = (mnode_t *) (loadmodel->leafs + p);
|
||||
} else {
|
||||
Sys_Printf ("Mod_LoadNodes: invalid leaf index %i "
|
||||
"(file has only %i leafs)\n", p,
|
||||
loadmodel->numleafs);
|
||||
//map it to the solid leaf
|
||||
out->children[j] = (mnode_t *)(loadmodel->leafs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -605,6 +638,9 @@ Mod_LoadLeafs (bsp_t *bsp)
|
|||
count = bsp->numleafs;
|
||||
out = Hunk_AllocName (count * sizeof (*out), loadname);
|
||||
|
||||
if (count > 32767)
|
||||
Sys_Error ("%i leafs exceeds limit of 32767.\n", count);
|
||||
|
||||
loadmodel->leafs = out;
|
||||
loadmodel->numleafs = count;
|
||||
// snprintf(s, sizeof (s), "maps/%s.bsp",
|
||||
|
@ -621,8 +657,8 @@ Mod_LoadLeafs (bsp_t *bsp)
|
|||
out->contents = p;
|
||||
|
||||
out->firstmarksurface = loadmodel->marksurfaces +
|
||||
LittleShort (in->firstmarksurface);
|
||||
out->nummarksurfaces = LittleShort (in->nummarksurfaces);
|
||||
(uint16_t) LittleShort (in->firstmarksurface);
|
||||
out->nummarksurfaces = (uint16_t) LittleShort (in->nummarksurfaces);
|
||||
|
||||
p = LittleLong (in->visofs);
|
||||
if (p == -1)
|
||||
|
@ -657,6 +693,12 @@ Mod_LoadClipnodes (bsp_t *bsp)
|
|||
count = bsp->numclipnodes;
|
||||
out = Hunk_AllocName (count * sizeof (*out), loadname);
|
||||
|
||||
if (count > 32767) {
|
||||
Sys_MaskPrintf (SYS_WARN,
|
||||
"%i clilpnodes exceeds standard limit of 32767.\n",
|
||||
count);
|
||||
}
|
||||
|
||||
loadmodel->clipnodes = out;
|
||||
loadmodel->numclipnodes = count;
|
||||
|
||||
|
@ -688,8 +730,14 @@ Mod_LoadClipnodes (bsp_t *bsp)
|
|||
|
||||
for (i = 0; i < count; i++, out++, in++) {
|
||||
out->planenum = LittleLong (in->planenum);
|
||||
out->children[0] = LittleShort (in->children[0]);
|
||||
out->children[1] = LittleShort (in->children[1]);
|
||||
if (out->planenum < 0 || out->planenum >= loadmodel->numplanes)
|
||||
Sys_Error ("Mod_LoadClipnodes: planenum out of bounds");
|
||||
out->children[0] = (uint16_t) LittleShort (in->children[0]);
|
||||
out->children[1] = (uint16_t) LittleShort (in->children[1]);
|
||||
if (out->children[0] >= count)
|
||||
out->children[0] -= 65536;
|
||||
if (out->children[1] >= count)
|
||||
out->children[1] -= 65536;
|
||||
if ((out->children[0] >= 0
|
||||
&& (out->children[0] < hull->firstclipnode
|
||||
|| out->children[0] > hull->lastclipnode))
|
||||
|
@ -748,11 +796,17 @@ Mod_LoadMarksurfaces (bsp_t *bsp)
|
|||
count = bsp->nummarksurfaces;
|
||||
out = Hunk_AllocName (count * sizeof (*out), loadname);
|
||||
|
||||
if (count > 32767) {
|
||||
Sys_MaskPrintf (SYS_WARN,
|
||||
"%i marksurfaces exceeds standard limit of 32767.\n",
|
||||
count);
|
||||
}
|
||||
|
||||
loadmodel->marksurfaces = out;
|
||||
loadmodel->nummarksurfaces = count;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
j = LittleShort (in[i]);
|
||||
j = (uint16_t) LittleShort (in[i]);
|
||||
if (j >= loadmodel->numsurfaces)
|
||||
Sys_Error ("Mod_ParseMarksurfaces: bad surface number");
|
||||
out[i] = loadmodel->surfaces + j;
|
||||
|
|
|
@ -160,9 +160,24 @@ MSG_WriteAngleV (sizebuf_t *sb, const vec3_t angles)
|
|||
}
|
||||
|
||||
VISIBLE void
|
||||
MSG_WriteAngle16 (sizebuf_t *sb, float angle16)
|
||||
MSG_WriteAngle16 (sizebuf_t *sb, float angle)
|
||||
{
|
||||
MSG_WriteShort (sb, (int) (angle16 * (65536.0 / 360.0)) & 65535);
|
||||
MSG_WriteShort (sb, (int) (angle * (65536.0 / 360.0)) & 65535);
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
MSG_WriteAngle16V (sizebuf_t *sb, const vec3_t angles)
|
||||
{
|
||||
byte *buf;
|
||||
int i;
|
||||
unsigned short ang;
|
||||
|
||||
buf = SZ_GetSpace (sb, 6);
|
||||
for (i = 0; i < 3; i++) {
|
||||
ang = (int) (angles[i] * (65536.0 / 360.0)) & 65535;
|
||||
*buf++ = ang & 0xff;
|
||||
*buf++ = ang >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
|
@ -383,6 +398,19 @@ MSG_ReadAngle16 (qmsg_t *msg)
|
|||
return MSG_ReadShort (msg) * (360.0 / 65536.0);
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
MSG_ReadAngle16V (qmsg_t *msg, vec3_t angles)
|
||||
{
|
||||
int i;
|
||||
short ang;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
ang = MSG_ReadByte (msg);
|
||||
ang |= MSG_ReadByte (msg) << 8;
|
||||
angles[i] = ang * (360.0 / 65536.0);
|
||||
}
|
||||
}
|
||||
|
||||
VISIBLE int
|
||||
MSG_ReadUTF8 (qmsg_t *msg)
|
||||
{
|
||||
|
|
|
@ -110,7 +110,7 @@ vec5_t skyvec[6][4] = {
|
|||
}
|
||||
};
|
||||
|
||||
void
|
||||
VISIBLE void
|
||||
R_LoadSkys (const char *skyname)
|
||||
{
|
||||
const char *name;
|
||||
|
|
|
@ -215,12 +215,10 @@ R_SetSkyFrame (void)
|
|||
|
||||
|
||||
/*
|
||||
R_LoadSkys
|
||||
|
||||
Stub function for loading a skybox. Currently we have support for
|
||||
skyboxes only in GL targets, so we just do nothing here. --KB
|
||||
*/
|
||||
void
|
||||
VISIBLE void
|
||||
R_LoadSkys (const char *name)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -216,12 +216,10 @@ R_SetSkyFrame (void)
|
|||
|
||||
|
||||
/*
|
||||
R_LoadSkys
|
||||
|
||||
Stub function for loading a skybox. Currently we have support for
|
||||
skyboxes only in GL targets, so we just do nothing here. --KB
|
||||
*/
|
||||
void
|
||||
VISIBLE void
|
||||
R_LoadSkys (const char *name)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -215,6 +215,8 @@ typedef struct
|
|||
|
||||
// frag scoreboard
|
||||
scoreboard_t *scores; // [cl.maxclients]
|
||||
|
||||
unsigned protocol;
|
||||
} client_state_t;
|
||||
|
||||
|
||||
|
@ -278,8 +280,7 @@ extern struct cvar_s *cl_cshift_powerup;
|
|||
|
||||
extern struct cvar_s *noskins;
|
||||
|
||||
#define MAX_TEMP_ENTITIES 64 // lightning bolts, etc
|
||||
#define MAX_STATIC_ENTITIES 128 // torches, etc
|
||||
#define MAX_STATIC_ENTITIES 512 // torches, etc
|
||||
|
||||
extern client_state_t cl;
|
||||
|
||||
|
@ -290,6 +291,7 @@ extern entity_t cl_static_entities[MAX_STATIC_ENTITIES];
|
|||
|
||||
extern int fps_count;
|
||||
|
||||
extern void (*write_angles) (sizebuf_t *sb, const vec3_t angles);
|
||||
|
||||
// cl_main
|
||||
void CL_Init (void);
|
||||
|
|
|
@ -34,11 +34,14 @@
|
|||
#include "QF/qtypes.h"
|
||||
#include "QF/qdefs.h"
|
||||
|
||||
#undef MAX_DATAGRAM
|
||||
#define MAX_DATAGRAM 1024 // max length of unreliable message
|
||||
|
||||
#undef MAX_MSGLEN
|
||||
#define MAX_MSGLEN 8000 // max length of a reliable message
|
||||
#define MIN_EDICTS 256 // lowest allowed value for max_edicts
|
||||
#define MAX_EDICTS 32000 // highest allowed value for max_edicts
|
||||
#define MAX_DATAGRAM 32000 // max length of unreliable message
|
||||
#define MAX_MSGLEN 32000 // max length of a reliable message
|
||||
#define DATAGRAM_MTU 1400 // actual limit for unreliable messages
|
||||
// to nonlocal clients
|
||||
#define MAX_MODELS 2048
|
||||
#define MAX_SOUNDS 2048
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
|
||||
#include "QF/qtypes.h"
|
||||
|
||||
#define PROTOCOL_VERSION 15
|
||||
#define PROTOCOL_NETQUAKE 15
|
||||
#define PROTOCOL_FITZQUAKE 666
|
||||
|
||||
// if the high bit of the servercmd is set, the low bits are fast update flags:
|
||||
#define U_MOREBITS (1<<0)
|
||||
|
@ -39,7 +40,7 @@
|
|||
#define U_ORIGIN2 (1<<2)
|
||||
#define U_ORIGIN3 (1<<3)
|
||||
#define U_ANGLE2 (1<<4)
|
||||
#define U_NOLERP (1<<5) // don't interpolate movement
|
||||
#define U_STEP (1<<5) // don't interpolate movement
|
||||
#define U_FRAME (1<<6)
|
||||
#define U_SIGNAL (1<<7) // just differentiates from other updates
|
||||
|
||||
|
@ -51,30 +52,16 @@
|
|||
#define U_SKIN (1<<12)
|
||||
#define U_EFFECTS (1<<13)
|
||||
#define U_LONGENTITY (1<<14)
|
||||
|
||||
// QSG Protocol Extensions (Version 2) ========================================
|
||||
// Network definitions for the engine
|
||||
|
||||
#define U_EXTEND1 (1<<15)
|
||||
#define U_DELTA (1<<16) // no data, while this is set the entity is delta compressed (uses previous frame as a baseline, meaning only things that have changed from the previous frame are sent, except for the forced full update every half second)
|
||||
#define U_ALPHA (1<<17) // 1 byte, 0.0-1.0 = 0-255 (Unsent if 1)
|
||||
#define U_SCALE (1<<18) // 1 byte, scale / 16 positive, (Unsent if 1)
|
||||
#define U_EFFECTS2 (1<<19) // 1 byte, .effects & 0xFF00
|
||||
#define U_GLOWSIZE (1<<20) // 1 byte, float/8.0, signed. Unsent if 1
|
||||
#define U_GLOWCOLOR (1<<21) // 1 byte, palette index, default, 254.
|
||||
#define U_COLORMOD (1<<22) // 1 byte, rrrgggbb. Model tinting
|
||||
#define U_EXTEND2 (1<<23) // Another byte to follow
|
||||
|
||||
#define U_GLOWTRAIL (1<<24) // Leave U_GLOW* trail
|
||||
#define U_VIEWMODEL (1<<25) // Attach model to view (relative). Owner only
|
||||
#define U_FRAME2 (1<<26) // 1 byte .frame & 0xFF00 (second byte)
|
||||
#define U_UNUSED27 (1<<27) // future expansion
|
||||
#define U_UNUSED28 (1<<28) // future expansion
|
||||
#define U_UNUSED29 (1<<29) // future expansion
|
||||
#define U_UNUSED30 (1<<30) // future expansion
|
||||
#define U_EXTEND3 (1<<31) // another byte to follow, future expansion
|
||||
|
||||
// QSG 2 End ==================================================================
|
||||
//PROTOCOL_FITZQUAKE -- new bits
|
||||
#define U_EXTEND1 (1<<15)
|
||||
#define U_ALPHA (1<<16) // 1 byte, uses ENTALPHA_ENCODE, not sent if equal to baseline
|
||||
#define U_FRAME2 (1<<17) // 1 byte, this is .frame & 0xFF00 (second byte)
|
||||
#define U_MODEL2 (1<<18) // 1 byte, this is .modelindex & 0xFF00 (second byte)
|
||||
#define U_LERPFINISH (1<<19) // 1 byte, 0.0-1.0 maps to 0-255, not sent if exactly 0.1, this is ent->v.nextthink - sv.time, used for lerping
|
||||
#define U_UNUSED20 (1<<20)
|
||||
#define U_UNUSED21 (1<<21)
|
||||
#define U_UNUSED22 (1<<22)
|
||||
#define U_EXTEND2 (1<<23) // another byte to follow, future expansion
|
||||
|
||||
#define SU_VIEWHEIGHT (1<<0)
|
||||
#define SU_IDEALPITCH (1<<1)
|
||||
|
@ -84,21 +71,55 @@
|
|||
#define SU_VELOCITY1 (1<<5)
|
||||
#define SU_VELOCITY2 (1<<6)
|
||||
#define SU_VELOCITY3 (1<<7)
|
||||
//#define SU_AIMENT (1<<8) AVAILABLE BIT
|
||||
#define SU_UNUSED8 (1<<8) //AVAILABLE BIT
|
||||
#define SU_ITEMS (1<<9)
|
||||
#define SU_ONGROUND (1<<10) // no data follows, the bit is it
|
||||
#define SU_INWATER (1<<11) // no data follows, the bit is it
|
||||
#define SU_WEAPONFRAME (1<<12)
|
||||
#define SU_ARMOR (1<<13)
|
||||
#define SU_WEAPON (1<<14)
|
||||
// PROTOCOL_FITZQUAKE -- new bits
|
||||
#define SU_EXTEND1 (1<<15) // another byte to follow
|
||||
#define SU_WEAPON2 (1<<16) // 1 byte, this is .weaponmodel & 0xFF00 (second byte)
|
||||
#define SU_ARMOR2 (1<<17) // 1 byte, this is .armorvalue & 0xFF00 (second byte)
|
||||
#define SU_AMMO2 (1<<18) // 1 byte, this is .currentammo & 0xFF00 (second byte)
|
||||
#define SU_SHELLS2 (1<<19) // 1 byte, this is .ammo_shells & 0xFF00 (second byte)
|
||||
#define SU_NAILS2 (1<<20) // 1 byte, this is .ammo_nails & 0xFF00 (second byte)
|
||||
#define SU_ROCKETS2 (1<<21) // 1 byte, this is .ammo_rockets & 0xFF00 (second byte)
|
||||
#define SU_CELLS2 (1<<22) // 1 byte, this is .ammo_cells & 0xFF00 (second byte)
|
||||
#define SU_EXTEND2 (1<<23) // another byte to follow
|
||||
#define SU_WEAPONFRAME2 (1<<24) // 1 byte, this is .weaponframe & 0xFF00 (second byte)
|
||||
#define SU_WEAPONALPHA (1<<25) // 1 byte, this is alpha for weaponmodel, uses ENTALPHA_ENCODE, not sent if ENTALPHA_DEFAULT
|
||||
#define SU_UNUSED26 (1<<26)
|
||||
#define SU_UNUSED27 (1<<27)
|
||||
#define SU_UNUSED28 (1<<28)
|
||||
#define SU_UNUSED29 (1<<29)
|
||||
#define SU_UNUSED30 (1<<30)
|
||||
#define SU_EXTEND3 (1<<31) // another byte to follow, future expansion
|
||||
|
||||
// a sound with no channel is a local-only sound
|
||||
#define SND_VOLUME (1<<0) // a byte
|
||||
#define SND_ATTENUATION (1<<1) // a byte
|
||||
#define SND_LOOPING (1<<2) // a long
|
||||
// PROTOCOL_FITZQUAKE -- new bits
|
||||
#define SND_LARGEENTITY (1<<3) // a short + byte (instead of just a short)
|
||||
#define SND_LARGESOUND (1<<4) // a short soundindex (instead of a byte)
|
||||
#define DEFAULT_SOUND_PACKET_VOLUME 255
|
||||
#define DEFAULT_SOUND_PACKET_ATTENUATION 1.0
|
||||
|
||||
// PROTOCOL_FITZQUAKE -- flags for entity baseline messages
|
||||
#define B_LARGEMODEL (1<<0) // modelindex is short instead of byte
|
||||
#define B_LARGEFRAME (1<<1) // frame is short instead of byte
|
||||
#define B_ALPHA (1<<2) // 1 byte, uses ENTALPHA_ENCODE, not sent if ENTALPHA_DEFAULT
|
||||
|
||||
// PROTOCOL_FITZQUAKE -- alpha encoding
|
||||
#define ENTALPHA_DEFAULT 0 //entity's alpha is "default" (i.e. water obeys r_wateralpha) -- must be zero so zeroed out memory works
|
||||
#define ENTALPHA_ZERO 1 //entity is invisible (lowest possible alpha)
|
||||
#define ENTALPHA_ONE 255 //entity is fully opaque (highest possible alpha)
|
||||
#define ENTALPHA_ENCODE(a) (((a)==0)?ENTALPHA_DEFAULT:RINT(CLAMP(1,(a)*254.0f+1,255))) //server convert to byte to send to client
|
||||
#define ENTALPHA_DECODE(a) (((a)==ENTALPHA_DEFAULT)?1.0f:((float)(a)-1)/(254)) //client convert to float for rendering
|
||||
#define ENTALPHA_TOSAVE(a) (((a)==ENTALPHA_DEFAULT)?0.0f:(((a)==ENTALPHA_ZERO)?-1.0f:((float)(a)-1)/(254))) //server convert to float for savegame
|
||||
|
||||
// defaults for clientinfo messages
|
||||
#define DEFAULT_VIEWHEIGHT 22
|
||||
|
||||
|
@ -156,13 +177,21 @@
|
|||
|
||||
#define svc_spawnstaticsound 29 // [coord3] [byte] samp [byte] vol [byte] aten
|
||||
|
||||
#define svc_intermission 30 // [string] music
|
||||
#define svc_finale 31 // [string] music [string] text
|
||||
#define svc_intermission 30 // [string] music
|
||||
#define svc_finale 31 // [string] music [string] text
|
||||
|
||||
#define svc_cdtrack 32 // [byte] track [byte] looptrack
|
||||
#define svc_sellscreen 33
|
||||
#define svc_cdtrack 32 // [byte] track [byte] looptrack
|
||||
#define svc_sellscreen 33
|
||||
|
||||
#define svc_cutscene 34
|
||||
#define svc_cutscene 34
|
||||
|
||||
// PROTOCOL_FITZQUAKE -- new server messages
|
||||
#define svc_skybox 37 // [string] name
|
||||
#define svc_bf 40
|
||||
#define svc_fog 41 // [byte] density [byte] red [byte] green [byte] blue [float] time
|
||||
#define svc_spawnbaseline2 42 // support for large modelindex, large framenum, alpha, using flags
|
||||
#define svc_spawnstatic2 43 // support for large modelindex, large framenum, alpha, using flags
|
||||
#define svc_spawnstaticsound2 44 // [coord3] [short] samp [byte] vol [byte] aten
|
||||
|
||||
// client to server ===========================================================
|
||||
|
||||
|
@ -199,13 +228,11 @@ typedef struct entity_state_s
|
|||
{
|
||||
vec3_t origin;
|
||||
vec3_t angles;
|
||||
int modelindex;
|
||||
int frame;
|
||||
int colormap;
|
||||
int skin;
|
||||
unsigned short modelindex;
|
||||
unsigned short frame;
|
||||
int effects;
|
||||
|
||||
// LordHavoc: Endy neglected to mark this as a QSG version 2 thingy...
|
||||
byte colormap;
|
||||
byte skin;
|
||||
byte alpha;
|
||||
byte scale;
|
||||
byte glow_size;
|
||||
|
|
|
@ -89,7 +89,9 @@ typedef struct
|
|||
byte reliable_datagram_buf[MAX_DATAGRAM];
|
||||
|
||||
sizebuf_t signon;
|
||||
byte signon_buf[8192];
|
||||
byte signon_buf[MAX_MSGLEN-2];
|
||||
|
||||
unsigned protocol;
|
||||
} server_t;
|
||||
|
||||
|
||||
|
@ -213,6 +215,8 @@ extern struct cvar_s *sv_aim;
|
|||
extern struct cvar_s *sv_friction;
|
||||
extern struct cvar_s *sv_stopspeed;
|
||||
|
||||
extern struct cvar_s *max_edicts;
|
||||
|
||||
extern server_static_t svs; // persistant server info
|
||||
extern server_t sv; // local server
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ kbutton_t in_up, in_down;
|
|||
|
||||
int in_impulse;
|
||||
|
||||
void (*write_angles) (sizebuf_t *sb, const vec3_t angles);
|
||||
|
||||
static void
|
||||
KeyPress (kbutton_t *b)
|
||||
|
@ -555,7 +556,7 @@ CL_SendMove (usercmd_t *cmd)
|
|||
|
||||
MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times
|
||||
|
||||
MSG_WriteAngleV (&buf, cl.viewangles);
|
||||
write_angles (&buf, cl.viewangles);
|
||||
|
||||
MSG_WriteShort (&buf, cmd->forwardmove);
|
||||
MSG_WriteShort (&buf, cmd->sidemove);
|
||||
|
|
|
@ -608,7 +608,7 @@ CL_RelinkEntities (void)
|
|||
CL_NewDlight (i, ent->origin, state->effects);
|
||||
if (VectorDistance_fast (state->msg_origins[1], ent->origin)
|
||||
> (256 * 256))
|
||||
VectorCopy (ent ->origin, state->msg_origins[1]);
|
||||
VectorCopy (ent->origin, state->msg_origins[1]);
|
||||
if (ent->model->flags & EF_ROCKET) {
|
||||
dl = R_AllocDlight (i);
|
||||
if (dl) {
|
||||
|
@ -729,6 +729,10 @@ CL_SetState (cactive_t state)
|
|||
key_dest = key_console;
|
||||
VID_SetCaption ("Disconnected");
|
||||
}
|
||||
if (state == ca_connected)
|
||||
S_AmbientOn ();
|
||||
else
|
||||
S_AmbientOff ();
|
||||
}
|
||||
if (con_module)
|
||||
con_module->data->console->force_commandline = (state != ca_active);
|
||||
|
|
|
@ -43,6 +43,7 @@ static __attribute__ ((used)) const char rcsid[] =
|
|||
#include "QF/cmd.h"
|
||||
#include "QF/console.h"
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/dstring.h"
|
||||
#include "QF/idparse.h"
|
||||
#include "QF/input.h"
|
||||
#include "QF/msg.h"
|
||||
|
@ -50,8 +51,10 @@ static __attribute__ ((used)) const char rcsid[] =
|
|||
#include "QF/screen.h"
|
||||
#include "QF/skin.h"
|
||||
#include "QF/sound.h" // FIXME: DEFAULT_SOUND_PACKET_*
|
||||
#include "QF/va.h"
|
||||
|
||||
#include "client.h"
|
||||
#include "compat.h"
|
||||
#include "host.h"
|
||||
#include "sbar.h"
|
||||
#include "server.h"
|
||||
|
@ -100,11 +103,24 @@ const char *svc_strings[] = {
|
|||
"svc_finale", // [string] music [string] text
|
||||
"svc_cdtrack", // [byte] track [byte] looptrack
|
||||
"svc_sellscreen",
|
||||
"svc_cutscene"
|
||||
"svc_cutscene",
|
||||
// end of iD svc
|
||||
// FIXME switchable extensions?
|
||||
// protocol 666
|
||||
"",
|
||||
"",
|
||||
"svc_skybox",
|
||||
"",
|
||||
"",
|
||||
"svc_bf",
|
||||
"svc_fog",
|
||||
"svc_spawnbaseline2",
|
||||
"svc_spawnstatic2",
|
||||
"svc_spawnstaticsound2",
|
||||
};
|
||||
|
||||
float r_gravity;
|
||||
|
||||
dstring_t *centerprint;
|
||||
|
||||
/*
|
||||
CL_EntityNum
|
||||
|
@ -114,9 +130,9 @@ float r_gravity;
|
|||
static cl_entity_state_t *
|
||||
CL_EntityNum (int num)
|
||||
{
|
||||
if (num < 0 || num >= MAX_EDICTS)
|
||||
Host_Error ("CL_EntityNum: %i is an invalid number", num);
|
||||
if (num >= cl.num_entities) {
|
||||
if (num >= MAX_EDICTS)
|
||||
Host_Error ("CL_EntityNum: %i is an invalid number", num);
|
||||
while (cl.num_entities <= num) {
|
||||
cl_baselines[cl.num_entities].ent =
|
||||
&cl_entities[cl.num_entities];
|
||||
|
@ -147,12 +163,22 @@ CL_ParseStartSoundPacket (void)
|
|||
else
|
||||
attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
|
||||
|
||||
channel = MSG_ReadShort (net_message);
|
||||
sound_num = MSG_ReadByte (net_message);
|
||||
if (field_mask & SND_LARGEENTITY) {
|
||||
ent = (uint16_t) MSG_ReadShort (net_message);
|
||||
channel = MSG_ReadByte (net_message);
|
||||
} else {
|
||||
channel = (uint16_t) MSG_ReadShort (net_message);
|
||||
ent = channel >> 3;
|
||||
channel &= 7;
|
||||
}
|
||||
|
||||
ent = channel >> 3;
|
||||
channel &= 7;
|
||||
if (field_mask & SND_LARGESOUND)
|
||||
sound_num = (uint16_t) MSG_ReadShort (net_message);
|
||||
else
|
||||
sound_num = MSG_ReadByte (net_message);
|
||||
|
||||
if (sound_num >= MAX_SOUNDS)
|
||||
Host_Error ("CL_ParseStartSoundPacket: %i > MAX_SOUNDS", sound_num);
|
||||
if (ent > MAX_EDICTS)
|
||||
Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
|
||||
|
||||
|
@ -275,10 +301,16 @@ CL_ParseServerInfo (void)
|
|||
|
||||
// parse protocol version number
|
||||
i = MSG_ReadLong (net_message);
|
||||
if (i != PROTOCOL_VERSION) {
|
||||
Sys_Printf ("Server returned version %i, not %i", i, PROTOCOL_VERSION);
|
||||
if (i != PROTOCOL_NETQUAKE && i!= PROTOCOL_FITZQUAKE) {
|
||||
Sys_Printf ("Server returned version %i, not %i or %i\n", i,
|
||||
PROTOCOL_NETQUAKE, PROTOCOL_FITZQUAKE);
|
||||
goto done;
|
||||
}
|
||||
cl.protocol = i;
|
||||
if (cl.protocol == PROTOCOL_FITZQUAKE)
|
||||
write_angles = MSG_WriteAngle16V;
|
||||
else
|
||||
write_angles = MSG_WriteAngleV;
|
||||
// parse maxclients
|
||||
cl.maxclients = MSG_ReadByte (net_message);
|
||||
if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD) {
|
||||
|
@ -351,6 +383,10 @@ CL_ParseServerInfo (void)
|
|||
|
||||
// local state
|
||||
cl_entities[0].model = cl.worldmodel = cl.model_precache[1];
|
||||
if (!centerprint)
|
||||
centerprint = dstring_newstr ();
|
||||
else
|
||||
dstring_clearstr (centerprint);
|
||||
CL_NewMap (model_precache[1]);
|
||||
|
||||
Hunk_Check (); // make sure nothing is hurt
|
||||
|
@ -389,6 +425,13 @@ CL_ParseUpdate (int bits)
|
|||
i = MSG_ReadByte (net_message);
|
||||
bits |= (i << 8);
|
||||
}
|
||||
|
||||
if (cl.protocol == PROTOCOL_FITZQUAKE) {
|
||||
if (bits & U_EXTEND1)
|
||||
bits |= MSG_ReadByte(net_message) << 16;
|
||||
if (bits & U_EXTEND2)
|
||||
bits |= MSG_ReadByte(net_message) << 24;
|
||||
}
|
||||
|
||||
if (bits & U_LONGENTITY)
|
||||
num = MSG_ReadShort (net_message);
|
||||
|
@ -422,26 +465,6 @@ CL_ParseUpdate (int bits)
|
|||
} else
|
||||
modnum = state->baseline.modelindex;
|
||||
|
||||
model = cl.model_precache[modnum];
|
||||
if (model != ent->model) {
|
||||
ent->model = model;
|
||||
// automatic animation (torches, etc) can be either all together
|
||||
// or randomized
|
||||
if (model) {
|
||||
if (model->synctype == ST_RAND)
|
||||
ent->syncbase = (float) (rand () & 0x7fff) / 0x7fff;
|
||||
else
|
||||
ent->syncbase = 0.0;
|
||||
} else
|
||||
forcelink = true; // hack to make null model players work
|
||||
if (num > 0 && num <= cl.maxclients) {
|
||||
if (!ent->skin)
|
||||
ent->skin = Skin_NewTempSkin ();
|
||||
if (ent->skin)
|
||||
CL_NewTranslation (num - 1, ent->skin);
|
||||
}
|
||||
}
|
||||
|
||||
if (bits & U_FRAME)
|
||||
ent->frame = MSG_ReadByte (net_message);
|
||||
else
|
||||
|
@ -509,50 +532,49 @@ CL_ParseUpdate (int bits)
|
|||
else
|
||||
state->msg_angles[0][2] = state->baseline.angles[2];
|
||||
|
||||
if (bits & U_NOLERP)
|
||||
if (bits & U_STEP) //FIXME lerping (see fitzquake)
|
||||
forcelink = true;
|
||||
|
||||
// QSG Start
|
||||
if (bits & U_ALPHA)
|
||||
state->alpha = MSG_ReadByte (net_message);
|
||||
else
|
||||
if (cl.protocol == PROTOCOL_FITZQUAKE) {
|
||||
if (bits & U_ALPHA)
|
||||
state->alpha = MSG_ReadByte(net_message);
|
||||
else
|
||||
state->alpha = state->baseline.alpha;
|
||||
if (bits & U_FRAME2)
|
||||
ent->frame |= MSG_ReadByte(net_message) << 8;
|
||||
if (bits & U_MODEL2)
|
||||
modnum |= MSG_ReadByte(net_message) << 8;
|
||||
if (bits & U_LERPFINISH) {
|
||||
MSG_ReadByte (net_message); //FIXME ignored for now. see fitzquake
|
||||
}
|
||||
} else {
|
||||
state->alpha = state->baseline.alpha;
|
||||
|
||||
if (bits & U_SCALE)
|
||||
state->scale = MSG_ReadByte (net_message);
|
||||
else
|
||||
state->scale = state->baseline.scale;
|
||||
|
||||
if (bits & U_EFFECTS2)
|
||||
state->effects = (state->effects & 0xFF) |
|
||||
(MSG_ReadByte (net_message) << 8);
|
||||
|
||||
if (bits & U_GLOWSIZE)
|
||||
state->glow_size = MSG_ReadByte (net_message);
|
||||
else
|
||||
state->glow_size = state->baseline.glow_size;
|
||||
|
||||
if (bits & U_GLOWCOLOR)
|
||||
state->glow_color = MSG_ReadByte (net_message);
|
||||
else
|
||||
state->glow_color = state->baseline.glow_color;
|
||||
|
||||
if (bits & U_COLORMOD)
|
||||
state->colormod = MSG_ReadByte (net_message);
|
||||
else
|
||||
state->colormod = state->baseline.colormod;
|
||||
}
|
||||
|
||||
if (!(bits & U_EXTEND2))
|
||||
goto link;
|
||||
model = cl.model_precache[modnum];
|
||||
if (model != ent->model) {
|
||||
ent->model = model;
|
||||
// automatic animation (torches, etc) can be either all together
|
||||
// or randomized
|
||||
if (model) {
|
||||
if (model->synctype == ST_RAND)
|
||||
ent->syncbase = (float) (rand () & 0x7fff) / 0x7fff;
|
||||
else
|
||||
ent->syncbase = 0.0;
|
||||
} else
|
||||
forcelink = true; // hack to make null model players work
|
||||
if (num > 0 && num <= cl.maxclients) {
|
||||
if (!ent->skin)
|
||||
ent->skin = Skin_NewTempSkin ();
|
||||
if (ent->skin)
|
||||
CL_NewTranslation (num - 1, ent->skin);
|
||||
}
|
||||
}
|
||||
|
||||
if (bits & U_GLOWTRAIL)
|
||||
state->effects |= EF_GLOWTRAIL;
|
||||
|
||||
if (bits & U_FRAME2)
|
||||
ent->frame = (ent->frame & 0xFF) | (MSG_ReadByte (net_message) << 8);
|
||||
// QSG End
|
||||
|
||||
link:
|
||||
if (forcelink) { // didn't have an update last message
|
||||
VectorCopy (state->msg_origins[0], state->msg_origins[1]);
|
||||
VectorCopy (state->msg_origins[0], ent->origin);
|
||||
|
@ -563,18 +585,33 @@ link:
|
|||
}
|
||||
|
||||
static void
|
||||
CL_ParseBaseline (cl_entity_state_t *state)
|
||||
CL_ParseBaseline (cl_entity_state_t *state, int version)
|
||||
{
|
||||
state->baseline.modelindex = MSG_ReadByte (net_message);
|
||||
state->baseline.frame = MSG_ReadByte (net_message);
|
||||
int bits = 0;
|
||||
|
||||
if (version == 2)
|
||||
bits = MSG_ReadByte (net_message);
|
||||
|
||||
if (bits & B_LARGEMODEL)
|
||||
state->baseline.modelindex = MSG_ReadShort (net_message);
|
||||
else
|
||||
state->baseline.modelindex = MSG_ReadByte (net_message);
|
||||
|
||||
if (bits & B_LARGEFRAME)
|
||||
state->baseline.frame = MSG_ReadShort (net_message);
|
||||
else
|
||||
state->baseline.frame = MSG_ReadByte (net_message);
|
||||
|
||||
state->baseline.colormap = MSG_ReadByte (net_message);
|
||||
state->baseline.skin = MSG_ReadByte (net_message);
|
||||
|
||||
MSG_ReadCoordAngleV (net_message, state->baseline.origin,
|
||||
state->baseline.angles);
|
||||
|
||||
// LordHavoc: set up baseline for new effects (alpha, colormod, etc)
|
||||
state->baseline.alpha = 255;
|
||||
if (bits & B_ALPHA)
|
||||
state->baseline.alpha = MSG_ReadByte (net_message);
|
||||
else
|
||||
state->baseline.alpha = 255;//FIXME alpha
|
||||
state->baseline.scale = 16;
|
||||
state->baseline.glow_size = 0;
|
||||
state->baseline.glow_color = 254;
|
||||
|
@ -587,9 +624,16 @@ CL_ParseBaseline (cl_entity_state_t *state)
|
|||
Server information pertaining to only this client
|
||||
*/
|
||||
static void
|
||||
CL_ParseClientdata (int bits)
|
||||
CL_ParseClientdata (void)
|
||||
{
|
||||
int i, j;
|
||||
int bits;
|
||||
|
||||
bits = (uint16_t) MSG_ReadShort (net_message);
|
||||
if (bits & SU_EXTEND1)
|
||||
bits |= MSG_ReadByte (net_message) << 16;
|
||||
if (bits & SU_EXTEND2)
|
||||
bits |= MSG_ReadByte (net_message) << 24;
|
||||
|
||||
if (bits & SU_VIEWHEIGHT)
|
||||
cl.viewheight = ((signed char) MSG_ReadByte (net_message));
|
||||
|
@ -614,6 +658,12 @@ CL_ParseClientdata (int bits)
|
|||
cl.mvelocity[0][i] = 0;
|
||||
}
|
||||
|
||||
//FIXME
|
||||
//if (!VectorCompare (v_punchangles[0], cl.punchangle[0])) {
|
||||
// VectorCopy (v_punchangles[0], v_punchangles[1]);
|
||||
// VectorCopy (cl.punchangle, v_punchangles[0]);
|
||||
//}
|
||||
|
||||
// [always sent] if (bits & SU_ITEMS)
|
||||
i = MSG_ReadLong (net_message);
|
||||
|
||||
|
@ -684,10 +734,33 @@ CL_ParseClientdata (int bits)
|
|||
Sbar_Changed ();
|
||||
}
|
||||
}
|
||||
|
||||
if (bits & SU_WEAPON2)
|
||||
cl.stats[STAT_WEAPON] |= MSG_ReadByte (net_message) << 8;
|
||||
if (bits & SU_ARMOR2)
|
||||
cl.stats[STAT_ARMOR] |= MSG_ReadByte (net_message) << 8;
|
||||
if (bits & SU_AMMO2)
|
||||
cl.stats[STAT_AMMO] |= MSG_ReadByte (net_message) << 8;
|
||||
if (bits & SU_SHELLS2)
|
||||
cl.stats[STAT_SHELLS] |= MSG_ReadByte (net_message) << 8;
|
||||
if (bits & SU_NAILS2)
|
||||
cl.stats[STAT_NAILS] |= MSG_ReadByte (net_message) << 8;
|
||||
if (bits & SU_ROCKETS2)
|
||||
cl.stats[STAT_ROCKETS] |= MSG_ReadByte (net_message) << 8;
|
||||
if (bits & SU_CELLS2)
|
||||
cl.stats[STAT_CELLS] |= MSG_ReadByte (net_message) << 8;
|
||||
if (bits & SU_WEAPONFRAME2)
|
||||
cl.stats[STAT_WEAPONFRAME] |= MSG_ReadByte (net_message) << 8;
|
||||
if (bits & SU_WEAPONALPHA) {
|
||||
byte alpha = MSG_ReadByte (net_message);
|
||||
cl.viewent.colormod[3] = ENTALPHA_DECODE (alpha);
|
||||
} else {
|
||||
cl.viewent.colormod[3] = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
CL_ParseStatic (void)
|
||||
CL_ParseStatic (int version)
|
||||
{
|
||||
cl_entity_state_t state;
|
||||
entity_t *ent;
|
||||
|
@ -698,11 +771,12 @@ CL_ParseStatic (void)
|
|||
Host_Error ("Too many static entities");
|
||||
ent = &cl_static_entities[i];
|
||||
cl.num_statics++;
|
||||
CL_ParseBaseline (&state);
|
||||
CL_ParseBaseline (&state, version);
|
||||
|
||||
// copy it to the current state
|
||||
VectorCopy (state.baseline.origin, ent->origin);
|
||||
VectorCopy (state.baseline.angles, ent->angles);
|
||||
//FIXME alpha & lerp
|
||||
ent->model = cl.model_precache[state.baseline.modelindex];
|
||||
ent->frame = state.baseline.frame;
|
||||
ent->colormap = vid.colormap8;
|
||||
|
@ -717,20 +791,23 @@ CL_ParseStatic (void)
|
|||
ent->colormod[2] = ((float) (state.baseline.colormod & 3)) *
|
||||
(1.0 / 3.0);
|
||||
}
|
||||
ent->colormod[3] = state.baseline.alpha / 255.0;
|
||||
ent->colormod[3] = ENTALPHA_DECODE (state.baseline.alpha);
|
||||
ent->scale = state.baseline.scale / 16.0;
|
||||
|
||||
R_AddEfrags (ent);
|
||||
}
|
||||
|
||||
static void
|
||||
CL_ParseStaticSound (void)
|
||||
CL_ParseStaticSound (int version)
|
||||
{
|
||||
int sound_num, vol, atten;
|
||||
vec3_t org;
|
||||
|
||||
MSG_ReadCoordV (net_message, org);
|
||||
sound_num = MSG_ReadByte (net_message);
|
||||
if (version == 2)
|
||||
sound_num = MSG_ReadShort (net_message);
|
||||
else
|
||||
sound_num = MSG_ReadByte (net_message);
|
||||
vol = MSG_ReadByte (net_message);
|
||||
atten = MSG_ReadByte (net_message);
|
||||
|
||||
|
@ -747,6 +824,7 @@ void
|
|||
CL_ParseServerMessage (void)
|
||||
{
|
||||
int cmd, i;
|
||||
const char *str;
|
||||
|
||||
// if recording demos, copy the message out
|
||||
if (cl_shownet->int_val == 1)
|
||||
|
@ -770,13 +848,13 @@ CL_ParseServerMessage (void)
|
|||
return; // end of message
|
||||
}
|
||||
// if the high bit of the command byte is set, it is a fast update
|
||||
if (cmd & 128) {
|
||||
if (cmd & U_SIGNAL) {
|
||||
SHOWNET ("fast update");
|
||||
CL_ParseUpdate (cmd & 127);
|
||||
CL_ParseUpdate (cmd & ~U_SIGNAL);
|
||||
continue;
|
||||
}
|
||||
|
||||
SHOWNET (svc_strings[cmd]);
|
||||
SHOWNET (va ("%s(%d)", svc_strings[cmd], cmd));
|
||||
|
||||
// other commands
|
||||
switch (cmd) {
|
||||
|
@ -794,15 +872,16 @@ CL_ParseServerMessage (void)
|
|||
break;
|
||||
|
||||
case svc_clientdata:
|
||||
i = MSG_ReadShort (net_message);
|
||||
CL_ParseClientdata (i);
|
||||
CL_ParseClientdata ();
|
||||
break;
|
||||
|
||||
case svc_version:
|
||||
i = MSG_ReadLong (net_message);
|
||||
if (i != PROTOCOL_VERSION)
|
||||
if (i != PROTOCOL_NETQUAKE && i!= PROTOCOL_FITZQUAKE)
|
||||
Host_Error ("CL_ParseServerMessage: Server is protocol %i "
|
||||
"instead of %i\n", i, PROTOCOL_VERSION);
|
||||
"instead of %i or %i\n", i, PROTOCOL_NETQUAKE,
|
||||
PROTOCOL_FITZQUAKE);
|
||||
cl.protocol = i;
|
||||
break;
|
||||
|
||||
case svc_disconnect:
|
||||
|
@ -813,7 +892,12 @@ CL_ParseServerMessage (void)
|
|||
break;
|
||||
|
||||
case svc_centerprint:
|
||||
Sbar_CenterPrint (MSG_ReadString (net_message));
|
||||
str = MSG_ReadString (net_message);
|
||||
if (strcmp (str, centerprint->str)) {
|
||||
dstring_copystr (centerprint, str);
|
||||
//FIXME logging
|
||||
}
|
||||
Sbar_CenterPrint (str);
|
||||
break;
|
||||
|
||||
case svc_stufftext:
|
||||
|
@ -844,6 +928,7 @@ CL_ParseServerMessage (void)
|
|||
Sys_Error ("svc_lightstyle > MAX_LIGHTSTYLES");
|
||||
strcpy (r_lightstyle[i].map, MSG_ReadString (net_message));
|
||||
r_lightstyle[i].length = strlen (r_lightstyle[i].map);
|
||||
// FIXME extra info
|
||||
break;
|
||||
|
||||
case svc_sound:
|
||||
|
@ -896,10 +981,10 @@ CL_ParseServerMessage (void)
|
|||
case svc_spawnbaseline:
|
||||
i = MSG_ReadShort (net_message);
|
||||
// must use CL_EntityNum () to force cl.num_entities up
|
||||
CL_ParseBaseline (CL_EntityNum (i));
|
||||
CL_ParseBaseline (CL_EntityNum (i), 1);
|
||||
break;
|
||||
case svc_spawnstatic:
|
||||
CL_ParseStatic ();
|
||||
CL_ParseStatic (1);
|
||||
break;
|
||||
case svc_temp_entity:
|
||||
CL_ParseTEnt ();
|
||||
|
@ -942,7 +1027,7 @@ CL_ParseServerMessage (void)
|
|||
break;
|
||||
|
||||
case svc_spawnstaticsound:
|
||||
CL_ParseStaticSound ();
|
||||
CL_ParseStaticSound (1);
|
||||
break;
|
||||
|
||||
case svc_cdtrack:
|
||||
|
@ -967,7 +1052,12 @@ CL_ParseServerMessage (void)
|
|||
r_force_fullscreen = 1;
|
||||
cl.completed_time = cl.time;
|
||||
vid.recalc_refdef = true; // go to full screen
|
||||
Sbar_CenterPrint (MSG_ReadString (net_message));
|
||||
str = MSG_ReadString (net_message);
|
||||
if (strcmp (str, centerprint->str)) {
|
||||
dstring_copystr (centerprint, str);
|
||||
//FIXME logging
|
||||
}
|
||||
Sbar_CenterPrint (str);
|
||||
break;
|
||||
|
||||
case svc_cutscene:
|
||||
|
@ -975,12 +1065,47 @@ CL_ParseServerMessage (void)
|
|||
r_force_fullscreen = 1;
|
||||
cl.completed_time = cl.time;
|
||||
vid.recalc_refdef = true; // go to full screen
|
||||
Sbar_CenterPrint (MSG_ReadString (net_message));
|
||||
str = MSG_ReadString (net_message);
|
||||
if (strcmp (str, centerprint->str)) {
|
||||
dstring_copystr (centerprint, str);
|
||||
//FIXME logging
|
||||
}
|
||||
Sbar_CenterPrint (str);
|
||||
break;
|
||||
|
||||
case svc_sellscreen:
|
||||
Cmd_ExecuteString ("help", src_command);
|
||||
break;
|
||||
|
||||
// PROTOCOL_FITZQUAKE
|
||||
case svc_skybox:
|
||||
R_LoadSkys (MSG_ReadString(net_message));
|
||||
break;
|
||||
case svc_bf:
|
||||
Cmd_ExecuteString ("bf", src_command);
|
||||
break;
|
||||
case svc_fog:
|
||||
{ //FIXME implement
|
||||
float density, red, green, blue, time;
|
||||
density = MSG_ReadByte (net_message) / 255.0;
|
||||
red = MSG_ReadByte (net_message) / 255.0;
|
||||
green = MSG_ReadByte (net_message) / 255.0;
|
||||
blue = MSG_ReadByte (net_message) / 255.0;
|
||||
time = MSG_ReadShort (net_message) / 100.0;
|
||||
time = max (0.0, time);
|
||||
}
|
||||
break;
|
||||
case svc_spawnbaseline2:
|
||||
i = MSG_ReadShort (net_message);
|
||||
// must use CL_EntityNum() to force cl.num_entities up
|
||||
CL_ParseBaseline (CL_EntityNum(i), 2);
|
||||
break;
|
||||
case svc_spawnstatic2:
|
||||
CL_ParseStatic (2);
|
||||
break;
|
||||
case svc_spawnstaticsound2:
|
||||
CL_ParseStaticSound (2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,6 +112,7 @@ cvar_t *host_mem_size;
|
|||
|
||||
cvar_t *host_framerate;
|
||||
cvar_t *host_speeds;
|
||||
cvar_t *max_edicts;
|
||||
|
||||
cvar_t *sys_ticrate;
|
||||
cvar_t *serverprofile;
|
||||
|
@ -258,6 +259,8 @@ Host_InitLocal (void)
|
|||
host_speeds =
|
||||
Cvar_Get ("host_speeds", "0", CVAR_NONE, NULL,
|
||||
"set for running times");
|
||||
max_edicts = Cvar_Get ("max_edicts", "1024", CVAR_NONE, NULL,
|
||||
"maximum server edicts");
|
||||
|
||||
sys_ticrate = Cvar_Get ("sys_ticrate", "0.05", CVAR_NONE, NULL, "None");
|
||||
serverprofile = Cvar_Get ("serverprofile", "0", CVAR_NONE, NULL, "None");
|
||||
|
|
|
@ -49,8 +49,36 @@ server_static_t svs;
|
|||
|
||||
char localmodels[MAX_MODELS][5]; // inline model names for precache
|
||||
|
||||
int sv_protocol = PROTOCOL_FITZQUAKE;
|
||||
|
||||
entity_state_t baselines[MAX_EDICTS];
|
||||
|
||||
static void
|
||||
SV_Protocol_f (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
switch (Cmd_Argc ()) {
|
||||
case 1:
|
||||
Sys_Printf ("\"sv_protocol\" is \"%i\"\n", sv_protocol);
|
||||
break;
|
||||
case 2:
|
||||
i = atoi (Cmd_Argv (1));
|
||||
if (i != PROTOCOL_NETQUAKE && i != PROTOCOL_FITZQUAKE) {
|
||||
Sys_Printf ("sv_protocol must be %i or %i\n",
|
||||
PROTOCOL_NETQUAKE, PROTOCOL_FITZQUAKE);
|
||||
} else {
|
||||
sv_protocol = i;
|
||||
if (sv.active)
|
||||
Sys_Printf ("changes will not take effect until the next "
|
||||
"level load.\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Sys_Printf ("usage: sv_protocol <protocol>\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SV_Init (void)
|
||||
|
@ -73,6 +101,9 @@ SV_Init (void)
|
|||
sv_aim = Cvar_Get ("sv_aim", "0.93", CVAR_NONE, NULL, "None");
|
||||
sv_nostep = Cvar_Get ("sv_nostep", "0", CVAR_NONE, NULL, "None");
|
||||
|
||||
Cmd_AddCommand ("sv_protocol", SV_Protocol_f, "set the protocol to be "
|
||||
"used after the next map load");
|
||||
|
||||
for (i = 0; i < MAX_MODELS; i++)
|
||||
snprintf (localmodels[i], sizeof (localmodels[i]), "*%i", i);
|
||||
}
|
||||
|
@ -149,14 +180,25 @@ SV_StartSound (edict_t *entity, int channel, const char *sample, int volume,
|
|||
|
||||
ent = NUM_FOR_EDICT (&sv_pr_state, entity);
|
||||
|
||||
channel = (ent << 3) | channel;
|
||||
|
||||
field_mask = 0;
|
||||
if (volume != DEFAULT_SOUND_PACKET_VOLUME)
|
||||
field_mask |= SND_VOLUME;
|
||||
if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
|
||||
field_mask |= SND_ATTENUATION;
|
||||
|
||||
if (ent >= 8192) {
|
||||
if (sv.protocol == PROTOCOL_NETQUAKE)
|
||||
return; //don't send any info protocol can't support
|
||||
else
|
||||
field_mask |= SND_LARGEENTITY;
|
||||
}
|
||||
if (sound_num >= 256 || channel >= 8) {
|
||||
if (sv.protocol == PROTOCOL_NETQUAKE)
|
||||
return; //don't send any info protocol can't support
|
||||
else
|
||||
field_mask |= SND_LARGESOUND;
|
||||
}
|
||||
|
||||
// directed messages go to only the entity on which they are targeted
|
||||
MSG_WriteByte (&sv.datagram, svc_sound);
|
||||
MSG_WriteByte (&sv.datagram, field_mask);
|
||||
|
@ -164,8 +206,18 @@ SV_StartSound (edict_t *entity, int channel, const char *sample, int volume,
|
|||
MSG_WriteByte (&sv.datagram, volume);
|
||||
if (field_mask & SND_ATTENUATION)
|
||||
MSG_WriteByte (&sv.datagram, attenuation * 64);
|
||||
MSG_WriteShort (&sv.datagram, channel);
|
||||
MSG_WriteByte (&sv.datagram, sound_num);
|
||||
|
||||
if (field_mask & SND_LARGEENTITY) {
|
||||
MSG_WriteShort (&sv.datagram, ent);
|
||||
MSG_WriteByte (&sv.datagram, channel);
|
||||
} else {
|
||||
MSG_WriteShort (&sv.datagram, (ent << 3 | channel));
|
||||
}
|
||||
if (field_mask & SND_LARGESOUND)
|
||||
MSG_WriteShort (&sv.datagram, sound_num);
|
||||
else
|
||||
MSG_WriteByte (&sv.datagram, sound_num);
|
||||
|
||||
VectorBlend (SVvector (entity, mins), SVvector (entity, maxs), 0.5, v);
|
||||
VectorAdd (v, SVvector (entity, origin), v);
|
||||
MSG_WriteCoordV (&sv.datagram, v);
|
||||
|
@ -184,6 +236,7 @@ SV_SendServerinfo (client_t *client)
|
|||
{
|
||||
const char **s;
|
||||
char message[2048];
|
||||
int i;
|
||||
|
||||
MSG_WriteByte (&client->message, svc_print);
|
||||
snprintf (message, sizeof (message), "%c\nVersion %s server (%i CRC)", 2,
|
||||
|
@ -191,7 +244,7 @@ SV_SendServerinfo (client_t *client)
|
|||
MSG_WriteString (&client->message, message);
|
||||
|
||||
MSG_WriteByte (&client->message, svc_serverinfo);
|
||||
MSG_WriteLong (&client->message, PROTOCOL_VERSION);
|
||||
MSG_WriteLong (&client->message, sv.protocol);
|
||||
MSG_WriteByte (&client->message, svs.maxclients);
|
||||
|
||||
if (!coop->int_val && deathmatch->int_val)
|
||||
|
@ -201,15 +254,19 @@ SV_SendServerinfo (client_t *client)
|
|||
|
||||
snprintf (message, sizeof (message), "%s",
|
||||
PR_GetString (&sv_pr_state, SVstring (sv.edicts, message)));
|
||||
message[sizeof (message) - 1] = 0;
|
||||
|
||||
MSG_WriteString (&client->message, message);
|
||||
|
||||
for (s = sv.model_precache + 1; *s; s++)
|
||||
MSG_WriteString (&client->message, *s);
|
||||
// send only the first 256 model and sound precaches if protocol 15
|
||||
for (i = 0, s = sv.model_precache + 1; *s; s++, i++)
|
||||
if (sv.protocol != PROTOCOL_NETQUAKE || i < 256)
|
||||
MSG_WriteString (&client->message, *s);
|
||||
MSG_WriteByte (&client->message, 0);
|
||||
|
||||
for (s = sv.sound_precache + 1; *s; s++)
|
||||
MSG_WriteString (&client->message, *s);
|
||||
for (i = 0, s = sv.sound_precache + 1; *s; s++, i++)
|
||||
if (sv.protocol != PROTOCOL_NETQUAKE || i < 256)
|
||||
MSG_WriteString (&client->message, *s);
|
||||
MSG_WriteByte (&client->message, 0);
|
||||
|
||||
// send music
|
||||
|
@ -385,6 +442,7 @@ SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg)
|
|||
float miss;
|
||||
vec3_t org;
|
||||
edict_t *ent;
|
||||
entity_state_t *baseline;
|
||||
|
||||
// find the client's PVS
|
||||
VectorAdd (SVvector (clent, origin), SVvector (clent, view_ofs), org);
|
||||
|
@ -393,6 +451,8 @@ SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg)
|
|||
// send over all entities (excpet the client) that touch the pvs
|
||||
ent = NEXT_EDICT (&sv_pr_state, sv.edicts);
|
||||
for (e = 1; e < sv.num_edicts; e++, ent = NEXT_EDICT (&sv_pr_state, ent)) {
|
||||
baseline = (entity_state_t*) ent->data;
|
||||
|
||||
// ignore if not touching a PV leaf
|
||||
if (ent != clent) { // clent is ALWAYS sent
|
||||
// ignore ents without visible models
|
||||
|
@ -400,6 +460,11 @@ SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg)
|
|||
!*PR_GetString (&sv_pr_state, SVstring (ent, model)))
|
||||
continue;
|
||||
|
||||
// don't send model > 255 for protocol 15
|
||||
if (sv.protocol == PROTOCOL_NETQUAKE
|
||||
&& (int) SVfloat (ent, modelindex) & 0xFF00)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < ent->num_leafs; i++)
|
||||
if (pvs[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i] & 7)))
|
||||
break;
|
||||
|
@ -408,51 +473,79 @@ SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg)
|
|||
continue; // not visible
|
||||
}
|
||||
|
||||
if (msg->maxsize - msg->cursize < 16) {
|
||||
if (msg->cursize + 24 > msg->maxsize) {
|
||||
Sys_Printf ("packet overflow\n");
|
||||
return;
|
||||
}
|
||||
// send an update
|
||||
bits = 0;
|
||||
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
miss = SVvector (ent, origin)[i] -
|
||||
((entity_state_t*)ent->data)->origin[i];
|
||||
miss = SVvector (ent, origin)[i] - baseline->origin[i];
|
||||
if (miss < -0.1 || miss > 0.1)
|
||||
bits |= U_ORIGIN1 << i;
|
||||
}
|
||||
|
||||
if (SVvector (ent, angles)[0] !=
|
||||
((entity_state_t*)ent->data)->angles[0])
|
||||
if (SVvector (ent, angles)[0] != baseline->angles[0])
|
||||
bits |= U_ANGLE1;
|
||||
|
||||
if (SVvector (ent, angles)[1] !=
|
||||
((entity_state_t*)ent->data)->angles[1])
|
||||
if (SVvector (ent, angles)[1] != baseline->angles[1])
|
||||
bits |= U_ANGLE2;
|
||||
|
||||
if (SVvector (ent, angles)[2] !=
|
||||
((entity_state_t*)ent->data)->angles[2])
|
||||
if (SVvector (ent, angles)[2] != baseline->angles[2])
|
||||
bits |= U_ANGLE3;
|
||||
|
||||
if (SVfloat (ent, movetype) == MOVETYPE_STEP)
|
||||
bits |= U_NOLERP; // don't mess up the step animation
|
||||
bits |= U_STEP; // don't mess up the step animation
|
||||
|
||||
if (((entity_state_t*)ent->data)->colormap != SVfloat (ent, colormap))
|
||||
if (baseline->colormap != SVfloat (ent, colormap))
|
||||
bits |= U_COLORMAP;
|
||||
|
||||
if (((entity_state_t*)ent->data)->skin != SVfloat (ent, skin))
|
||||
if (baseline->skin != SVfloat (ent, skin))
|
||||
bits |= U_SKIN;
|
||||
|
||||
if (((entity_state_t*)ent->data)->frame != SVfloat (ent, frame))
|
||||
if (baseline->frame != SVfloat (ent, frame))
|
||||
bits |= U_FRAME;
|
||||
|
||||
if (((entity_state_t*)ent->data)->effects != SVfloat (ent, effects))
|
||||
if (baseline->effects != SVfloat (ent, effects))
|
||||
bits |= U_EFFECTS;
|
||||
|
||||
if (((entity_state_t*)ent->data)->modelindex != SVfloat (ent,
|
||||
modelindex))
|
||||
if (baseline->modelindex != SVfloat (ent, modelindex))
|
||||
bits |= U_MODEL;
|
||||
|
||||
#if 0
|
||||
//FIXME finish porting to QF
|
||||
if (pr_alpha_supported) {
|
||||
// TODO: find a cleaner place to put this code
|
||||
eval_t *val;
|
||||
val = GetEdictFieldValue(ent, "alpha");
|
||||
if (val)
|
||||
ent->alpha = ENTALPHA_ENCODE(val->_float);
|
||||
}
|
||||
|
||||
//don't send invisible entities unless they have effects
|
||||
if (ent->alpha == ENTALPHA_ZERO && !ent->v.effects)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
if (sv.protocol != PROTOCOL_NETQUAKE) {
|
||||
//FIXME
|
||||
//if (ent->baseline.alpha != ent->alpha)
|
||||
// bits |= U_ALPHA;
|
||||
if (bits & U_FRAME && (int) SVfloat (ent, frame) & 0xFF00)
|
||||
bits |= U_FRAME2;
|
||||
if (bits & U_MODEL && (int) SVfloat (ent, modelindex) & 0xFF00)
|
||||
bits |= U_MODEL2;
|
||||
//if (ent->sendinterval) FIXME
|
||||
// bits |= U_LERPFINISH;
|
||||
if (bits >= 65536)
|
||||
bits |= U_EXTEND1;
|
||||
if (bits >= 16777216)
|
||||
bits |= U_EXTEND2;
|
||||
}
|
||||
|
||||
|
||||
if (e >= 256)
|
||||
bits |= U_LONGENTITY;
|
||||
|
||||
|
@ -464,6 +557,11 @@ SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg)
|
|||
|
||||
if (bits & U_MOREBITS)
|
||||
MSG_WriteByte (msg, bits >> 8);
|
||||
if (bits & U_EXTEND1)
|
||||
MSG_WriteByte (msg, bits >> 16);
|
||||
if (bits & U_EXTEND2)
|
||||
MSG_WriteByte (msg, bits >> 24);
|
||||
|
||||
if (bits & U_LONGENTITY)
|
||||
MSG_WriteShort (msg, e);
|
||||
else
|
||||
|
@ -491,6 +589,16 @@ SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg)
|
|||
MSG_WriteCoord (msg, SVvector (ent, origin)[2]);
|
||||
if (bits & U_ANGLE3)
|
||||
MSG_WriteAngle (msg, SVvector (ent, angles)[2]);
|
||||
|
||||
//FIXME
|
||||
//if (bits & U_ALPHA)
|
||||
// MSG_WriteByte(msg, ent->alpha);
|
||||
if (bits & U_FRAME2)
|
||||
MSG_WriteByte(msg, (int) SVfloat (ent, frame) >> 8);
|
||||
if (bits & U_MODEL2)
|
||||
MSG_WriteByte(msg, (int) SVfloat (ent, modelindex) >> 8);
|
||||
if (bits & U_LERPFINISH)
|
||||
MSG_WriteByte(msg, rint ((SVfloat (ent, nextthink) - sv.time) * 255));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -512,6 +620,9 @@ SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
|
|||
int bits, items, i;
|
||||
vec3_t v;
|
||||
edict_t *other;
|
||||
const char *weaponmodel;
|
||||
|
||||
weaponmodel = PR_GetString (&sv_pr_state, SVstring (ent, weaponmodel));
|
||||
|
||||
// send a damage message
|
||||
if (SVfloat (ent, dmg_take) || SVfloat (ent, dmg_save)) {
|
||||
|
@ -577,11 +688,42 @@ SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
|
|||
// if (SVfloat (ent, weapon))
|
||||
bits |= SU_WEAPON;
|
||||
|
||||
if (sv.protocol != PROTOCOL_NETQUAKE) {
|
||||
if (bits & SU_WEAPON && SV_ModelIndex(weaponmodel) & 0xFF00)
|
||||
bits |= SU_WEAPON2;
|
||||
if ((int) SVfloat (ent, armorvalue) & 0xFF00)
|
||||
bits |= SU_ARMOR2;
|
||||
if ((int) SVfloat (ent, currentammo) & 0xFF00)
|
||||
bits |= SU_AMMO2;
|
||||
if ((int) SVfloat (ent, ammo_shells) & 0xFF00)
|
||||
bits |= SU_SHELLS2;
|
||||
if ((int) SVfloat (ent, ammo_nails) & 0xFF00)
|
||||
bits |= SU_NAILS2;
|
||||
if ((int) SVfloat (ent, ammo_rockets) & 0xFF00)
|
||||
bits |= SU_ROCKETS2;
|
||||
if ((int) SVfloat (ent, ammo_cells) & 0xFF00)
|
||||
bits |= SU_CELLS2;
|
||||
if (bits & SU_WEAPONFRAME && (int) SVfloat (ent, weaponframe) & 0xFF00)
|
||||
bits |= SU_WEAPONFRAME2;
|
||||
//FIXME
|
||||
//if (bits & SU_WEAPON && ent->alpha != ENTALPHA_DEFAULT)
|
||||
// bits |= SU_WEAPONALPHA; //for now, weaponalpha = client entity alpha
|
||||
if (bits >= 65536)
|
||||
bits |= SU_EXTEND1;
|
||||
if (bits >= 16777216)
|
||||
bits |= SU_EXTEND2;
|
||||
}
|
||||
|
||||
// send the data
|
||||
|
||||
MSG_WriteByte (msg, svc_clientdata);
|
||||
MSG_WriteShort (msg, bits);
|
||||
|
||||
if (bits & SU_EXTEND1)
|
||||
MSG_WriteByte(msg, bits>>16);
|
||||
if (bits & SU_EXTEND2)
|
||||
MSG_WriteByte(msg, bits>>24);
|
||||
|
||||
if (bits & SU_VIEWHEIGHT)
|
||||
MSG_WriteByte (msg, SVvector (ent, view_ofs)[2]);
|
||||
|
||||
|
@ -603,8 +745,7 @@ SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
|
|||
if (bits & SU_ARMOR)
|
||||
MSG_WriteByte (msg, SVfloat (ent, armorvalue));
|
||||
if (bits & SU_WEAPON)
|
||||
MSG_WriteByte (msg, SV_ModelIndex (PR_GetString (&sv_pr_state, SVstring
|
||||
(ent, weaponmodel))));
|
||||
MSG_WriteByte (msg, SV_ModelIndex (weaponmodel));
|
||||
|
||||
MSG_WriteShort (msg, SVfloat (ent, health));
|
||||
MSG_WriteByte (msg, SVfloat (ent, currentammo));
|
||||
|
@ -623,6 +764,26 @@ SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bits & SU_WEAPON2)
|
||||
MSG_WriteByte (msg, SV_ModelIndex(weaponmodel) >> 8);
|
||||
if (bits & SU_ARMOR2)
|
||||
MSG_WriteByte (msg, (int) SVfloat (ent, armorvalue) >> 8);
|
||||
if (bits & SU_AMMO2)
|
||||
MSG_WriteByte (msg, (int) SVfloat (ent, currentammo) >> 8);
|
||||
if (bits & SU_SHELLS2)
|
||||
MSG_WriteByte (msg, (int) SVfloat (ent, ammo_shells) >> 8);
|
||||
if (bits & SU_NAILS2)
|
||||
MSG_WriteByte (msg, (int) SVfloat (ent, ammo_nails) >> 8);
|
||||
if (bits & SU_ROCKETS2)
|
||||
MSG_WriteByte (msg, (int) SVfloat (ent, ammo_rockets) >> 8);
|
||||
if (bits & SU_CELLS2)
|
||||
MSG_WriteByte (msg, (int) SVfloat (ent, ammo_cells) >> 8);
|
||||
if (bits & SU_WEAPONFRAME2)
|
||||
MSG_WriteByte (msg, (int) SVfloat (ent, weaponframe) >> 8);
|
||||
// FIXME
|
||||
//if (bits & SU_WEAPONALPHA)
|
||||
// MSG_WriteByte (msg, ent->alpha); //for now, weaponalpha = client entity alpha
|
||||
}
|
||||
|
||||
static qboolean
|
||||
|
@ -635,6 +796,9 @@ SV_SendClientDatagram (client_t *client)
|
|||
msg.maxsize = sizeof (buf);
|
||||
msg.cursize = 0;
|
||||
|
||||
if (strcmp (client->netconnection->address, "LOCAL") != 0)
|
||||
msg.maxsize = DATAGRAM_MTU;
|
||||
|
||||
MSG_WriteByte (&msg, svc_time);
|
||||
MSG_WriteFloat (&msg, sv.time);
|
||||
|
||||
|
@ -799,46 +963,81 @@ SV_CreateBaseline (void)
|
|||
{
|
||||
int entnum;
|
||||
edict_t *svent;
|
||||
entity_state_t *baseline;
|
||||
int bits;
|
||||
|
||||
for (entnum = 0; entnum < sv.num_edicts; entnum++) {
|
||||
// get the current server version
|
||||
svent = EDICT_NUM (&sv_pr_state, entnum);
|
||||
baseline = (entity_state_t *) svent->data;
|
||||
|
||||
if (svent->free)
|
||||
continue;
|
||||
if (entnum > svs.maxclients && !SVfloat (svent, modelindex))
|
||||
continue;
|
||||
|
||||
// create entity baseline
|
||||
VectorCopy (SVvector (svent, origin),
|
||||
((entity_state_t *) svent->data)->origin);
|
||||
VectorCopy (SVvector (svent, angles),
|
||||
((entity_state_t *) svent->data)->angles);
|
||||
((entity_state_t *) svent->data)->frame = SVfloat (svent, frame);
|
||||
((entity_state_t *) svent->data)->skin = SVfloat (svent, skin);
|
||||
VectorCopy (SVvector (svent, origin), baseline->origin);
|
||||
VectorCopy (SVvector (svent, angles), baseline->angles);
|
||||
baseline->frame = SVfloat (svent, frame);
|
||||
baseline->skin = SVfloat (svent, skin);
|
||||
if (entnum > 0 && entnum <= svs.maxclients) {
|
||||
((entity_state_t *) svent->data)->colormap = entnum;
|
||||
((entity_state_t *) svent->data)->modelindex = SV_ModelIndex
|
||||
("progs/player.mdl");
|
||||
baseline->colormap = entnum;
|
||||
baseline->modelindex = SV_ModelIndex ("progs/player.mdl");
|
||||
baseline->alpha = ENTALPHA_DEFAULT;
|
||||
} else {
|
||||
((entity_state_t *) svent->data)->colormap = 0;
|
||||
((entity_state_t *) svent->data)->modelindex =
|
||||
SV_ModelIndex (PR_GetString (&sv_pr_state, SVstring (svent,
|
||||
model)));
|
||||
const char *model;
|
||||
model = PR_GetString (&sv_pr_state, SVstring (svent, model));
|
||||
baseline->colormap = 0;
|
||||
baseline->modelindex = SV_ModelIndex (model);
|
||||
baseline->alpha = ENTALPHA_DEFAULT;
|
||||
}
|
||||
|
||||
bits = 0;
|
||||
if (sv.protocol == PROTOCOL_NETQUAKE) {
|
||||
//still want to send baseline in PROTOCOL_NETQUAKE, so reset
|
||||
//these values
|
||||
if (baseline->modelindex & 0xFF00)
|
||||
baseline->modelindex = 0;
|
||||
if (baseline->frame & 0xFF00)
|
||||
baseline->frame = 0;
|
||||
baseline->alpha = ENTALPHA_DEFAULT;
|
||||
} else {
|
||||
if (baseline->modelindex & 0xFF00)
|
||||
bits |= B_LARGEMODEL;
|
||||
if (baseline->frame & 0xFF00)
|
||||
bits |= B_LARGEFRAME;
|
||||
if (baseline->alpha != ENTALPHA_DEFAULT)
|
||||
bits |= B_ALPHA;
|
||||
}
|
||||
|
||||
// add to the message
|
||||
MSG_WriteByte (&sv.signon, svc_spawnbaseline);
|
||||
if (bits)
|
||||
MSG_WriteByte (&sv.signon, svc_spawnbaseline2);
|
||||
else
|
||||
MSG_WriteByte (&sv.signon, svc_spawnbaseline);
|
||||
|
||||
MSG_WriteShort (&sv.signon, entnum);
|
||||
|
||||
MSG_WriteByte (&sv.signon,
|
||||
((entity_state_t *) svent->data)->modelindex);
|
||||
MSG_WriteByte (&sv.signon, ((entity_state_t *) svent->data)->frame);
|
||||
MSG_WriteByte (&sv.signon, ((entity_state_t *) svent->data)->colormap);
|
||||
MSG_WriteByte (&sv.signon, ((entity_state_t *) svent->data)->skin);
|
||||
if (bits)
|
||||
MSG_WriteByte (&sv.signon, bits);
|
||||
|
||||
MSG_WriteCoordAngleV (&sv.signon,
|
||||
((entity_state_t *) svent->data)->origin,
|
||||
((entity_state_t *) svent->data)->angles);
|
||||
if (bits & B_LARGEMODEL)
|
||||
MSG_WriteShort (&sv.signon, baseline->modelindex);
|
||||
else
|
||||
MSG_WriteByte (&sv.signon, baseline->modelindex);
|
||||
|
||||
if (bits & B_LARGEFRAME)
|
||||
MSG_WriteShort (&sv.signon, baseline->frame);
|
||||
else
|
||||
MSG_WriteByte (&sv.signon, baseline->frame);
|
||||
MSG_WriteByte (&sv.signon, baseline->colormap);
|
||||
MSG_WriteByte (&sv.signon, baseline->skin);
|
||||
|
||||
MSG_WriteCoordAngleV (&sv.signon, baseline->origin, baseline->angles);
|
||||
|
||||
if (bits & B_ALPHA)
|
||||
MSG_WriteByte (&sv.signon, baseline->alpha);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -935,12 +1134,14 @@ SV_SpawnServer (const char *server)
|
|||
|
||||
strcpy (sv.name, server);
|
||||
|
||||
sv.protocol = sv_protocol;
|
||||
|
||||
// load progs to get entity field count
|
||||
sv.max_edicts = MAX_EDICTS;
|
||||
sv.max_edicts = bound (MIN_EDICTS, max_edicts->int_val, MAX_EDICTS);
|
||||
SV_LoadProgs ();
|
||||
|
||||
// init the data field of the edicts
|
||||
for (i = 0; i < MAX_EDICTS; i++) {
|
||||
for (i = 0; i < sv.max_edicts; i++) {
|
||||
ent = EDICT_NUM (&sv_pr_state, i);
|
||||
ent->data = &baselines[i];
|
||||
}
|
||||
|
@ -1034,6 +1235,10 @@ SV_SpawnServer (const char *server)
|
|||
// create a baseline for more efficient communications
|
||||
SV_CreateBaseline ();
|
||||
|
||||
if (sv.signon.cursize > 8000-2)
|
||||
Sys_Printf ("%i byte signon buffer exceeds standard limit of 7998.\n",
|
||||
sv.signon.cursize);
|
||||
|
||||
// send serverinfo to all connected clients
|
||||
for (i = 0, host_client = svs.clients; i < svs.maxclients; i++,
|
||||
host_client++)
|
||||
|
|
|
@ -128,6 +128,7 @@ qboolean
|
|||
SV_RunThink (edict_t *ent)
|
||||
{
|
||||
float thinktime;
|
||||
float oldframe;
|
||||
|
||||
do {
|
||||
thinktime = SVfloat (ent, nextthink);
|
||||
|
@ -138,12 +139,27 @@ SV_RunThink (edict_t *ent)
|
|||
thinktime = sv.time; // don't let things stay in the past.
|
||||
// it is possible to start that way
|
||||
// by a trigger with a local time.
|
||||
oldframe = SVfloat (ent, frame);
|
||||
|
||||
SVfloat (ent, nextthink) = 0;
|
||||
*sv_globals.time = thinktime;
|
||||
sv_pr_think (ent);
|
||||
|
||||
if (ent->free)
|
||||
return false;
|
||||
#if 0 //FIXME
|
||||
ent->sendinterval = false;
|
||||
if (SVfloat (ent, nextthink)
|
||||
&& (SVfloat (ent, movetype) == MOVETYPE_STEP
|
||||
|| SVfloat (ent, frame) != oldframe)) {
|
||||
int i;
|
||||
i = rint ((SVfloat (ent, nextthink) - thinktime) * 255);
|
||||
if (i >= 0 && i < 256 && i != 25 && i != 26) {
|
||||
//25 and 26 are close enough to 0.1 to not send
|
||||
ent->sendinterval = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} while (0);
|
||||
|
||||
return true;
|
||||
|
@ -383,10 +399,11 @@ SV_Push (edict_t *pusher, vec3_t move)
|
|||
float solid_save;
|
||||
int num_moved, i, e;
|
||||
edict_t *check, *block;
|
||||
edict_t *moved_edict[MAX_EDICTS];
|
||||
edict_t **moved_edict;
|
||||
vec3_t entorig;
|
||||
vec3_t mins, maxs, pushorig;
|
||||
vec3_t moved_from[MAX_EDICTS];
|
||||
vec3_t *moved_from;
|
||||
int mark;
|
||||
|
||||
VectorAdd (SVvector (pusher, absmin), move, mins);
|
||||
VectorAdd (SVvector (pusher, absmax), move, maxs);
|
||||
|
@ -397,6 +414,10 @@ SV_Push (edict_t *pusher, vec3_t move)
|
|||
VectorAdd (SVvector (pusher, origin), move, SVvector (pusher, origin));
|
||||
SV_LinkEdict (pusher, false);
|
||||
|
||||
mark = Hunk_LowMark ();
|
||||
moved_edict = Hunk_Alloc (sv.num_edicts * sizeof (edict_t *));
|
||||
moved_from = Hunk_Alloc (sv.num_edicts * sizeof (vec_t));
|
||||
|
||||
// see if any solid entities are inside the final position
|
||||
num_moved = 0;
|
||||
check = NEXT_EDICT (&sv_pr_state, sv.edicts);
|
||||
|
@ -473,8 +494,10 @@ SV_Push (edict_t *pusher, vec3_t move)
|
|||
VectorCopy (moved_from[i], SVvector (moved_edict[i], origin));
|
||||
SV_LinkEdict (moved_edict[i], false);
|
||||
}
|
||||
Hunk_FreeToLowMark (mark);
|
||||
return false;
|
||||
}
|
||||
Hunk_FreeToLowMark (mark);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -262,10 +262,16 @@ PF_setmodel (progs_t *pr)
|
|||
|
||||
mod = sv.models[(int) SVfloat (e, modelindex)]; // Mod_ForName (m, true);
|
||||
|
||||
if (mod)
|
||||
SetMinMaxSize (pr, e, mod->mins, mod->maxs, true);
|
||||
else
|
||||
if (mod) {
|
||||
// FIXME disabled for now as setting clipmins/maxs is currently
|
||||
// too messy
|
||||
//if (mod->type == mod_brush)
|
||||
// SetMinMaxSize (pr, e, mod->clipmins, mod->clipmaxs, true);
|
||||
//else
|
||||
SetMinMaxSize (pr, e, mod->mins, mod->maxs, true);
|
||||
} else {
|
||||
SetMinMaxSize (pr, e, vec3_origin, vec3_origin, true);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -370,6 +376,7 @@ PF_ambientsound (progs_t *pr)
|
|||
float *pos;
|
||||
float vol, attenuation;
|
||||
int soundnum;
|
||||
int large = false;
|
||||
|
||||
pos = P_VECTOR (pr, 0);
|
||||
samp = P_GSTRING (pr, 1);
|
||||
|
@ -385,11 +392,20 @@ PF_ambientsound (progs_t *pr)
|
|||
Sys_Printf ("no precache: %s\n", samp);
|
||||
return;
|
||||
}
|
||||
if (soundnum > 255) {
|
||||
if (sv.protocol == PROTOCOL_NETQUAKE)
|
||||
return;
|
||||
large = true;
|
||||
}
|
||||
|
||||
// add an svc_spawnambient command to the level signon packet
|
||||
MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
|
||||
MSG_WriteByte (&sv.signon,
|
||||
large ? svc_spawnstaticsound2 : svc_spawnstaticsound);
|
||||
MSG_WriteCoordV (&sv.signon, pos);
|
||||
MSG_WriteByte (&sv.signon, soundnum);
|
||||
if (large)
|
||||
MSG_WriteShort (&sv.signon, soundnum);
|
||||
else
|
||||
MSG_WriteByte (&sv.signon, soundnum);
|
||||
MSG_WriteByte (&sv.signon, vol * 255);
|
||||
MSG_WriteByte (&sv.signon, attenuation * 64);
|
||||
|
||||
|
@ -1141,22 +1157,57 @@ PF_makestatic (progs_t *pr)
|
|||
{
|
||||
const char *model;
|
||||
edict_t *ent;
|
||||
int bits = 0;
|
||||
|
||||
ent = P_EDICT (pr, 0);
|
||||
|
||||
MSG_WriteByte (&sv.signon, svc_spawnstatic);
|
||||
//if (ent->alpha == ENTALPHA_ZERO) { //FIXME
|
||||
// //johnfitz -- don't send invisible static entities
|
||||
// goto nosend;
|
||||
//}
|
||||
|
||||
model = PR_GetString (pr, SVstring (ent, model));
|
||||
MSG_WriteByte (&sv.signon, SV_ModelIndex (model));
|
||||
if (sv.protocol == PROTOCOL_NETQUAKE) {
|
||||
if (SV_ModelIndex (model) & 0xff00
|
||||
|| (int) SVfloat (ent, frame) & 0xff00)
|
||||
goto nosend;
|
||||
} else {
|
||||
if (SV_ModelIndex (model) & 0xff00)
|
||||
bits |= B_LARGEMODEL;
|
||||
if ((int) SVfloat (ent, frame) & 0xff00)
|
||||
bits |= B_LARGEFRAME;
|
||||
//FIXME
|
||||
//if (ent->alpha != ENTALPHA_DEFAULT)
|
||||
// bits |= B_ALPHA;
|
||||
}
|
||||
|
||||
if (bits) {
|
||||
MSG_WriteByte (&sv.signon, svc_spawnstatic2);
|
||||
MSG_WriteByte (&sv.signon, bits);
|
||||
} else {
|
||||
MSG_WriteByte (&sv.signon, svc_spawnstatic);
|
||||
}
|
||||
|
||||
if (bits & B_LARGEMODEL)
|
||||
MSG_WriteShort (&sv.signon, SV_ModelIndex (model));
|
||||
else
|
||||
MSG_WriteByte (&sv.signon, SV_ModelIndex (model));
|
||||
|
||||
if (bits & B_LARGEFRAME)
|
||||
MSG_WriteShort (&sv.signon, SVfloat (ent, frame));
|
||||
else
|
||||
MSG_WriteByte (&sv.signon, SVfloat (ent, frame));
|
||||
|
||||
MSG_WriteByte (&sv.signon, SVfloat (ent, frame));
|
||||
MSG_WriteByte (&sv.signon, SVfloat (ent, colormap));
|
||||
MSG_WriteByte (&sv.signon, SVfloat (ent, skin));
|
||||
|
||||
MSG_WriteCoordAngleV (&sv.signon, SVvector (ent, origin),
|
||||
SVvector (ent, angles));
|
||||
|
||||
//FIXME
|
||||
//if (bits & B_ALPHA)
|
||||
// MSG_WriteByte (&sv.signon, ent->alpha);
|
||||
// throw the entity away now
|
||||
nosend:
|
||||
ED_Free (pr, ent);
|
||||
}
|
||||
|
||||
|
|
|
@ -427,7 +427,10 @@ SV_ReadClientMove (usercmd_t *move)
|
|||
host_client->num_pings++;
|
||||
|
||||
// read current angles
|
||||
MSG_ReadAngleV (net_message, angle);
|
||||
if (sv.protocol == PROTOCOL_NETQUAKE)
|
||||
MSG_ReadAngleV (net_message, angle);
|
||||
else
|
||||
MSG_ReadAngle16V (net_message, angle);
|
||||
|
||||
VectorCopy (angle, SVvector (host_client->edict, v_angle));
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#define __server_h
|
||||
|
||||
#include "netchan.h"
|
||||
#include "qw/bothdefs.h"
|
||||
#include "qw/pmove.h"
|
||||
|
||||
struct client_s;
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "QF/zone.h"
|
||||
|
||||
#include "netchan.h"
|
||||
#include "qw/bothdefs.h"
|
||||
#include "qw/protocol.h"
|
||||
#include "r_local.h"
|
||||
#include "QF/render.h"
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
#include "host.h"
|
||||
#include "netchan.h"
|
||||
#include "qw/bothdefs.h"
|
||||
#include "qw/msg_backbuf.h"
|
||||
#include "qw/protocol.h"
|
||||
|
||||
|
|
Loading…
Reference in a new issue