This prepares for moving the net_svc code to a branch allowing both network

code cleanups and general performance work to be developed in relative peace.
While cleaning up the networking code /is/ important, fixing QF's perfomance
issues is of much higher priority.
This commit is contained in:
Bill Currie 2001-11-07 08:24:56 +00:00
parent f60c39e0bc
commit c5aec15569
25 changed files with 1371 additions and 1507 deletions

View file

@ -62,10 +62,11 @@
#define MAX_LIGHTSTYLES 64
#define MAX_MODELS 256 // these are sent over the net as bytes
#define MAX_SOUNDS 256 // so they cannot be blindly increased
#define MAX_PROJECTILES 32
#define SAVEGAME_COMMENT_LENGTH 39
#define MAX_STYLESTRING 64
//
// stats are integers communicated to the client by the server
//

View file

@ -36,8 +36,7 @@ void CL_SetUpPlayerPrediction(qboolean dopred);
void CL_EmitEntities (void);
void CL_ClearProjectiles (void);
void CL_ParseProjectiles (void);
void CL_ParsePacketEntities (void);
void CL_ParseDeltaPacketEntities ();
void CL_ParsePacketEntities (qboolean delta);
void CL_SetSolidEntities (void);
void CL_ParsePlayerinfo (void);
void CL_Ents_Init (void);

View file

@ -338,7 +338,7 @@ void CL_UpdateScreen (double realtime);
void CL_SetState (cactive_t state);
void CL_ParseDamage (void);
void V_ParseDamage (void);
void V_PrepBlend (void);

View file

@ -60,7 +60,6 @@ void Host_InitCommands (void);
void Host_Init (void);
void Host_Shutdown(void);
void Host_Error (const char *error, ...) __attribute__((format(printf,1,2)));
void Host_NetError (const char *error, ...) __attribute((format(printf,1,2)));
void Host_EndGame (const char *message, ...) __attribute__((format(printf,1,2)));
void Host_Frame (float time);
void Host_Quit_f (void);

View file

@ -138,8 +138,6 @@ int Net_Log_Init (const char **sound_precache);
void Log_Incoming_Packet (const char *p, int len);
void Log_Outgoing_Packet (const char *p, int len);
void Net_LogStop (void);
void Analyze_Server_Packet (const byte *data, int len);
void Analyze_Client_Packet (const byte *data, int len);
extern struct cvar_s *net_packetlog;

View file

@ -214,22 +214,6 @@
#define U_UNUSED30 (1<<30) // future expansion
#define U_EXTEND3 (1<<31) // another byte to follow, future expansion
#define U_GROUP_ORIG (U_ORIGIN1 | U_ORIGIN2 | U_ORIGIN3 | \
U_ANGLE2 | U_FRAME | U_REMOVE | U_MOREBITS)
#define U_GROUP_MOREBITS (U_ANGLE1 | U_ANGLE3 | U_MODEL | \
U_COLORMAP | U_SKIN | U_EFFECTS | \
U_SOLID | U_EXTEND1)
#define U_GROUP_EXTEND1 (U_ALPHA | U_SCALE | U_EFFECTS2 | \
U_GLOWSIZE | U_GLOWCOLOR | U_COLORMOD | \
U_EXTEND2)
#define U_GROUP_EXTEND2 (U_GLOWTRAIL | U_VIEWMODEL | U_FRAME2)
// I skip the UNUSED and EXTEND3 bits because although they exist in
// QSG2, they're not usable
#define U_VERSION_ID ((U_GROUP_ORIG | U_GROUP_MOREBITS) & ~U_EXTEND1)
#define U_VERSION_QSG2 (U_VERSION_ID | U_EXTEND1 | U_GROUP_EXTEND1 | \
U_GROUP_EFFECTS2)
//==============================================
// a sound with no channel is a local only sound

View file

@ -499,7 +499,7 @@ void SV_SendClientMessages (void);
void SV_Multicast (vec3_t origin, int to);
void SV_StartSound (struct edict_s *entity, int channel, const char *sample,
float volume, float attenuation);
int volume, float attenuation);
void SV_ClientPrintf (client_t *cl, int level, const char *fmt, ...) __attribute__((format(printf,3,4)));
void SV_BroadcastPrintf (int level, const char *fmt, ...) __attribute__((format(printf,2,3)));
void SV_BroadcastCommand (const char *fmt, ...) __attribute__((format(printf,1,2)));

View file

@ -52,7 +52,7 @@ libasm_la_SOURCES= $(asm_src)
noinst_LTLIBRARIES= libqfnet.la $(asm)
common_sources= buildnum.c com.c game.c msg_ucmd.c pmove.c pmovetst.c \
net_packetlog.c net_svc.c
net_packetlog.c
common_ldflags= -export-dynamic

View file

@ -265,7 +265,7 @@ CL_GetDemoMessage (void)
(net_message->message->cursize);
// Con_Printf("read: %ld bytes\n", net_message->message->cursize);
if (net_message->message->cursize > MAX_MSGLEN + 8) //+8 for header
Host_Error ("Demo message > MAX_MSGLEN + 8: %d/%d",
Host_EndGame ("Demo message > MAX_MSGLEN + 8: %d/%d",
net_message->message->cursize, MAX_MSGLEN + 8);
r = Qread (cls.demofile, net_message->message->data,
net_message->message->cursize);

View file

@ -43,7 +43,6 @@ static const char rcsid[] =
#include "QF/render.h"
#include "QF/skin.h"
#include "bothdefs.h"
#include "cl_cam.h"
#include "cl_ents.h"
#include "cl_main.h"
@ -54,7 +53,6 @@ static const char rcsid[] =
#include "d_iface.h"
#include "host.h"
#include "msg_ucmd.h"
#include "net_svc.h"
#include "pmove.h"
#include "r_cvar.h"
#include "r_dynamic.h"
@ -71,7 +69,6 @@ entity_t cl_flag_ents[MAX_CLIENTS];
entity_t cl_player_ents[MAX_CLIENTS];
void
CL_ClearEnts ()
{
@ -127,168 +124,221 @@ CL_NewDlight (int key, vec3_t org, int effects)
int bitcounts[32]; // / just for protocol profiling
/*
CL_ParseDelta
Can go from either a baseline or a previous packet_entity
*/
void
CL_EntityState_Copy (entity_state_t *src, entity_state_t *dest, int bits)
CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits)
{
int i;
// set everything to the state we are delta'ing from
*to = *from;
to->number = bits & 511;
bits &= ~511;
if (bits & U_MOREBITS) { // read in the low order bits
i = MSG_ReadByte (net_message);
bits |= i;
}
// count the bits for net profiling
// for (i=0 ; i<16 ; i++)
// if (bits&(1<<i))
// bitcounts[i]++;
// LordHavoc: Endy neglected to mark this as being part of the QSG
// version 2 stuff...
if (bits & U_EXTEND1) {
bits |= MSG_ReadByte (net_message) << 16;
if (bits & U_EXTEND2)
bits |= MSG_ReadByte (net_message) << 24;
}
to->flags = bits;
if (bits & U_MODEL)
dest->modelindex = src->modelindex;
to->modelindex = MSG_ReadByte (net_message);
if (bits & U_FRAME)
dest->frame = (dest->frame & 0xFF00) | (src->frame & 0xFF);
to->frame = MSG_ReadByte (net_message);
if (bits & U_COLORMAP)
dest->colormap = src->colormap;
to->colormap = MSG_ReadByte (net_message);
if (bits & U_SKIN)
dest->skinnum = src->skinnum;
to->skinnum = MSG_ReadByte (net_message);
if (bits & U_EFFECTS)
dest->effects = (dest->effects & 0xFF00) | (src->effects & 0xFF);
to->effects = MSG_ReadByte (net_message);
if (bits & U_ORIGIN1)
dest->origin[0] = src->origin[0];
if (bits & U_ANGLE1)
dest->angles[0] = src->angles[0];
if (bits & U_ORIGIN2)
dest->origin[1] = src->origin[1];
if (bits & U_ANGLE2)
dest->angles[1] = src->angles[1];
if (bits & U_ORIGIN3)
dest->origin[2] = src->origin[2];
if (bits & U_ANGLE3)
dest->angles[2] = src->angles[2];
to->origin[0] = MSG_ReadCoord (net_message);
if (bits & U_ANGLE1)
to->angles[0] = MSG_ReadAngle (net_message);
if (bits & U_ORIGIN2)
to->origin[1] = MSG_ReadCoord (net_message);
if (bits & U_ANGLE2)
to->angles[1] = MSG_ReadAngle (net_message);
if (bits & U_ORIGIN3)
to->origin[2] = MSG_ReadCoord (net_message);
if (bits & U_ANGLE3)
to->angles[2] = MSG_ReadAngle (net_message);
// LordHavoc: Endy neglected to mark this as being part of the QSG
// version 2 stuff... rearranged it and implemented missing effects
// Ender (QSG - Begin)
if (bits & U_ALPHA)
dest->alpha = src->alpha;
to->alpha = MSG_ReadByte (net_message);
if (bits & U_SCALE)
dest->scale = src->scale;
to->scale = MSG_ReadByte (net_message);
if (bits & U_EFFECTS2)
dest->effects = (dest->effects & 0xFF) | (src->effects & 0xFF00);
to->effects = (to->effects & 0xFF) | (MSG_ReadByte (net_message) << 8);
if (bits & U_GLOWSIZE)
dest->glow_size = src->glow_size;
to->glow_size = MSG_ReadByte (net_message);
if (bits & U_GLOWCOLOR)
dest->glow_color = src->glow_color;
to->glow_color = MSG_ReadByte (net_message);
if (bits & U_COLORMOD)
dest->colormod = src->colormod;
to->colormod = MSG_ReadByte (net_message);
if (bits & U_FRAME2)
dest->frame = (dest->frame & 0xFF) | (src->frame & 0xFF00);
to->frame = (to->frame & 0xFF) | (MSG_ReadByte (net_message) << 8);
// Ender (QSG - End)
if (bits & U_SOLID) {
// FIXME
}
/*
if ((!to->alpha) || (!to->colormod))
Con_Printf("fa: %d, fc: %d, ta: %d, tc: %d\n",
from->alpha, from->colormod, to->alpha, to->colormod);
*/
/*
if ((!ent->alpha) || (!ent->colormod[0]) || (!ent->colormod[1]) ||
(!ent->colormod[2])) {
Con_Printf ("ea: %f, ec0: %f, ec1: %f ec2: %f, sa: %d, sc: %d\n",
ent->alpha, ent->colormod[0], ent->colormod[1],
ent->colormod[2], s1->alpha, s1->colormod);
}
*/
}
void
CL_ParsePacketEntities (void)
FlushEntityPacket (void)
{
int index, packetnum;
packet_entities_t *newp;
net_svc_packetentities_t block;
entity_state_t olde, newe;
int word;
packetnum = cls.netchan.incoming_sequence & UPDATE_MASK;
newp = &cl.frames[packetnum].packet_entities;
cl.frames[packetnum].invalid = false;
Con_DPrintf ("FlushEntityPacket\n");
cl.validsequence = cls.netchan.incoming_sequence;
memset (&olde, 0, sizeof (olde));
newp->num_entities = 0;
cl.validsequence = 0; // can't render a frame
cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK].invalid = true;
if (NET_SVC_PacketEntities_Parse (&block, net_message)) {
Host_NetError ("CL_ParsePacketEntities: Bad Read");
// read it all, but ignore it
while (1) {
word = (unsigned short) MSG_ReadShort (net_message);
if (net_message->badread) { // something didn't parse right...
Host_EndGame ("msg_badread in packetentities");
return;
}
for (index = 0; block.words[index]; index++) {
if (block.words[index] & U_REMOVE) {
Host_NetError ("CL_ParsePacketEntities: U_REMOVE on full "
"update\n");
cl.validsequence = 0; // XXX
cl.frames[packetnum].invalid = true;
return;
}
if (!word)
break; // done
if (index >= MAX_PACKET_ENTITIES) {
Host_NetError ("CL_ParsePacketEntities: index %i >= "
"MAX_PACKET_ENTITIES", index);
return;
CL_ParseDelta (&olde, &newe, word);
}
newp->entities[index] = cl_baselines[block.words[index] & 511];
CL_EntityState_Copy (&block.deltas[index],
&newp->entities[index],
block.deltas[index].flags);
newp->entities[index].number = block.deltas[index].number;
if (newp->entities[index].modelindex >= MAX_MODELS) {
Host_NetError ("CL_ParsePacketEntities: modelindex %i >= "
"MAX_MODELS", newp->entities[index].modelindex);
return;
}
continue;
}
newp->num_entities = index;
}
/*
CL_ParseDeltaPacketEntities
CL_ParsePacketEntities
An svc_packetentities has just been parsed, deal with the
rest of the data stream.
*/
void
CL_ParseDeltaPacketEntities ()
CL_ParsePacketEntities (qboolean delta)
{
int oldindex = 0, newindex = 0;
int wordindex = 0, deltaindex = 0;
int oldnum, newnum;
int oldpacket, newpacket;
packet_entities_t *oldp, *newp;
net_svc_deltapacketentities_t block;
if (NET_SVC_DeltaPacketEntities_Parse (&block, net_message)) {
Host_NetError ("CL_ParseDeltaPacketEntities: Bad Read");
return;
}
byte from;
int oldindex, newindex, newnum, oldnum, oldpacket, newpacket, word;
packet_entities_t *oldp, *newp, dummy;
qboolean full;
newpacket = cls.netchan.incoming_sequence & UPDATE_MASK;
newp = &cl.frames[newpacket].packet_entities;
cl.frames[newpacket].invalid = false;
if (delta) {
from = MSG_ReadByte (net_message);
oldpacket = cl.frames[newpacket].delta_sequence;
if ((from & UPDATE_MASK) != (oldpacket & UPDATE_MASK))
Con_DPrintf ("WARNING: from mismatch\n");
} else
oldpacket = -1;
full = false;
if (oldpacket != -1) {
if (cls.netchan.outgoing_sequence - oldpacket >= UPDATE_BACKUP - 1) {
// we can't use this, it is too old
Con_DPrintf ("CL_ParseDeltaPacketEntities: old packet\n");
cl.validsequence = 0; // can't render a frame
cl.frames[newpacket].invalid = true;
FlushEntityPacket ();
return;
}
if ((block.from & UPDATE_MASK) != (oldpacket & UPDATE_MASK)) {
Con_DPrintf ("CL_ParseDeltaPacketEntities: from mismatch\n");
cl.validsequence = 0;
cl.frames[newpacket].invalid = true;
return;
}
if (oldpacket == -1) {
Host_NetError ("Cl_ParseDeltaPacketEntities: invalid "
"delta_sequence\n");
return;
}
cl.validsequence = cls.netchan.incoming_sequence;
oldp = &cl.frames[oldpacket & UPDATE_MASK].packet_entities;
} else { // a full update that we can start delta compressing from now
oldp = &dummy;
dummy.num_entities = 0;
cl.validsequence = cls.netchan.incoming_sequence;
full = true;
}
oldindex = 0;
newindex = 0;
newp->num_entities = 0;
for (; block.words[wordindex];) {
newnum = block.words[wordindex] & 511;
while (1) {
word = (unsigned short) MSG_ReadShort (net_message);
if (net_message->badread) { // something didn't parse right...
Host_EndGame ("msg_badread in packetentities");
return;
}
if (!word) { // copy rest of ents from old packet
while (oldindex < oldp->num_entities) {
// Con_Printf ("copy %i\n", oldp->entities[oldindex].number);
if (newindex >= MAX_PACKET_ENTITIES)
Host_EndGame ("CL_ParsePacketEntities: newindex == "
"MAX_PACKET_ENTITIES");
newp->entities[newindex] = oldp->entities[oldindex];
newindex++;
oldindex++;
}
break;
}
newnum = word & 511;
oldnum = oldindex >= oldp->num_entities ? 9999 :
oldp->entities[oldindex].number;
while (newnum > oldnum) { // copy one of the old entities
// over to the new packet unchanged
// Con_Printf ("copy %i\n", oldnum);
if (newindex >= MAX_PACKET_ENTITIES) {
Host_NetError ("CL_ParseDeltaPacketEntities: newindex >= "
"MAX_PACKET_ENTITIES (1st)");
while (newnum > oldnum) {
if (full) {
Con_Printf ("WARNING: oldcopy on full update");
FlushEntityPacket ();
return;
}
// Con_Printf ("copy %i\n", oldnum);
// copy one of the old entities over to the new packet unchanged
if (newindex >= MAX_PACKET_ENTITIES)
Host_EndGame ("CL_ParsePacketEntities: newindex == "
"MAX_PACKET_ENTITIES");
newp->entities[newindex] = oldp->entities[oldindex];
newindex++;
oldindex++;
@ -298,74 +348,44 @@ CL_ParseDeltaPacketEntities ()
if (newnum < oldnum) { // new from baseline
// Con_Printf ("baseline %i\n", newnum);
if (block.words[wordindex] & U_REMOVE) {
wordindex++;
if (word & U_REMOVE) {
if (full) {
cl.validsequence = 0;
Con_Printf ("WARNING: U_REMOVE on full update\n");
FlushEntityPacket ();
return;
}
continue;
}
if (newindex >= MAX_PACKET_ENTITIES) {
Host_NetError ("CL_ParseDeltaPacketEntities: newindex >= "
"MAX_PACKET_ENTITIES (2nd)");
return;
}
newp->entities[newindex] = cl_baselines[newnum];
CL_EntityState_Copy (&block.deltas[deltaindex],
&newp->entities[newindex],
block.deltas[deltaindex].flags);
newp->entities[newindex].number
= block.deltas[deltaindex].number;
if (newp->entities[newindex].modelindex >= MAX_MODELS) {
Host_NetError ("CL_ParsePacketEntities: modelindex %i >= "
"MAX_MODELS",
newp->entities[newindex].modelindex);
return;
}
wordindex++;
deltaindex++;
if (newindex >= MAX_PACKET_ENTITIES)
Host_EndGame ("CL_ParsePacketEntities: newindex == "
"MAX_PACKET_ENTITIES");
CL_ParseDelta (&cl_baselines[newnum], &newp->entities[newindex],
word);
newindex++;
continue;
}
if (newnum == oldnum) { // delta from previous
// Con_Printf ("delta %i\n", newnum);
if (block.words[wordindex] & U_REMOVE) { // Clear the entity
memset (&cl_packet_ents[newnum], 0, sizeof (entity_t));
wordindex++;
if (full) {
cl.validsequence = 0;
Con_Printf ("WARNING: delta on full update");
}
if (word & U_REMOVE) { // Clear the entity
entity_t *ent = &cl_packet_ents[newnum];
memset (ent, 0, sizeof (entity_t));
oldindex++;
continue;
}
newp->entities[newindex] = oldp->entities[oldindex];
CL_EntityState_Copy (&block.deltas[deltaindex],
&newp->entities[newindex],
block.deltas[deltaindex].flags);
newp->entities[newindex].number
= block.deltas[deltaindex].number;
if (newp->entities[newindex].modelindex >= MAX_MODELS) {
Host_NetError ("CL_ParsePacketEntities: modelindex %i >= "
"MAX_MODELS",
newp->entities[newindex].modelindex);
return;
}
wordindex++;
deltaindex++;
// Con_Printf ("delta %i\n", newnum);
CL_ParseDelta (&oldp->entities[oldindex],
&newp->entities[newindex], word);
newindex++;
oldindex++;
}
}
while (oldindex < oldp->num_entities) { // copy rest of ents from old packet
// Con_Printf ("copy %i\n", oldp->entities[oldindex].number);
if (newindex >= MAX_PACKET_ENTITIES) {
Host_NetError ("CL_ParseDeltaPacketEntities: newindex >= "
"MAX_PACKET_ENTITIES (3rd)");
return;
}
newp->entities[newindex] = oldp->entities[oldindex];
newindex++;
oldindex++;
}
newp->num_entities = newindex;
}
@ -523,6 +543,7 @@ typedef struct {
entity_t ent;
} projectile_t;
#define MAX_PROJECTILES 32
projectile_t cl_projectiles[MAX_PROJECTILES];
int cl_num_projectiles;
@ -540,25 +561,27 @@ CL_ClearProjectiles (void)
void
CL_ParseProjectiles (void)
{
int i;
byte bits[6];
int i, c, j;
projectile_t *pr;
net_svc_nails_t block;
if (NET_SVC_Nails_Parse (&block, net_message)) {
Host_NetError ("CL_ParseProjectiles: Bad Read\n");
return;
}
c = MSG_ReadByte (net_message);
for (i = 0; i < c; i++) {
for (j = 0; j < 6; j++)
bits[j] = MSG_ReadByte (net_message);
for (i = 0; i < block.numnails; i++) {
if (cl_num_projectiles == MAX_PROJECTILES)
break;
continue;
pr = &cl_projectiles[cl_num_projectiles];
cl_num_projectiles++;
pr->modelindex = cl_spikeindex;
VectorCopy (block.nails[i].origin, pr->ent.origin);
VectorCopy (block.nails[i].angles, pr->ent.angles);
pr->ent.origin[0] = ((bits[0] + ((bits[1] & 15) << 8)) << 1) - 4096;
pr->ent.origin[1] = (((bits[1] >> 4) + (bits[2] << 4)) << 1) - 4096;
pr->ent.origin[2] = ((bits[3] + ((bits[4] & 15) << 8)) << 1) - 4096;
pr->ent.angles[0] = 360 * (bits[4] >> 4) / 16;
pr->ent.angles[1] = 360 * bits[5] / 256;
}
}
@ -594,57 +617,66 @@ CL_LinkProjectiles (void)
}
}
void
CL_ParsePlayerinfo (void)
{
int flags, msec, num, i;
player_state_t *state;
net_svc_playerinfo_t block;
if (NET_SVC_Playerinfo_Parse (&block, net_message)) {
Host_NetError ("CL_ParsePlayerinfo: Bad Read\n");
return;
}
num = MSG_ReadByte (net_message);
if (num > MAX_CLIENTS)
// Sys_Error ("CL_ParsePlayerinfo: bad num");
Host_EndGame ("CL_ParsePlayerinfo: bad num");
if (block.playernum >= MAX_CLIENTS) {
Host_NetError ("CL_ParsePlayerinfo: playernum %i >= MAX_CLIENTS",
block.playernum);
return;
}
if (block.modelindex >= MAX_MODELS) {
Host_NetError ("CL_ParsePlayerinfo: modelindex %i >= MAX_MODELS",
block.modelindex);
return;
}
state = &cl.frames[parsecountmod].playerstate[num];
state = &cl.frames[parsecountmod].playerstate[block.playernum];
state->number = block.playernum;
state->flags = block.flags;
state->number = num;
flags = state->flags = MSG_ReadShort (net_message);
state->messagenum = cl.parsecount;
VectorCopy (block.origin, state->origin);
state->origin[0] = MSG_ReadCoord (net_message);
state->origin[1] = MSG_ReadCoord (net_message);
state->origin[2] = MSG_ReadCoord (net_message);
state->frame = block.frame;
state->frame = MSG_ReadByte (net_message);
// the other player's last move was likely some time
// before the packet was sent out, so accurately track
// the exact time it was valid at
state->state_time = parsecounttime - block.msec * 0.001;
if (flags & PF_MSEC) {
msec = MSG_ReadByte (net_message);
state->state_time = parsecounttime - msec * 0.001;
} else
state->state_time = parsecounttime;
if (block.flags & PF_COMMAND)
memcpy (&state->command, &block.usercmd, sizeof (state->command));
if (flags & PF_COMMAND)
MSG_ReadDeltaUsercmd (&nullcmd, &state->command);
VectorCopy (block.velocity, state->velocity);
if (block.flags & PF_MODEL)
state->modelindex = block.modelindex;
for (i = 0; i < 3; i++) {
if (flags & (PF_VELOCITY1 << i))
state->velocity[i] = MSG_ReadShort (net_message);
else
state->velocity[i] = 0;
}
if (flags & PF_MODEL)
state->modelindex = MSG_ReadByte (net_message);
else
state->modelindex = cl_playerindex;
state->skinnum = block.skinnum;
state->effects = block.effects;
state->weaponframe = block.weaponframe;
if (flags & PF_SKINNUM)
state->skinnum = MSG_ReadByte (net_message);
else
state->skinnum = 0;
if (flags & PF_EFFECTS)
state->effects = MSG_ReadByte (net_message);
else
state->effects = 0;
if (flags & PF_WEAPONFRAME)
state->weaponframe = MSG_ReadByte (net_message);
else
state->weaponframe = 0;
VectorCopy (state->command.angles, state->viewangles);
}

View file

@ -1318,34 +1318,6 @@ Host_EndGame (const char *message, ...)
longjmp (host_abort, 1);
}
/*
Host_NetError
Used for networking errors that disconnect, but don't exit the
client
*/
void
Host_NetError (const char *message, ...)
{
va_list argptr;
int old = 0;
old = net_packetlog->int_val;
if (net_packetlog->int_val)
Cvar_Set (net_packetlog, "0");
Log_Incoming_Packet (net_message->message->data,
net_message->message->cursize);
if (old)
Cvar_SetValue (net_packetlog, old);
va_start (argptr, message);
Host_EndGame (message, argptr);
Con_Printf ("%s", "Please report this to "
"quake-devel@lists.sourceforge.net, including the "
"packet log printed out above\n");
va_end (argptr);
}
/*
Host_Error

File diff suppressed because it is too large Load diff

View file

@ -206,7 +206,7 @@ CL_NewTranslation (int slot, skin_t *skin)
player_info_t *player;
if (slot > MAX_CLIENTS)
Host_NetError ("CL_NewTranslation: slot > MAX_CLIENTS");
Host_EndGame ("CL_NewTranslation: slot > MAX_CLIENTS");
player = &cl.players[slot];
if (!player->name[0])

View file

@ -50,8 +50,6 @@ static const char rcsid[] =
#include "cl_main.h"
#include "cl_tent.h"
#include "client.h"
#include "host.h"
#include "net_svc.h"
#include "r_dynamic.h"
#define MAX_BEAMS 8
@ -184,37 +182,42 @@ CL_AllocExplosion (void)
}
void
CL_ParseBeam (net_svc_tempentity_t *tempentity, model_t *m)
CL_ParseBeam (model_t *m)
{
beam_t *b;
int i;
int ent, i;
vec3_t start, end;
if (tempentity->beamentity >= MAX_EDICTS) {
Host_NetError ("CL_ParseBeam: beamentity %i >= MAX_EDICTS",
tempentity->beamentity);
return;
}
ent = MSG_ReadShort (net_message);
start[0] = MSG_ReadCoord (net_message);
start[1] = MSG_ReadCoord (net_message);
start[2] = MSG_ReadCoord (net_message);
end[0] = MSG_ReadCoord (net_message);
end[1] = MSG_ReadCoord (net_message);
end[2] = MSG_ReadCoord (net_message);
// override any beam with the same entity
for (i = 0, b = cl_beams; i < MAX_BEAMS; i++, b++)
if (b->entity == tempentity->beamentity) {
b->entity = tempentity->beamentity;
if (b->entity == ent) {
b->entity = ent;
b->model = m;
b->endtime = cl.time + 0.2;
b->seed = rand();
VectorCopy (tempentity->position, b->start);
VectorCopy (tempentity->beamend, b->end);
VectorCopy (start, b->start);
VectorCopy (end, b->end);
return;
}
// find a free beam
for (i = 0, b = cl_beams; i < MAX_BEAMS; i++, b++) {
if (!b->model || b->endtime < cl.time) {
b->entity = tempentity->beamentity;
b->entity = ent;
b->model = m;
b->endtime = cl.time + 0.2;
b->seed = rand();
VectorCopy (tempentity->position, b->start);
VectorCopy (tempentity->beamend, b->end);
VectorCopy (start, b->start);
VectorCopy (end, b->end);
return;
}
}
@ -224,66 +227,79 @@ CL_ParseBeam (net_svc_tempentity_t *tempentity, model_t *m)
void
CL_ParseTEnt (void)
{
byte type;
dlight_t *dl;
explosion_t *ex;
int rnd;
net_svc_tempentity_t tempentity;
int colorStart, colorLength, rnd;
int cnt = -1;
vec3_t pos;
if (NET_SVC_TempEntity_Parse (&tempentity, net_message)) {
Host_NetError ("CL_ParseTEnt: Bad Read\n");
return;
}
switch (tempentity.type) {
type = MSG_ReadByte (net_message);
switch (type) {
case TE_WIZSPIKE: // spike hitting wall
R_RunSpikeEffect (tempentity.position, prot_to_rend[tempentity.type]);
S_StartSound (-1, 0, cl_sfx_wizhit, tempentity.position, 1, 1);
pos[0] = MSG_ReadCoord (net_message);
pos[1] = MSG_ReadCoord (net_message);
pos[2] = MSG_ReadCoord (net_message);
R_RunSpikeEffect (pos, prot_to_rend[type]);
S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
break;
case TE_KNIGHTSPIKE: // spike hitting wall
R_RunSpikeEffect (tempentity.position, prot_to_rend[tempentity.type]);
S_StartSound (-1, 0, cl_sfx_knighthit, tempentity.position, 1, 1);
pos[0] = MSG_ReadCoord (net_message);
pos[1] = MSG_ReadCoord (net_message);
pos[2] = MSG_ReadCoord (net_message);
R_RunSpikeEffect (pos, prot_to_rend[type]);
S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
break;
case TE_SPIKE: // spike hitting wall
R_RunSpikeEffect (tempentity.position, prot_to_rend[tempentity.type]);
pos[0] = MSG_ReadCoord (net_message);
pos[1] = MSG_ReadCoord (net_message);
pos[2] = MSG_ReadCoord (net_message);
R_RunSpikeEffect (pos, prot_to_rend[type]);
if (rand () % 5)
S_StartSound (-1, 0, cl_sfx_tink1, tempentity.position, 1, 1);
S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
else {
rnd = rand () & 3;
if (rnd == 1)
S_StartSound (-1, 0, cl_sfx_ric1, tempentity.position, 1, 1);
S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
else if (rnd == 2)
S_StartSound (-1, 0, cl_sfx_ric2, tempentity.position, 1, 1);
S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
else
S_StartSound (-1, 0, cl_sfx_ric3, tempentity.position, 1, 1);
S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
}
break;
case TE_SUPERSPIKE: // super spike hitting wall
R_RunSpikeEffect (tempentity.position, prot_to_rend[tempentity.type]);
pos[0] = MSG_ReadCoord (net_message);
pos[1] = MSG_ReadCoord (net_message);
pos[2] = MSG_ReadCoord (net_message);
R_RunSpikeEffect (pos, prot_to_rend[type]);
if (rand () % 5)
S_StartSound (-1, 0, cl_sfx_tink1, tempentity.position, 1, 1);
S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
else {
rnd = rand () & 3;
if (rnd == 1)
S_StartSound (-1, 0, cl_sfx_ric1, tempentity.position, 1, 1);
S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
else if (rnd == 2)
S_StartSound (-1, 0, cl_sfx_ric2, tempentity.position, 1, 1);
S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
else
S_StartSound (-1, 0, cl_sfx_ric3, tempentity.position, 1, 1);
S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
}
break;
case TE_EXPLOSION: // rocket explosion
// particles
R_ParticleExplosion (tempentity.position);
pos[0] = MSG_ReadCoord (net_message);
pos[1] = MSG_ReadCoord (net_message);
pos[2] = MSG_ReadCoord (net_message);
R_ParticleExplosion (pos);
// light
dl = R_AllocDlight (0);
VectorCopy (tempentity.position, dl->origin);
VectorCopy (pos, dl->origin);
dl->radius = 350;
dl->die = cl.time + 0.5;
dl->decay = 300;
@ -292,78 +308,94 @@ CL_ParseTEnt (void)
dl->color[2] = 0.24;
// sound
S_StartSound (-1, 0, cl_sfx_r_exp3, tempentity.position, 1, 1);
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
// sprite
ex = CL_AllocExplosion ();
VectorCopy (tempentity.position, ex->ent.origin);
VectorCopy (pos, ex->ent.origin);
ex->start = cl.time;
ex->ent.model = cl_spr_explod;
break;
case TE_TAREXPLOSION: // tarbaby explosion
R_BlobExplosion (tempentity.position);
pos[0] = MSG_ReadCoord (net_message);
pos[1] = MSG_ReadCoord (net_message);
pos[2] = MSG_ReadCoord (net_message);
R_BlobExplosion (pos);
S_StartSound (-1, 0, cl_sfx_r_exp3, tempentity.position, 1, 1);
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
break;
case TE_LIGHTNING1: // lightning bolts
CL_ParseBeam (&tempentity, cl_mod_bolt);
CL_ParseBeam (cl_mod_bolt);
break;
case TE_LIGHTNING2: // lightning bolts
CL_ParseBeam (&tempentity, cl_mod_bolt2);
CL_ParseBeam (cl_mod_bolt2);
break;
case TE_LIGHTNING3: // lightning bolts
CL_ParseBeam (&tempentity, cl_mod_bolt3);
CL_ParseBeam (cl_mod_bolt3);
break;
// PGM 01/21/97
case TE_BEAM: // grappling hook beam
CL_ParseBeam (&tempentity, Mod_ForName ("progs/beam.mdl", true));
CL_ParseBeam (Mod_ForName ("progs/beam.mdl", true));
break;
// PGM 01/21/97
case TE_LAVASPLASH:
R_LavaSplash (tempentity.position);
pos[0] = MSG_ReadCoord (net_message);
pos[1] = MSG_ReadCoord (net_message);
pos[2] = MSG_ReadCoord (net_message);
R_LavaSplash (pos);
break;
case TE_TELEPORT:
R_TeleportSplash (tempentity.position);
pos[0] = MSG_ReadCoord (net_message);
pos[1] = MSG_ReadCoord (net_message);
pos[2] = MSG_ReadCoord (net_message);
R_TeleportSplash (pos);
break;
case TE_EXPLOSION2: // color mapped explosion
R_ParticleExplosion2 (tempentity.position,
tempentity.colorstart,
tempentity.colorlength);
pos[0] = MSG_ReadCoord (net_message);
pos[1] = MSG_ReadCoord (net_message);
pos[2] = MSG_ReadCoord (net_message);
colorStart = MSG_ReadByte (net_message);
colorLength = MSG_ReadByte (net_message);
R_ParticleExplosion2 (pos, colorStart, colorLength);
dl = R_AllocDlight (0);
VectorCopy (tempentity.position, dl->origin);
VectorCopy (pos, dl->origin);
dl->radius = 350;
dl->die = cl.time + 0.5;
dl->decay = 300;
dl->color[0] = vid_basepal[(tempentity.colorstart
+ (rand() % tempentity.colorlength))
* 3] * (1.0 / 255.0);
dl->color[1] = vid_basepal[(tempentity.colorstart
+ (rand() % tempentity.colorlength))
* 3 + 1] * (1.0 / 255.0);
dl->color[2] = vid_basepal[(tempentity.colorstart
+ (rand() % tempentity.colorlength))
* 3 + 2] * (1.0 / 255.0);
S_StartSound (-1, 0, cl_sfx_r_exp3, tempentity.position, 1, 1);
dl->color[0] = vid_basepal[(colorStart + (rand() % colorLength)) *
3] * (1.0 / 255.0);
dl->color[1] = vid_basepal[(colorStart + (rand() % colorLength)) *
3 + 1] * (1.0 / 255.0);
dl->color[2] = vid_basepal[(colorStart + (rand() % colorLength)) *
3 + 2] * (1.0 / 255.0);
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
break;
case TE_GUNSHOT: // bullet hitting wall
case TE_BLOOD: // bullets hitting body
R_RunPuffEffect (tempentity.position, prot_to_rend[tempentity.type],
tempentity.gunshotcount * 20);
cnt = MSG_ReadByte (net_message) * 20;
pos[0] = MSG_ReadCoord (net_message);
pos[1] = MSG_ReadCoord (net_message);
pos[2] = MSG_ReadCoord (net_message);
R_RunPuffEffect (pos, prot_to_rend[type], cnt);
break;
case TE_LIGHTNINGBLOOD: // lightning hitting body
pos[0] = MSG_ReadCoord (net_message);
pos[1] = MSG_ReadCoord (net_message);
pos[2] = MSG_ReadCoord (net_message);
// light
dl = R_AllocDlight (0);
VectorCopy (tempentity.position, dl->origin);
VectorCopy (pos, dl->origin);
dl->radius = 150;
dl->die = cl.time + 0.1;
dl->decay = 200;
@ -371,11 +403,11 @@ CL_ParseTEnt (void)
dl->color[1] = 0.40;
dl->color[2] = 0.65;
R_RunPuffEffect (tempentity.position, prot_to_rend[tempentity.type], 0);
R_RunPuffEffect (pos, prot_to_rend[type], cnt);
break;
default:
Sys_Error ("CL_ParseTEnt: bad tempentity.type %i", tempentity.type);
Sys_Error ("CL_ParseTEnt: bad type");
}
}

View file

@ -45,7 +45,6 @@ static const char rcsid[] =
#include "client.h"
#include "compat.h"
#include "host.h"
#include "net_svc.h"
#include "pmove.h"
#include "view.h"
@ -241,18 +240,18 @@ V_DriftPitch (void)
/* PALETTE FLASHES */
void
CL_ParseDamage (void)
V_ParseDamage (void)
{
float count, side;
vec3_t forward, right, up;
net_svc_damage_t damage;
int armor, blood, i;
vec3_t forward, from, right, up;
if (NET_SVC_Damage_Parse (&damage, net_message)) {
Host_NetError ("CL_ParseDamage: Bad Read\n");
return;
}
armor = MSG_ReadByte (net_message);
blood = MSG_ReadByte (net_message);
for (i = 0; i < 3; i++)
from[i] = MSG_ReadCoord (net_message);
count = damage.blood * 0.5 + damage.armor * 0.5;
count = blood * 0.5 + armor * 0.5;
if (count < 10)
count = 10;
@ -266,11 +265,11 @@ CL_ParseDamage (void)
cl.cshifts[CSHIFT_DAMAGE].percent =
bound (0, cl.cshifts[CSHIFT_DAMAGE].percent, 150);
if (damage.armor > damage.blood) {
if (armor > blood) {
cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 200;
cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 100;
cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 100;
} else if (damage.armor) {
} else if (armor) {
cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 220;
cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 50;
cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 50;
@ -282,15 +281,15 @@ CL_ParseDamage (void)
}
// calculate view angle kicks
VectorSubtract (damage.from, cl.simorg, damage.from);
VectorNormalize (damage.from);
VectorSubtract (from, cl.simorg, from);
VectorNormalize (from);
AngleVectors (cl.simangles, forward, right, up);
side = DotProduct (damage.from, right);
side = DotProduct (from, right);
v_dmg_roll = count * side * v_kickroll->value;
side = DotProduct (damage.from, forward);
side = DotProduct (from, forward);
v_dmg_pitch = count * side * v_kickpitch->value;
v_dmg_time = v_kicktime->value;

View file

@ -56,7 +56,6 @@ static const char rcsid[] =
#include "compat.h"
#include "net.h"
#include "net_svc.h"
#include "protocol.h"
#include "server.h"
@ -71,6 +70,81 @@ void Parse_Server_Packet (void);
void Parse_Client_Packet (void);
void Net_LogStop (void);
// note: this is SUPPOSED to be duplicate, like many others
const char *svc_string[] = {
"svc_bad",
"svc_nop",
"svc_disconnect",
"svc_updatestat",
"svc_version", // [long] server version
"svc_setview", // [short] entity number
"svc_sound", // <see code>
"svc_time", // [float] server time
"svc_print", // [string] null terminated string
"svc_stufftext", // [string] stuffed into client's
// console buffer the string
// should be \n terminated
"svc_setangle", // [vec3] set the view angle to this
// absolute value
"svc_serverdata", // [long] version ...
"svc_lightstyle", // [byte] [string]
"svc_updatename", // [byte] [string]
"svc_updatefrags", // [byte] [short]
"svc_clientdata", // <shortbits + data>
"svc_stopsound", // <see code>
"svc_updatecolors", // [byte] [byte]
"svc_particle", // [vec3] <variable>
"svc_damage", // [byte] impact [byte] blood [vec3]
// from
"svc_spawnstatic",
"svc_spawnbinary",
"svc_spawnbaseline",
"svc_temp_entity", // <variable>
"svc_setpause",
"svc_signonnum",
"svc_centerprint",
"svc_killedmonster",
"svc_foundsecret",
"svc_spawnstaticsound",
"svc_intermission",
"svc_finale", // [string] music [string] text
"svc_cdtrack", // [byte] track [byte] looptrack
"svc_sellscreen",
"svc_smallkick", // Quake svc_cutscene
"svc_bigkick",
"svc_updateping",
"svc_updateentertime",
"svc_updatestatlong",
"svc_muzzleflash",
"svc_updateuserinfo",
"svc_download",
"svc_playerinfo",
"svc_nails",
"svc_chokecount",
"svc_modellist",
"svc_soundlist",
"svc_packetentities",
"svc_deltapacketentities",
"svc_maxspeed",
"svc_entgravity",
"svc_setinfo",
"svc_serverinfo",
"svc_updatepl",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL"
};
const char *clc_string[] = {
"clc_bad",
"clc_nop",
@ -95,6 +169,7 @@ const char *clc_string[] = {
#define svc_particle 18 // [vec3] <variable>
#define svc_signonnum 25 // [byte] used for the signon
// sequence
static VFile *_stdout;
static VFile *Net_PacketLog;
static const char **Net_sound_precache;
static sizebuf_t _packet;
@ -115,12 +190,11 @@ Net_LogPrintf (char *fmt, ...)
va_start (argptr, fmt);
vsnprintf (text, sizeof (text), fmt, argptr);
va_end (argptr);
if (!Net_PacketLog)
return;
if (Net_PacketLog) {
Qprintf (Net_PacketLog, "%s", text);
Qflush (Net_PacketLog);
} else
Con_Printf ("%s", text);
}
int
@ -230,43 +304,30 @@ Log_Outgoing_Packet (const char *p, int len)
return;
}
qboolean
void
Log_Delta(int bits)
{
entity_state_t to;
int i;
Net_LogPrintf ("\n\t<%06x> ", MSG_GetReadCount (&packet) - 2);
if (!bits) {
Net_LogPrintf ("End");
return 1;
}
Net_LogPrintf ("\n\t");
// set everything to the state we are delta'ing from
to.number = bits & 511;
bits &= ~511;
Net_LogPrintf ("Ent: %d", to.number);
if (bits & U_REMOVE)
Net_LogPrintf (" U_REMOVE");
if (bits & U_MOREBITS) { // read in the low order bits
i = MSG_ReadByte (&packet);
bits |= i;
Net_LogPrintf (" U_MOREBITS");
}
// LordHavoc: Endy neglected to mark this as being part of the QSG
// version 2 stuff...
if (bits & U_EXTEND1) {
bits |= MSG_ReadByte (&packet) << 16;
Net_LogPrintf (" U_EXTEND1");
if (bits & U_EXTEND2) {
if (bits & U_EXTEND2)
bits |= MSG_ReadByte (&packet) << 24;
Net_LogPrintf (" U_EXTEND2");
}
}
to.flags = bits;
@ -325,7 +386,7 @@ Log_Delta(int bits)
Net_LogPrintf(" Uframe2: %d", ((to.frame & 0xFF) | (MSG_ReadByte (&packet) << 8)));
// Ender (QSG - End)
return 0;
return;
}
@ -333,10 +394,14 @@ Log_Delta(int bits)
void
Analyze_Server_Packet (const byte * data, int len)
{
if (!Net_PacketLog)
Net_PacketLog = _stdout;
packet.message->data = (byte*)data;
packet.message->cursize = len;
MSG_BeginReading (&packet);
Parse_Server_Packet ();
if (Net_PacketLog == _stdout)
Net_PacketLog = NULL;
}
@ -373,11 +438,10 @@ Parse_Server_Packet ()
if (c == -1)
break;
// Net_LogPrintf("\n<%ld,%ld> ",seq1 & 0x7FFFFFFF,seq2 & 0x7FFFFFFF);
Net_LogPrintf ("<%06x> [0x%02x] ",
MSG_GetReadCount (&packet) - 1, c);
Net_LogPrintf ("<%06x> [0x%02x] ", MSG_GetReadCount (&packet), c);
if (c < 53)
Net_LogPrintf ("%s: ", NET_SVC_GetString (c));
Net_LogPrintf ("%s: ", svc_string[c]);
// else Net_LogPrintf("(UNK: %d): ",c);
if (MSG_GetReadCount (&packet) > packet.message->cursize)
@ -559,7 +623,7 @@ Parse_Server_Packet ()
Net_LogPrintf ("**QW OBSOLETE**");
break;
case svc_centerprint:
Net_LogPrintf ("%s", MSG_ReadString (&packet));
Net_LogPrintf ("%s\n", MSG_ReadString (&packet));
break;
case svc_killedmonster:
break;
@ -730,9 +794,6 @@ Parse_Server_Packet ()
else
Net_LogPrintf ("\n\t*End of sound list*");
break;
case svc_deltapacketentities:
Net_LogPrintf ("from: %d", MSG_ReadByte (&packet));
// intentional fallthrough
case svc_packetentities:
while (1) {
mask1 = (unsigned short) MSG_ReadShort(&packet);
@ -740,10 +801,15 @@ Parse_Server_Packet ()
Net_LogPrintf ("Badread\n");
return;
}
if (Log_Delta(mask1))
break;
if (!mask1) break;
if (mask1 & U_REMOVE) Net_LogPrintf("UREMOVE ");
Log_Delta(mask1);
}
break;
case svc_deltapacketentities:
Net_LogPrintf ("idx: %d", MSG_ReadByte (&packet));
return;
break;
case svc_maxspeed:
Net_LogPrintf ("%f", MSG_ReadFloat (&packet));
break;
@ -775,10 +841,14 @@ Parse_Server_Packet ()
void
Analyze_Client_Packet (const byte * data, int len)
{
if (!Net_PacketLog)
Net_PacketLog = _stdout;
packet.message->data = (byte*)data;
packet.message->cursize = len;
MSG_BeginReading (&packet);
Parse_Client_Packet ();
if (Net_PacketLog == _stdout)
Net_PacketLog = NULL;
}
void
@ -892,7 +962,7 @@ Net_PacketLog_f (cvar_t *var)
void
Net_PacketLog_Zap_f (void)
{
if (Net_PacketLog) {
if (Net_PacketLog && Net_PacketLog != _stdout) {
Con_Printf ("truncating packet logfile: %s\n", "qfpacket.log");
Qseek (Net_PacketLog, 0, 0);
Qwrite (Net_PacketLog, 0, 0);
@ -910,6 +980,8 @@ Net_Log_Init (const char **sound_precache)
{
Net_sound_precache = sound_precache;
_stdout = Qdopen (1, "wt"); // create a QFile of stdout
net_packetlog = Cvar_Get ("net_packetlog", "0", CVAR_NONE, Net_PacketLog_f,
"enable/disable packet logging");

View file

@ -52,7 +52,6 @@ static const char rcsid[] =
#include "bothdefs.h"
#include "compat.h"
#include "net_svc.h"
#include "server.h"
#include "sv_progs.h"
@ -830,15 +829,12 @@ SV_Heartbeat_f (void)
void
SV_SendServerInfoChange (const char *key, const char *value)
{
net_svc_serverinfo_t block;
if (!sv.state)
return;
block.key = key;
block.value = value;
MSG_WriteByte (&sv.reliable_datagram, svc_serverinfo);
NET_SVC_ServerInfo_Emit (&block, &sv.reliable_datagram);
MSG_WriteString (&sv.reliable_datagram, key);
MSG_WriteString (&sv.reliable_datagram, value);
}
/*

View file

@ -42,7 +42,6 @@ static const char rcsid[] =
#include "compat.h"
#include "msg_ucmd.h"
#include "net_svc.h"
#include "server.h"
#include "sv_progs.h"
@ -126,29 +125,51 @@ SV_AddNailUpdate (edict_t *ent)
void
SV_EmitNailUpdate (sizebuf_t *msg)
{
int i;
net_svc_nails_t block;
byte bits[6]; // [48 bits] xyzpy 12 12 12 4 8
int i, n, p, x, y, z, yaw;
edict_t *ent;
if (!numnails)
return;
block.numnails = numnails;
for (i = 0; i < numnails; i++) {
VectorCopy (SVvector (nails[i], origin), block.nails[i].origin);
VectorCopy (SVvector (nails[i], angles), block.nails[i].angles);
}
MSG_WriteByte (msg, svc_nails);
NET_SVC_Nails_Emit (&block, msg);
MSG_WriteByte (msg, numnails);
for (n = 0; n < numnails; n++) {
ent = nails[n];
x = (int) (SVvector (ent, origin)[0] + 4096) >> 1;
y = (int) (SVvector (ent, origin)[1] + 4096) >> 1;
z = (int) (SVvector (ent, origin)[2] + 4096) >> 1;
p = (int) (16 * SVvector (ent, angles)[0] / 360) & 15;
yaw = (int) (256 * SVvector (ent, angles)[1] / 360) & 255;
bits[0] = x;
bits[1] = (x >> 8) | (y << 4);
bits[2] = (y >> 4);
bits[3] = z;
bits[4] = (z >> 8) | (p << 4);
bits[5] = yaw;
for (i = 0; i < 6; i++)
MSG_WriteByte (msg, bits[i]);
}
}
unsigned int
SV_EntityState_Diff (entity_state_t *from, entity_state_t *to)
/*
SV_WriteDelta
Writes part of a packetentities message.
Can delta from either a baseline or a previous packet_entity
*/
void
SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg,
qboolean force, int stdver)
{
int i;
int bits, i;
float miss;
unsigned int bits = 0;
// send an update
bits = 0;
for (i = 0; i < 3; i++) {
miss = to->origin[i] - from->origin[i];
@ -182,7 +203,7 @@ SV_EntityState_Diff (entity_state_t *from, entity_state_t *to)
// LordHavoc: cleaned up Endy's coding style, and added missing effects
// Ender (QSG - Begin)
// if (stdver > 1) {
if (stdver > 1) {
if (to->alpha != from->alpha)
bits |= U_ALPHA;
@ -197,44 +218,20 @@ SV_EntityState_Diff (entity_state_t *from, entity_state_t *to)
if (to->colormod != from->colormod)
bits |= U_COLORMOD;
// }
}
// if (bits >= 16777216)
if (bits & U_GROUP_EXTEND2)
if (bits >= 16777216)
bits |= U_EXTEND2;
// if (bits >= 65536)
if (bits & U_GROUP_EXTEND1)
if (bits >= 65536)
bits |= U_EXTEND1;
// Ender (QSG - End)
// if (bits & 511)
if (bits & U_GROUP_MOREBITS)
if (bits & 511)
bits |= U_MOREBITS;
if (to->flags & U_SOLID)
bits |= U_SOLID;
return bits;
}
/*
SV_WriteDelta
Writes part of a packetentities message.
Can delta from either a baseline or a previous packet_entity
*/
void
SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg,
qboolean force, int stdver)
{
unsigned int bits;
// send an update
bits = SV_EntityState_Diff (from, to);
if (stdver <= 1)
bits &= U_VERSION_ID; // use old the original fields, no extensions
// write the message
if (!to->number)
SV_Error ("Unset entity number");
@ -243,7 +240,10 @@ SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg,
if (!bits && !force)
return; // nothing to send!
MSG_WriteShort (msg, to->number | (bits & ~511));
i = to->number | (bits & ~511);
if (i & U_REMOVE)
Sys_Error ("U_REMOVE");
MSG_WriteShort (msg, i);
if (bits & U_MOREBITS)
MSG_WriteByte (msg, bits & 255);
@ -302,118 +302,80 @@ SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg,
/*
SV_EmitPacketEntities
Writes an update of a packet_entities_t to the message.
Writes a delta update of a packet_entities_t to the message.
*/
void
SV_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t *msg)
{
int index;
entity_state_t *baseline;
net_svc_packetentities_t block;
block.numwords = block.numdeltas = to->num_entities;
for (index = 0; index < to->num_entities; index++) {
baseline = EDICT_NUM (&sv_pr_state,
to->entities[index].number)->data;
block.deltas[index] = to->entities[index];
block.deltas[index].flags =
SV_EntityState_Diff (baseline, &to->entities[index]);
// check if it's a client that doesn't support QSG2
if (client->stdver <= 1)
block.deltas[index].flags &= U_VERSION_ID;
block.words[index] = to->entities[index].number |
(block.deltas[index].flags & ~511);
}
block.words[index] = 0;
MSG_WriteByte (msg, svc_packetentities);
NET_SVC_PacketEntities_Emit (&block, msg);
}
/*
SV_EmitDeltaPacketEntities
Writes a delta update of a packet_entities_t to the message.
*/
void
SV_EmitDeltaPacketEntities (client_t *client, packet_entities_t *to,
sizebuf_t *msg)
{
int newindex, oldindex, newnum, oldnum;
int word;
entity_state_t *baseline;
int newindex, oldindex, newnum, oldnum, oldmax;
edict_t *ent;
client_frame_t *fromframe;
packet_entities_t *from;
net_svc_deltapacketentities_t block;
// this is the frame that we are going to delta update from
from = &client->frames[client->delta_sequence & UPDATE_MASK].entities;
if (client->delta_sequence != -1) {
fromframe = &client->frames[client->delta_sequence & UPDATE_MASK];
from = &fromframe->entities;
oldmax = from->num_entities;
block.from = client->delta_sequence;
MSG_WriteByte (msg, svc_deltapacketentities);
MSG_WriteByte (msg, client->delta_sequence);
} else {
oldmax = 0; // no delta update
from = NULL;
MSG_WriteByte (msg, svc_packetentities);
}
newindex = 0;
oldindex = 0;
// SV_Printf ("---%i to %i ----\n", client->delta_sequence & UPDATE_MASK,
// client->netchan.outgoing_sequence & UPDATE_MASK);
for (newindex = 0, oldindex = 0, word = 0;
newindex < to->num_entities || oldindex < from->num_entities;
word++) {
newnum = newindex >= to->num_entities ?
9999 : to->entities[newindex].number;
oldnum = oldindex >= from->num_entities ?
9999 : from->entities[oldindex].number;
while (newindex < to->num_entities || oldindex < oldmax) {
newnum =
newindex >= to->num_entities ? 9999 :
to->entities[newindex].number;
oldnum = oldindex >= oldmax ? 9999 : from->entities[oldindex].number;
if (newnum == oldnum) { // delta update from old position
// SV_Printf ("delta %i\n", newnum);
block.deltas[newindex] = to->entities[newindex];
block.deltas[newindex].flags =
SV_EntityState_Diff (&from->entities[oldindex],
&to->entities[newindex]);
// check if it's a client that doesn't support QSG2
if (client->stdver <= 1)
block.deltas[newindex].flags &= U_VERSION_ID;
block.words[word] = newnum | (block.deltas[newindex].flags & ~511);
SV_WriteDelta (&from->entities[oldindex], &to->entities[newindex],
msg, false, client->stdver);
oldindex++;
newindex++;
} else if (newnum < oldnum) { // this is a new entity, send
// it from the baseline
baseline = EDICT_NUM (&sv_pr_state, newnum)->data;
continue;
}
if (newnum < oldnum) { // this is a new entity, send it from
// the baseline
ent = EDICT_NUM (&sv_pr_state, newnum);
// SV_Printf ("baseline %i\n", newnum);
block.deltas[newindex] = to->entities[newindex];
block.deltas[newindex].flags =
SV_EntityState_Diff (baseline, &to->entities[newindex]);
// check if it's a client that doesn't support QSG2
if (client->stdver <= 1)
block.deltas[newindex].flags &= U_VERSION_ID;
block.words[word] = newnum | (block.deltas[newindex].flags & ~511);
SV_WriteDelta (ent->data, &to->entities[newindex], msg, true,
client->stdver);
newindex++;
} else if (newnum > oldnum) { // the old entity isn't
// present in the new message
continue;
}
if (newnum > oldnum) { // the old entity isn't present in
// the new message
// SV_Printf ("remove %i\n", oldnum);
block.words[word] = oldnum | U_REMOVE;
MSG_WriteShort (msg, oldnum | U_REMOVE);
oldindex++;
continue;
}
}
block.words[word] = 0;
MSG_WriteByte (msg, svc_deltapacketentities);
NET_SVC_DeltaPacketEntities_Emit (&block, msg);
MSG_WriteShort (msg, 0); // end of packetentities
}
void
SV_WritePlayersToClient (client_t *client, edict_t *clent, byte * pvs,
sizebuf_t *msg)
{
int i, j;
int i, j, msec, pflags;
client_t *cl;
edict_t *ent;
net_svc_playerinfo_t block;
usercmd_t cmd;
for (j = 0, cl = svs.clients; j < MAX_CLIENTS; j++, cl++) {
if (cl->state != cs_spawned)
@ -435,63 +397,82 @@ SV_WritePlayersToClient (client_t *client, edict_t *clent, byte * pvs,
continue; // not visible
}
block.flags = PF_MSEC | PF_COMMAND;
pflags = PF_MSEC | PF_COMMAND;
if (SVfloat (ent, modelindex) != sv_playermodel)
block.flags |= PF_MODEL;
pflags |= PF_MODEL;
for (i = 0; i < 3; i++)
if (SVvector (ent, velocity)[i])
block.flags |= PF_VELOCITY1 << i;
pflags |= PF_VELOCITY1 << i;
if (SVfloat (ent, effects))
block.flags |= PF_EFFECTS;
pflags |= PF_EFFECTS;
if (SVfloat (ent, skin))
block.flags |= PF_SKINNUM;
pflags |= PF_SKINNUM;
if (SVfloat (ent, health) <= 0)
block.flags |= PF_DEAD;
pflags |= PF_DEAD;
if (SVvector (ent, mins)[2] != -24)
block.flags |= PF_GIB;
pflags |= PF_GIB;
if (cl->spectator) { // only sent origin and velocity to
// spectators
block.flags &= PF_VELOCITY1 | PF_VELOCITY2 | PF_VELOCITY3;
pflags &= PF_VELOCITY1 | PF_VELOCITY2 | PF_VELOCITY3;
} else if (ent == clent) { // don't send a lot of data on
// personal entity
block.flags &= ~(PF_MSEC | PF_COMMAND);
pflags &= ~(PF_MSEC | PF_COMMAND);
if (SVfloat (ent, weaponframe))
block.flags |= PF_WEAPONFRAME;
pflags |= PF_WEAPONFRAME;
}
if (client->spec_track && client->spec_track - 1 == j &&
SVfloat (ent, weaponframe))
block.flags |= PF_WEAPONFRAME;
block.playernum = j;
VectorCopy (SVvector (ent, origin), block.origin);
block.frame = SVfloat (ent, frame);
block.msec = 1000 * (sv.time - cl->localtime);
if (block.msec > 255)
block.msec = 255;
block.usercmd = cl->lastcmd;
if (SVfloat (ent, health) <= 0) { // don't show the corpse
// looking around...
block.usercmd.angles[0] = 0;
block.usercmd.angles[1] = SVvector (ent, angles)[1];
block.usercmd.angles[0] = 0;
}
block.usercmd.buttons = 0; // never send buttons
block.usercmd.impulse = 0; // never send impulses
VectorCopy (SVvector (ent, velocity), block.velocity);
block.modelindex = SVfloat (ent, modelindex);
block.skinnum = SVfloat (ent, skin);
block.effects = SVfloat (ent, effects);
block.weaponframe = SVfloat (ent, weaponframe);
SVfloat (ent, weaponframe)) pflags |= PF_WEAPONFRAME;
MSG_WriteByte (msg, svc_playerinfo);
NET_SVC_Playerinfo_Emit (&block, msg);
MSG_WriteByte (msg, j);
MSG_WriteShort (msg, pflags);
for (i = 0; i < 3; i++)
MSG_WriteCoord (msg, SVvector (ent, origin)[i]);
MSG_WriteByte (msg, SVfloat (ent, frame));
if (pflags & PF_MSEC) {
msec = 1000 * (sv.time - cl->localtime);
if (msec > 255)
msec = 255;
MSG_WriteByte (msg, msec);
}
if (pflags & PF_COMMAND) {
cmd = cl->lastcmd;
if (SVfloat (ent, health) <= 0) { // don't show the corpse
// looking around...
cmd.angles[0] = 0;
cmd.angles[1] = SVvector (ent, angles)[1];
cmd.angles[0] = 0;
}
cmd.buttons = 0; // never send buttons
cmd.impulse = 0; // never send impulses
MSG_WriteDeltaUsercmd (msg, &nullcmd, &cmd);
}
for (i = 0; i < 3; i++)
if (pflags & (PF_VELOCITY1 << i))
MSG_WriteShort (msg, SVvector (ent, velocity)[i]);
if (pflags & PF_MODEL)
MSG_WriteByte (msg, SVfloat (ent, modelindex));
if (pflags & PF_SKINNUM)
MSG_WriteByte (msg, SVfloat (ent, skin));
if (pflags & PF_EFFECTS)
MSG_WriteByte (msg, SVfloat (ent, effects));
if (pflags & PF_WEAPONFRAME)
MSG_WriteByte (msg, SVfloat (ent, weaponframe));
}
}
@ -610,9 +591,7 @@ SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg)
// encode the packet entities as a delta from the
// last packetentities acknowledged by the client
if (client->delta_sequence != -1)
SV_EmitDeltaPacketEntities (client, pack, msg);
else
SV_EmitPacketEntities (client, pack, msg);
// now add the specialized nail update

View file

@ -46,7 +46,6 @@ static const char rcsid[] =
#include "compat.h"
#include "crudefile.h"
#include "net_svc.h"
#include "server.h"
#include "sv_progs.h"
#include "world.h"
@ -105,9 +104,8 @@ SV_FlushSignon (void)
void
SV_CreateBaseline (void)
{
int entnum;
int i, entnum;
edict_t *svent;
net_svc_spawnbaseline_t block;
for (entnum = 0; entnum < sv.num_edicts; entnum++) {
svent = EDICT_NUM (&sv_pr_state, entnum);
@ -145,15 +143,19 @@ SV_CreateBaseline (void)
SV_FlushSignon ();
// add to the message
block.num = entnum;
block.modelindex = ((entity_state_t*)svent->data)->modelindex;
block.frame = ((entity_state_t*)svent->data)->frame;
block.colormap = ((entity_state_t*)svent->data)->colormap;
block.skinnum = ((entity_state_t*)svent->data)->skinnum;
VectorCopy (((entity_state_t*)svent->data)->origin, block.origin);
VectorCopy (((entity_state_t*)svent->data)->angles, block.angles);
MSG_WriteByte (&sv.signon, svc_spawnbaseline);
NET_SVC_SpawnBaseline_Emit (&block, &sv.signon);
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)->skinnum);
for (i = 0; i < 3; i++) {
MSG_WriteCoord (&sv.signon,
((entity_state_t*)svent->data)->origin[i]);
MSG_WriteAngle (&sv.signon,
((entity_state_t*)svent->data)->angles[i]);
}
}
}

View file

@ -76,7 +76,6 @@ static const char rcsid[] =
#include "crudefile.h"
#include "game.h"
#include "net.h"
#include "net_svc.h"
#include "pmove.h"
#include "server.h"
#include "sv_progs.h"
@ -261,14 +260,11 @@ SV_FinalMessage (const char *message)
{
client_t *cl;
int i;
net_svc_print_t block;
block.level = PRINT_HIGH;
block.message = message;
SZ_Clear (net_message->message);
MSG_WriteByte (net_message->message, svc_print);
NET_SVC_Print_Emit (&block, net_message->message);
MSG_WriteByte (net_message->message, PRINT_HIGH);
MSG_WriteString (net_message->message, message);
MSG_WriteByte (net_message->message, svc_disconnect);
for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++)
@ -373,7 +369,6 @@ SV_FullClientUpdate (client_t *client, sizebuf_t *buf)
{
char *info;
int i;
net_svc_updateuserinfo_t block;
i = client - svs.clients;
@ -398,11 +393,10 @@ SV_FullClientUpdate (client_t *client, sizebuf_t *buf)
info = client->userinfo ? Info_MakeString (client->userinfo,
make_info_string_filter) : "";
block.slot = i;
block.userid = client->userid;
block.userinfo = info;
MSG_WriteByte (buf, svc_updateuserinfo);
NET_SVC_UpdateUserInfo_Emit (&block, buf);
MSG_WriteByte (buf, i);
MSG_WriteLong (buf, client->userid);
MSG_WriteString (buf, info);
}
/*
@ -2177,7 +2171,6 @@ Master_Shutdown (void)
static inline qboolean
iswhitespace (char c)
{
c &= 127;
return c == ' ' || c == '\r' || c == '\n' || c == '\t';
}
@ -2207,9 +2200,9 @@ SV_ExtractFromUserinfo (client_t *cl)
for (r = newname; *p && r != newname + sizeof (newname) - 1; p++) {
if (iswhitespace (*p)) {
if (!iswhitespace (p[1]) && p[1] != '\0')
*r++ = ' '; // get rid of any special chars
*r++ = *p;
} else
*r++ = *p & 127; // get rid of bold
*r++ = *p;
}
*r = '\0';
@ -2217,14 +2210,6 @@ SV_ExtractFromUserinfo (client_t *cl)
if (!*newname)
badname = true;
// ':' is used in chat messages
if (strchr (newname, ':'))
badname = true;
// I dunno if this is possible, but better safe than sorry
if (strchr (newname, '"'))
badname = true;
// impersonating an user-xxx name. if they're using it
// legitimately it'll be a no-op later on
if (!strncasecmp (newname, "user-", 5))
@ -2283,10 +2268,9 @@ SV_ExtractFromUserinfo (client_t *cl)
}
}
// finally, report it to all our friends, but only if more
// than whitespace changed
// finally, report it to all our friends
// if (cl->state >= cs_spawned && !cl->spectator)
if (*cl->name && strcmp (cl->name, newname))
if (*cl->name)
SV_BroadcastPrintf (PRINT_HIGH, "%s changed name to %s\n",
cl->name, newname);
strcpy (cl->name, newname);

View file

@ -36,6 +36,7 @@ static const char rcsid[] =
#include "QF/model.h"
const int mod_lightmap_bytes = 1;
cvar_t *gl_sky_divide; // not used but needed for linking
void Mod_LoadBrushModel (model_t *mod, void *buffer);

View file

@ -607,14 +607,14 @@ SV_CheckWaterTransition (edict_t *ent)
if (cont <= CONTENTS_WATER) {
if (SVfloat (ent, watertype) == CONTENTS_EMPTY) {
// just crossed into water
SV_StartSound (ent, 0, "misc/h2ohit1.wav", 1, 1);
SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
}
SVfloat (ent, watertype) = cont;
SVfloat (ent, waterlevel) = 1;
} else {
if (SVfloat (ent, watertype) != CONTENTS_EMPTY) {
// just crossed into water
SV_StartSound (ent, 0, "misc/h2ohit1.wav", 1, 1);
SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
}
SVfloat (ent, watertype) = CONTENTS_EMPTY;
SVfloat (ent, waterlevel) = cont;
@ -717,7 +717,7 @@ SV_Physics_Step (edict_t *ent)
if ((int) SVfloat (ent, flags) & FL_ONGROUND) // just hit ground
{
if (hitsound)
SV_StartSound (ent, 0, "demon/dland2.wav", 1, 1);
SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
}
}
// regular thinking

View file

@ -45,7 +45,6 @@ static const char rcsid[] =
#include "compat.h"
#include "crudefile.h"
#include "net_svc.h"
#include "server.h"
#include "sv_pr_cmds.h"
#include "sv_progs.h"
@ -280,16 +279,17 @@ PF_ambientsound (progs_t *pr)
{
const char **check;
const char *samp;
net_svc_spawnstaticsound_t block;
float *pos;
float vol, attenuation;
int i, soundnum;
VectorCopy (G_VECTOR (pr, OFS_PARM0), block.position);
pos = G_VECTOR (pr, OFS_PARM0);
samp = G_STRING (pr, OFS_PARM1);
block.volume = G_FLOAT (pr, OFS_PARM2) * 255;
block.attenuation = G_FLOAT (pr, OFS_PARM3) * 64;
vol = G_FLOAT (pr, OFS_PARM2);
attenuation = G_FLOAT (pr, OFS_PARM3);
// check to see if samp was properly precached
for (block.sound_num = 0, check = sv.sound_precache; *check;
check++, block.sound_num++)
for (soundnum = 0, check = sv.sound_precache; *check; check++, soundnum++)
if (!strcmp (*check, samp))
break;
@ -300,7 +300,14 @@ PF_ambientsound (progs_t *pr)
// add an svc_spawnambient command to the level signon packet
MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
NET_SVC_SpawnStaticSound_Emit (&block, &sv.signon);
for (i = 0; i < 3; i++)
MSG_WriteCoord (&sv.signon, pos[i]);
MSG_WriteByte (&sv.signon, soundnum);
MSG_WriteByte (&sv.signon, vol * 255);
MSG_WriteByte (&sv.signon, attenuation * 64);
}
/*
@ -320,13 +327,13 @@ PF_sound (progs_t *pr)
{
const char *sample;
edict_t *entity;
float volume, attenuation;
int channel;
float attenuation;
int channel, volume;
entity = G_EDICT (pr, OFS_PARM0);
channel = G_FLOAT (pr, OFS_PARM1);
sample = G_STRING (pr, OFS_PARM2);
volume = G_FLOAT (pr, OFS_PARM3);
volume = G_FLOAT (pr, OFS_PARM3) * 255;
attenuation = G_FLOAT (pr, OFS_PARM4);
SV_StartSound (entity, channel, sample, volume, attenuation);
@ -1135,21 +1142,25 @@ int SV_ModelIndex (const char *name);
void
PF_makestatic (progs_t *pr)
{
const char *model;
edict_t *ent;
net_svc_spawnstatic_t block;
int i;
ent = G_EDICT (pr, OFS_PARM0);
// SV_Printf ("Model: %d %s\n", SVstring (ent, model), model);
block.modelindex = SV_ModelIndex (PR_GetString (pr, SVstring (ent, model)));
block.frame = SVfloat (ent, frame);
block.colormap = SVfloat (ent, colormap);
block.skinnum = SVfloat (ent, skin);
VectorCopy (SVvector (ent, origin), block.origin);
VectorCopy (SVvector (ent, angles), block.angles);
MSG_WriteByte (&sv.signon, svc_spawnstatic);
NET_SVC_SpawnStatic_Emit (&block, &sv.signon);
model = PR_GetString (pr, SVstring (ent, model));
// SV_Printf ("Model: %d %s\n", SVstring (ent, model), model);
MSG_WriteByte (&sv.signon, SV_ModelIndex (model));
MSG_WriteByte (&sv.signon, SVfloat (ent, frame));
MSG_WriteByte (&sv.signon, SVfloat (ent, colormap));
MSG_WriteByte (&sv.signon, SVfloat (ent, skin));
for (i = 0; i < 3; i++) {
MSG_WriteCoord (&sv.signon, SVvector (ent, origin)[i]);
MSG_WriteAngle (&sv.signon, SVvector (ent, angles)[i]);
}
// throw the entity away now
ED_Free (pr, ent);
@ -1358,7 +1369,6 @@ PF_setinfokey (progs_t *pr)
int e1 = NUM_FOR_EDICT (pr, edict);
const char *key = G_STRING (pr, OFS_PARM1);
const char *value = G_STRING (pr, OFS_PARM2);
net_svc_setinfo_t block;
if (e1 == 0) {
if (*value)
@ -1372,11 +1382,12 @@ PF_setinfokey (progs_t *pr)
SV_ExtractFromUserinfo (&svs.clients[e1 - 1]);
if (Info_FilterForKey (key, client_info_filters)) {
block.slot = e1 - 1;
block.key = key;
block.value = Info_ValueForKey (svs.clients[e1 - 1].userinfo, key);
MSG_WriteByte (&sv.reliable_datagram, svc_setinfo);
NET_SVC_SetInfo_Emit (&block, &sv.reliable_datagram);
MSG_WriteByte (&sv.reliable_datagram, e1 - 1);
MSG_WriteString (&sv.reliable_datagram, key);
MSG_WriteString (&sv.reliable_datagram,
Info_ValueForKey (svs.clients[e1 - 1].userinfo,
key));
}
}
}

View file

@ -49,7 +49,6 @@ static const char rcsid[] =
#include "bothdefs.h"
#include "compat.h"
#include "net_svc.h"
#include "server.h"
#include "sv_progs.h"
@ -70,7 +69,6 @@ void
SV_FlushRedirect (void)
{
char send[8000 + 6];
net_svc_print_t block;
if (sv_redirected == RD_PACKET) {
send[0] = 0xff;
@ -82,15 +80,10 @@ SV_FlushRedirect (void)
NET_SendPacket (strlen (send) + 1, send, net_from);
} else if (sv_redirected == RD_CLIENT) {
block.level = PRINT_HIGH;
block.message = outputbuf;
ClientReliableWrite_Begin (host_client, svc_print,
strlen (outputbuf) + 3);
if (host_client->num_backbuf) {
NET_SVC_Print_Emit (&block, &host_client->backbuf);
ClientReliable_FinishWrite (host_client);
} else
NET_SVC_Print_Emit (&block, &host_client->netchan.message);
ClientReliableWrite_Byte (host_client, PRINT_HIGH);
ClientReliableWrite_String (host_client, outputbuf);
}
// clear it
outputbuf[0] = 0;
@ -227,7 +220,6 @@ SV_PrintToClient (client_t *cl, int level, const char *string)
unsigned char *b;
int size;
static int buffer_size;
net_svc_print_t block;
size = strlen (string) + 1;
if (size > buffer_size) {
@ -247,14 +239,9 @@ SV_PrintToClient (client_t *cl, int level, const char *string)
if (*b != 0xFF)
b++;
block.level = level;
block.message = buffer;
ClientReliableWrite_Begin (cl, svc_print, strlen (buffer) + 3);
if (cl->num_backbuf) {
NET_SVC_Print_Emit (&block, &cl->backbuf);
ClientReliable_FinishWrite (cl);
} else
NET_SVC_Print_Emit (&block, &cl->netchan.message);
ClientReliableWrite_Byte (cl, level);
ClientReliableWrite_String (cl, buffer);
}
/*
@ -429,16 +416,16 @@ SV_Multicast (vec3_t origin, int to)
Larger attenuations will drop off. (max 4 attenuation)
*/
void
SV_StartSound (edict_t *entity, int channel, const char *sample,
float volume, float attenuation)
SV_StartSound (edict_t *entity, int channel, const char *sample, int volume,
float attenuation)
{
int i, sound_num;
int ent, field_mask, sound_num, i;
qboolean use_phs;
qboolean reliable = false;
net_svc_sound_t block;
vec3_t origin;
if (volume < 0 || volume > 1)
SV_Error ("SV_StartSound: volume = %f", volume);
if (volume < 0 || volume > 255)
SV_Error ("SV_StartSound: volume = %i", volume);
if (attenuation < 0 || attenuation > 4)
SV_Error ("SV_StartSound: attenuation = %f", attenuation);
@ -457,9 +444,7 @@ SV_StartSound (edict_t *entity, int channel, const char *sample,
return;
}
block.sound_num = sound_num;
block.entity = NUM_FOR_EDICT (&sv_pr_state, entity);
ent = NUM_FOR_EDICT (&sv_pr_state, entity);
if ((channel & 8) || !sv_phs->int_val) // no PHS flag
{
@ -474,34 +459,37 @@ SV_StartSound (edict_t *entity, int channel, const char *sample,
// if (channel == CHAN_BODY || channel == CHAN_VOICE)
// reliable = true;
block.channel = channel;
channel = (ent << 3) | channel;
block.volume = volume;
// 4 * 64 == 256, which overflows a byte. 4 is the stated max for
// it, and I don't want to break any progs, so I just nudge it
// down instead
if (attenuation == 4)
attenuation = 3.999;
block.attenuation = attenuation;
field_mask = 0;
if (volume != DEFAULT_SOUND_PACKET_VOLUME)
channel |= SND_VOLUME;
if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
channel |= SND_ATTENUATION;
// use the entity origin unless it is a bmodel
if (SVfloat (entity, solid) == SOLID_BSP) {
for (i = 0; i < 3; i++)
block.position[i] = SVvector (entity, origin)[i] + 0.5 *
origin[i] = SVvector (entity, origin)[i] + 0.5 *
(SVvector (entity, mins)[i] + SVvector (entity, maxs)[i]);
} else {
VectorCopy (SVvector (entity, origin), block.position);
VectorCopy (SVvector (entity, origin), origin);
}
MSG_WriteByte (&sv.multicast, svc_sound);
NET_SVC_Sound_Emit (&block, &sv.multicast);
MSG_WriteShort (&sv.multicast, channel);
if (channel & SND_VOLUME)
MSG_WriteByte (&sv.multicast, volume);
if (channel & SND_ATTENUATION)
MSG_WriteByte (&sv.multicast, attenuation * 64);
MSG_WriteByte (&sv.multicast, sound_num);
for (i = 0; i < 3; i++)
MSG_WriteCoord (&sv.multicast, origin[i]);
if (use_phs)
SV_Multicast (block.position,
reliable ? MULTICAST_PHS_R : MULTICAST_PHS);
SV_Multicast (origin, reliable ? MULTICAST_PHS_R : MULTICAST_PHS);
else
SV_Multicast (block.position,
reliable ? MULTICAST_ALL_R : MULTICAST_ALL);
SV_Multicast (origin, reliable ? MULTICAST_ALL_R : MULTICAST_ALL);
}
/* FRAME UPDATES */
@ -534,7 +522,6 @@ SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg)
{
edict_t *ent, *other;
int i;
net_svc_damage_t block;
ent = client->edict;
@ -547,14 +534,13 @@ SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg)
// send a damage message if the player got hit this frame
if (SVfloat (ent, dmg_take) || SVfloat (ent, dmg_save)) {
other = PROG_TO_EDICT (&sv_pr_state, SVentity (ent, dmg_inflictor));
block.armor = SVfloat (ent, dmg_save);
block.blood = SVfloat (ent, dmg_take);
for (i = 0; i < 3; i++)
block.from[i] = SVvector (other, origin)[i] + 0.5 *
(SVvector (other, mins)[i] +
SVvector (other, maxs)[i]);
MSG_WriteByte (msg, svc_damage);
NET_SVC_Damage_Emit (&block, msg);
MSG_WriteByte (msg, SVfloat (ent, dmg_save));
MSG_WriteByte (msg, SVfloat (ent, dmg_take));
for (i = 0; i < 3; i++)
MSG_WriteCoord (msg, SVvector (other, origin)[i] + 0.5 *
(SVvector (other, mins)[i] +
SVvector (other, maxs)[i]));
SVfloat (ent, dmg_take) = 0;
SVfloat (ent, dmg_save) = 0;
@ -794,6 +780,7 @@ SV_SendClientMessages (void)
// if the reliable message overflowed, drop the client
if (c->netchan.message.overflowed) {
int i;
extern void Analyze_Server_Packet (byte *data, int len);
byte *data = Hunk_TempAlloc (MAX_MSGLEN + 8);
memset (data, 0, 8);

View file

@ -54,7 +54,6 @@ static const char rcsid[] =
#include "compat.h"
#include "bothdefs.h"
#include "msg_ucmd.h"
#include "net_svc.h"
#include "pmove.h"
#include "server.h"
#include "sv_progs.h"
@ -97,7 +96,7 @@ void
SV_New_f (void)
{
const char *gamedir;
net_svc_serverdata_t block;
int playernum;
if (host_client->state == cs_spawned)
return;
@ -116,23 +115,37 @@ SV_New_f (void)
//NOTE: This doesn't go through ClientReliableWrite since it's before the user
//spawns. These functions are written to not overflow
if (host_client->num_backbuf) {
SV_Printf ("WARNING %s: [SV_New] Back buffered (%d), clearing\n",
SV_Printf ("WARNING %s: [SV_New] Back buffered (%d0, clearing\n",
host_client->name, host_client->netchan.message.cursize);
host_client->num_backbuf = 0;
SZ_Clear (&host_client->netchan.message);
}
// send the serverdata
block.protocolversion = PROTOCOL_VERSION;
block.servercount = svs.spawncount;
block.gamedir = gamedir;
block.playernum = NUM_FOR_EDICT (&sv_pr_state, host_client->edict) - 1;
block.spectator = host_client->spectator;
block.levelname = PR_GetString (&sv_pr_state,
SVstring (sv.edicts, message));
block.movevars = movevars;
MSG_WriteByte (&host_client->netchan.message, svc_serverdata);
NET_SVC_ServerData_Emit (&block, &host_client->netchan.message);
MSG_WriteLong (&host_client->netchan.message, PROTOCOL_VERSION);
MSG_WriteLong (&host_client->netchan.message, svs.spawncount);
MSG_WriteString (&host_client->netchan.message, gamedir);
playernum = NUM_FOR_EDICT (&sv_pr_state, host_client->edict) - 1;
if (host_client->spectator)
playernum |= 128;
MSG_WriteByte (&host_client->netchan.message, playernum);
// send full levelname
MSG_WriteString (&host_client->netchan.message,
PR_GetString (&sv_pr_state, SVstring (sv.edicts, message)));
// send the movevars
MSG_WriteFloat (&host_client->netchan.message, movevars.gravity);
MSG_WriteFloat (&host_client->netchan.message, movevars.stopspeed);
MSG_WriteFloat (&host_client->netchan.message, movevars.maxspeed);
MSG_WriteFloat (&host_client->netchan.message, movevars.spectatormaxspeed);
MSG_WriteFloat (&host_client->netchan.message, movevars.accelerate);
MSG_WriteFloat (&host_client->netchan.message, movevars.airaccelerate);
MSG_WriteFloat (&host_client->netchan.message, movevars.wateraccelerate);
MSG_WriteFloat (&host_client->netchan.message, movevars.friction);
MSG_WriteFloat (&host_client->netchan.message, movevars.waterfriction);
MSG_WriteFloat (&host_client->netchan.message, movevars.entgravity);
// send music
MSG_WriteByte (&host_client->netchan.message, svc_cdtrack);
@ -152,14 +165,12 @@ void
SV_Soundlist_f (void)
{
const char **s;
int i, size;
net_svc_soundlist_t block;
unsigned n;
if (host_client->state != cs_connected) {
SV_Printf ("soundlist not valid -- already spawned\n");
return;
}
// handle the case of a level changing while a client was connecting
if (atoi (Cmd_Argv (1)) != svs.spawncount) {
SV_Printf ("SV_Soundlist_f from different level\n");
@ -167,40 +178,34 @@ SV_Soundlist_f (void)
return;
}
block.startsound = atoi (Cmd_Argv (2));
if (block.startsound >= MAX_SOUNDS) {
n = atoi (Cmd_Argv (2));
if (n >= MAX_SOUNDS) {
SV_Printf ("SV_Soundlist_f: Invalid soundlist index\n");
SV_New_f ();
return;
}
// NOTE: This doesn't go through ClientReliableWrite since it's
// before the user spawns. These functions are written to not
// overflow
//NOTE: This doesn't go through ClientReliableWrite since it's before the user
//spawns. These functions are written to not overflow
if (host_client->num_backbuf) {
SV_Printf ("WARNING %s: [SV_Soundlist] Back buffered (%d), clearing",
SV_Printf ("WARNING %s: [SV_Soundlist] Back buffered (%d0, clearing",
host_client->name, host_client->netchan.message.cursize);
host_client->num_backbuf = 0;
SZ_Clear (&host_client->netchan.message);
}
for (s = sv.sound_precache + 1 + block.startsound, i = 0, size = 0;
*s; i++, s++) {
if (host_client->netchan.message.cursize + size >= (MAX_MSGLEN / 2))
break;
size += strlen (*s) + 1;
block.sounds[i] = *s;
}
block.sounds[i] = "";
MSG_WriteByte (&host_client->netchan.message, svc_soundlist);
MSG_WriteByte (&host_client->netchan.message, n);
for (s = sv.sound_precache + 1 + n;
*s && host_client->netchan.message.cursize < (MAX_MSGLEN / 2);
s++, n++) MSG_WriteString (&host_client->netchan.message, *s);
MSG_WriteByte (&host_client->netchan.message, 0);
// next msg
if (*s)
block.nextsound = block.startsound + i;
MSG_WriteByte (&host_client->netchan.message, n);
else
block.nextsound = 0;
MSG_WriteByte (&host_client->netchan.message, svc_soundlist);
NET_SVC_Soundlist_Emit (&block, &host_client->netchan.message);
MSG_WriteByte (&host_client->netchan.message, 0);
}
/*
@ -210,14 +215,12 @@ void
SV_Modellist_f (void)
{
const char **s;
int i, size;
net_svc_modellist_t block;
unsigned n;
if (host_client->state != cs_connected) {
SV_Printf ("modellist not valid -- already spawned\n");
return;
}
// handle the case of a level changing while a client was connecting
if (atoi (Cmd_Argv (1)) != svs.spawncount) {
SV_Printf ("SV_Modellist_f from different level\n");
@ -225,40 +228,33 @@ SV_Modellist_f (void)
return;
}
block.startmodel = atoi (Cmd_Argv (2));
if (block.startmodel >= MAX_MODELS) {
n = atoi (Cmd_Argv (2));
if (n >= MAX_MODELS) {
SV_Printf ("SV_Modellist_f: Invalid modellist index\n");
SV_New_f ();
return;
}
// NOTE: This doesn't go through ClientReliableWrite since it's
// before the user spawns. These functions are written to not
// overflow
//NOTE: This doesn't go through ClientReliableWrite since it's before the user
//spawns. These functions are written to not overflow
if (host_client->num_backbuf) {
SV_Printf ("WARNING %s: [SV_Modellist] Back buffered (%d), clearing",
SV_Printf ("WARNING %s: [SV_Modellist] Back buffered (%d0, clearing",
host_client->name, host_client->netchan.message.cursize);
host_client->num_backbuf = 0;
SZ_Clear (&host_client->netchan.message);
}
for (s = sv.model_precache + 1 + block.startmodel, i = 0, size = 0;
*s; i++, s++) {
if (host_client->netchan.message.cursize + size >= (MAX_MSGLEN / 2))
break;
size += strlen (*s) + 1;
block.models[i] = *s;
}
block.models[i] = "";
MSG_WriteByte (&host_client->netchan.message, svc_modellist);
MSG_WriteByte (&host_client->netchan.message, n);
for (s = sv.model_precache + 1 + n;
*s && host_client->netchan.message.cursize < (MAX_MSGLEN / 2);
s++, n++) MSG_WriteString (&host_client->netchan.message, *s);
MSG_WriteByte (&host_client->netchan.message, 0);
// next msg
if (*s)
block.nextmodel = block.startmodel + i;
MSG_WriteByte (&host_client->netchan.message, n);
else
block.nextmodel = 0;
MSG_WriteByte (&host_client->netchan.message, svc_modellist);
NET_SVC_Modellist_Emit (&block, &host_client->netchan.message);
MSG_WriteByte (&host_client->netchan.message, 0);
}
/*
@ -566,27 +562,27 @@ void
SV_NextDownload_f (void)
{
byte buffer[1024];
net_svc_download_t block;
int r;
int percent;
int size;
if (!host_client->download)
return;
block.size = host_client->downloadsize - host_client->downloadcount;
if (block.size > 768)
block.size = 768;
block.size = Qread (host_client->download, buffer, block.size);
r = host_client->downloadsize - host_client->downloadcount;
if (r > 768)
r = 768;
r = Qread (host_client->download, buffer, r);
ClientReliableWrite_Begin (host_client, svc_download, 6 + r);
ClientReliableWrite_Short (host_client, r);
host_client->downloadcount += block.size;
block.percent = host_client->downloadcount * 100 /
(host_client->downloadsize ?: 1);
block.data = buffer;
ClientReliableWrite_Begin (host_client, svc_download, 6 + block.size);
if (host_client->num_backbuf) {
NET_SVC_Download_Emit (&block, &host_client->backbuf);
ClientReliable_FinishWrite (host_client);
} else
NET_SVC_Download_Emit (&block, &host_client->netchan.message);
host_client->downloadcount += r;
size = host_client->downloadsize;
if (!size)
size = 1;
percent = host_client->downloadcount * 100 / size;
ClientReliableWrite_Byte (host_client, percent);
ClientReliableWrite_SZ (host_client, buffer, r);
if (host_client->downloadcount != host_client->downloadsize)
return;
@ -695,7 +691,6 @@ SV_BeginDownload_f (void)
int size;
char realname[MAX_OSPATH];
int zip;
net_svc_download_t block;
name = Cmd_Argv (1);
// hacked by zoid to allow more conrol over download
@ -713,14 +708,9 @@ SV_BeginDownload_f (void)
|| (strncmp (name, "maps/", 5) == 0 && !allow_download_maps->int_val)
// MUST be in a subdirectory
|| !strstr (name, "/")) { // don't allow anything with .. path
block.size = -1;
block.percent = 0;
ClientReliableWrite_Begin (host_client, svc_download, 4);
if (host_client->num_backbuf) {
NET_SVC_Download_Emit (&block, &host_client->backbuf);
ClientReliable_FinishWrite (host_client);
} else
NET_SVC_Download_Emit (&block, &host_client->netchan.message);
ClientReliableWrite_Short (host_client, -1);
ClientReliableWrite_Byte (host_client, 0);
return;
}
@ -756,30 +746,19 @@ SV_BeginDownload_f (void)
}
SV_Printf ("Couldn't download %s to %s\n", name, host_client->name);
block.size = -1;
block.percent = 0;
ClientReliableWrite_Begin (host_client, svc_download, 4);
if (host_client->num_backbuf) {
NET_SVC_Download_Emit (&block, &host_client->backbuf);
ClientReliable_FinishWrite (host_client);
} else
NET_SVC_Download_Emit (&block, &host_client->netchan.message);
ClientReliableWrite_Short (host_client, -1);
ClientReliableWrite_Byte (host_client, 0);
return;
}
if (zip && strcmp (realname, name)) {
SV_Printf ("download renamed to %s\n", realname);
block.size = -2;
block.percent = 0;
block.name = realname;
ClientReliableWrite_Begin (host_client, svc_download,
strlen (realname) + 5);
if (host_client->num_backbuf)
NET_SVC_Download_Emit (&block, &host_client->backbuf);
else
NET_SVC_Download_Emit (&block, &host_client->netchan.message);
ClientReliableWrite_Short (host_client, -2);
ClientReliableWrite_Byte (host_client, 0);
ClientReliableWrite_String (host_client, realname);
ClientReliable_FinishWrite (host_client);
}
@ -1136,8 +1115,6 @@ SV_Msg_f (void)
void
SV_SetInfo_f (void)
{
net_svc_setinfo_t block;
if (Cmd_Argc () == 1) {
SV_Printf ("User info settings:\n");
Info_Print (host_client->userinfo);
@ -1176,11 +1153,12 @@ SV_SetInfo_f (void)
SV_ExtractFromUserinfo (host_client);
if (Info_FilterForKey (Cmd_Argv (1), client_info_filters)) {
block.slot = host_client - svs.clients;
block.key = Cmd_Argv (1);
block.value = Info_ValueForKey (host_client->userinfo, Cmd_Argv (1));
MSG_WriteByte (&sv.reliable_datagram, svc_setinfo);
NET_SVC_SetInfo_Emit (&block, &sv.reliable_datagram);
MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
MSG_WriteString (&sv.reliable_datagram, Cmd_Argv (1));
MSG_WriteString (&sv.reliable_datagram,
Info_ValueForKey (host_client->userinfo,
Cmd_Argv (1)));
}
}
@ -1839,7 +1817,7 @@ SV_UserInit (void)
"Toggles the ability of spectators to talk to players");
sv_mapcheck = Cvar_Get ("sv_mapcheck", "1", CVAR_NONE, NULL,
"Toggle the use of map checksumming to check for players who edit maps to cheat");
sv_kickfake = Cvar_Get ("sv_kickfake", "0", CVAR_NONE, NULL,
sv_kickfake = Cvar_Get ("sv_kickfake", "1", CVAR_NONE, NULL,
"Kick users sending to send fake talk messages");
}