low-copy networking code. gives about 3-4% speed boost to overkill (null

renderer).
This commit is contained in:
Bill Currie 2001-12-01 22:16:50 +00:00
parent fc8d9417cb
commit 6a51021f86
10 changed files with 215 additions and 173 deletions

View file

@ -35,6 +35,8 @@
#define NET_TIMINGSMASK 255
struct skin_s;
struct entity_s;
struct entity_state_s;
extern int packet_latency[NET_TIMINGS];
extern int parsecountmod;
@ -51,10 +53,13 @@ extern int cl_gib3index;
int CL_CalcNet (void);
void CL_ParseServerMessage (void);
void CL_NewTranslation (int slot, struct skin_s *skin);
void CL_SetColormap (struct entity_s *ent, int slot);
qboolean CL_CheckOrDownloadFile (const char *filename);
qboolean CL_IsUploading(void);
void CL_NextUpload(void);
void CL_StartUpload (byte *data, int size);
void CL_StopUpload(void);
void CL_EntFromBaseline (struct entity_state_s *es, struct entity_s *ent,
int ind);
#endif

View file

@ -29,6 +29,8 @@
#ifndef _CL_TENT_H
#define _CL_TENT_H
extern struct entity_s cl_entities[MAX_EDICTS];
void CL_TEnts_Init (void);
void CL_ClearEnts (void);
void CL_ClearTEnts (void);

View file

@ -78,7 +78,7 @@ typedef struct player_info_s
struct info_s *userinfo;
// scoreboard information
char name[MAX_SCOREBOARDNAME];
struct info_key_s *name;
float entertime;
int frags;
int ping;

View file

@ -266,7 +266,7 @@
// entity_state_t is the information conveyed from the server
// in an update message
typedef struct
typedef struct entity_state_s
{
int number; // edict index

View file

@ -355,7 +355,7 @@ Cam_CheckHighTarget (void)
j = -1;
for (i = 0, max = -9999; i < MAX_CLIENTS; i++) {
s = &cl.players[i];
if (s->name[0] && !s->spectator && s->frags > max) {
if (s->name && !s->spectator && s->frags > max) {
max = s->frags;
j = i;
}
@ -389,7 +389,7 @@ Cam_Track (usercmd_t *cmd)
return;
if (locked
&& (!cl.players[spec_track].name[0]
&& (!cl.players[spec_track].name
|| cl.players[spec_track].spectator)) {
locked = false;
if (cl_hightrack->int_val)
@ -604,7 +604,7 @@ Cam_FinishMove (usercmd_t *cmd)
i = end;
do {
s = &cl.players[i];
if (s->name[0] && !s->spectator) {
if (s->name && !s->spectator) {
Cam_Lock (i);
return;
}
@ -613,7 +613,7 @@ Cam_FinishMove (usercmd_t *cmd)
// stay on same guy?
i = spec_track;
s = &cl.players[i];
if (s->name[0] && !s->spectator) {
if (s->name && !s->spectator) {
Cam_Lock (i);
return;
}

View file

@ -68,23 +68,24 @@ static struct predicted_player {
#define MAX_PROJECTILES 32
int cl_num_projectiles;
entity_t cl_player_ents[MAX_CLIENTS];
entity_t cl_flag_ents[MAX_CLIENTS];
entity_t cl_projectiles[MAX_PROJECTILES];
entity_t cl_packet_ents[512]; // FIXME: magic number
entity_t cl_entities[MAX_EDICTS];
struct {
model_t *model;
int skinnum;
} cl_entity_model_states[MAX_EDICTS];
void
CL_ClearEnts ()
{
int i;
for (i = 0; i < sizeof (cl_packet_ents) / sizeof (cl_packet_ents[0]); i++)
CL_Init_Entity (&cl_packet_ents[i]);
for (i = 0; i < sizeof (cl_entities) / sizeof (cl_entities[0]); i++)
CL_Init_Entity (&cl_entities[i]);
for (i = 0; i < sizeof (cl_flag_ents) / sizeof (cl_flag_ents[0]); i++)
CL_Init_Entity (&cl_flag_ents[i]);
for (i = 0; i < sizeof (cl_player_ents) / sizeof (cl_player_ents[0]); i++)
CL_Init_Entity (&cl_player_ents[i]);
}
void
@ -129,13 +130,41 @@ CL_NewDlight (int key, vec3_t org, int effects)
int bitcounts[32]; // / just for protocol profiling
void
CL_EntFromBaseline (entity_state_t *es, entity_t *ent, int ind)
{
ent->model = cl.model_precache[es->modelindex];
ent->frame = es->frame;
ent->skinnum = es->skinnum;
VectorCopy (es->origin, ent->origin);
VectorCopy (es->origin, ent->old_origin);
VectorCopy (es->angles, ent->angles);
ent->alpha = es->alpha / 255.0;
ent->scale = es->scale / 16.0;
ent->glow_color = es->glow_color;
ent->glow_size = (char)es->glow_size / 8.0;
if (es->colormod == 255) {
ent->colormod[0] = ent->colormod[1] = ent->colormod[2] = 1;
} else {
ent->colormod[0] = ((es->colormod >> 5) & 7) / 7.0;
ent->colormod[1] = ((es->colormod >> 2) & 7) / 7.0;
ent->colormod[2] = ((es->colormod >> 0) & 3) / 3.0;
}
if (ind >= 0 && ind < MAX_EDICTS) {
cl_entity_model_states[ind].model = ent->model;
cl_entity_model_states[ind].skinnum = ent->skinnum;
CL_SetColormap (ent, es->colormap - 1);
}
}
/*
CL_ParseDelta
Can go from either a baseline or a previous packet_entity
*/
void
CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits)
CL_ParseDelta (entity_state_t *from, entity_state_t *to, entity_t *ent,
int bits, int do_colormap)
{
int i;
@ -164,67 +193,116 @@ CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits)
to->flags = bits;
if (bits & U_MODEL)
if (bits & U_MODEL) {
to->modelindex = MSG_ReadByte (net_message);
ent->model = cl.model_precache[to->modelindex];
}
if (bits & U_FRAME)
if (bits & U_FRAME) {
to->frame = MSG_ReadByte (net_message);
ent->frame = to->frame;
}
if (bits & U_COLORMAP)
to->colormap = MSG_ReadByte (net_message);
if (bits & U_SKIN)
if (bits & U_SKIN) {
to->skinnum = MSG_ReadByte (net_message);
ent->skinnum = to->skinnum;
}
if (bits & U_EFFECTS)
to->effects = MSG_ReadByte (net_message);
if (bits & U_ORIGIN1)
VectorCopy (ent->origin, ent->old_origin);
if (bits & U_ORIGIN1) {
to->origin[0] = MSG_ReadCoord (net_message);
ent->origin[0] = to->origin[0];
}
if (bits & U_ANGLE1)
if (bits & U_ANGLE1) {
to->angles[0] = MSG_ReadAngle (net_message);
ent->angles[0] = to->angles[0];
}
if (bits & U_ORIGIN2)
if (bits & U_ORIGIN2) {
to->origin[1] = MSG_ReadCoord (net_message);
ent->origin[1] = to->origin[1];
}
if (bits & U_ANGLE2)
if (bits & U_ANGLE2) {
to->angles[1] = MSG_ReadAngle (net_message);
ent->angles[1] = to->angles[1];
}
if (bits & U_ORIGIN3)
if (bits & U_ORIGIN3) {
to->origin[2] = MSG_ReadCoord (net_message);
ent->origin[2] = to->origin[2];
}
if (bits & U_ANGLE3)
if (bits & U_ANGLE3) {
to->angles[2] = MSG_ReadAngle (net_message);
ent->angles[2] = to->angles[2];
}
if (bits & U_SOLID) {
// FIXME
}
if (do_colormap) {
int ind = ent - cl_entities;
if (cl_entity_model_states[ind].model != ent->model
|| cl_entity_model_states[ind].skinnum != ent->skinnum) {
cl_entity_model_states[ind].model = ent->model;
cl_entity_model_states[ind].skinnum = ent->skinnum;
CL_SetColormap (ent, to->colormap - 1);
}
}
if (!(bits & U_EXTEND1))
return;
// 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)
if (bits & U_ALPHA) {
to->alpha = MSG_ReadByte (net_message);
if (bits & U_SCALE)
ent->alpha = to->alpha / 255.0;
}
if (bits & U_SCALE) {
to->scale = MSG_ReadByte (net_message);
if (bits & U_EFFECTS2)
ent->scale = to->scale / 16.0;
}
if (bits & U_EFFECTS2) {
to->effects = (to->effects & 0xFF) | (MSG_ReadByte (net_message) << 8);
if (bits & U_GLOWSIZE)
}
if (bits & U_GLOWSIZE) {
to->glow_size = MSG_ReadByte (net_message);
if (bits & U_GLOWCOLOR)
ent->glow_size = (char)to->glow_size * 8.0;
}
if (bits & U_GLOWCOLOR) {
to->glow_color = MSG_ReadByte (net_message);
if (bits & U_COLORMOD)
ent->glow_color = to->glow_color;
}
if (bits & U_COLORMOD) {
to->colormod = MSG_ReadByte (net_message);
if (to->colormod == 255) {
ent->colormod[0] = ent->colormod[1] = ent->colormod[2] = 1;
} else {
ent->colormod[0] = ((to->colormod >> 5) & 7) / 7.0;
ent->colormod[1] = ((to->colormod >> 2) & 7) / 7.0;
ent->colormod[2] = ((to->colormod >> 0) & 3) / 3.0;
}
}
if (!(bits & U_EXTEND2))
return;
if (bits & U_FRAME2)
if (bits & U_FRAME2) {
to->frame = (to->frame & 0xFF) | (MSG_ReadByte (net_message) << 8);
ent->frame = to->frame;
}
// Ender (QSG - End)
}
@ -232,6 +310,7 @@ void
FlushEntityPacket (void)
{
entity_state_t olde, newe;
entity_t fakee;
int word;
Con_DPrintf ("FlushEntityPacket\n");
@ -252,7 +331,7 @@ FlushEntityPacket (void)
if (!word)
break; // done
CL_ParseDelta (&olde, &newe, word);
CL_ParseDelta (&olde, &newe, &fakee, word, 0);
}
}
@ -360,8 +439,10 @@ CL_ParsePacketEntities (qboolean delta)
if (newindex >= MAX_PACKET_ENTITIES)
Host_Error ("CL_ParsePacketEntities: newindex == "
"MAX_PACKET_ENTITIES");
CL_EntFromBaseline (&cl_baselines[newnum], &cl_entities[newnum],
newnum);
CL_ParseDelta (&cl_baselines[newnum], &newp->entities[newindex],
word);
&cl_entities[newnum], word, 1);
newindex++;
continue;
}
@ -372,14 +453,13 @@ CL_ParsePacketEntities (qboolean delta)
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;
}
// Con_Printf ("delta %i\n", newnum);
CL_ParseDelta (&oldp->entities[oldindex],
&newp->entities[newindex], word);
&newp->entities[newindex], &cl_entities[newnum],
word, 1);
newindex++;
oldindex++;
}
@ -397,7 +477,6 @@ CL_LinkPacketEntities (void)
entity_state_t *s1;
model_t *model;
packet_entities_t *pack;
player_info_t *info;
pack = &cl.frames[cls.netchan.incoming_sequence &
UPDATE_MASK].packet_entities;
@ -429,76 +508,20 @@ CL_LinkPacketEntities (void)
if (!ent)
break; // object list is full
*ent = &cl_packet_ents[s1->number];
*ent = &cl_entities[s1->number];
(*ent)->model = model = cl.model_precache[s1->modelindex];
model = (*ent)->model;
// set colormap
if (s1->colormap && (s1->colormap <= MAX_CLIENTS)
&& cl.players[s1->colormap - 1].name[0]
&& !strcmp ((*ent)->model->name, "progs/player.mdl")) {
(*ent)->colormap = cl.players[s1->colormap - 1].translations;
info = &cl.players[s1->colormap - 1];
} else {
(*ent)->colormap = vid.colormap8;
info = NULL;
}
if (info && !info->skin)
Skin_Find (info);
if (info && info->skin) {
(*ent)->skin = Skin_NewTempSkin ();
if ((*ent)->skin) {
i = s1->colormap - 1;
CL_NewTranslation (i, (*ent)->skin);
}
} else {
(*ent)->skin = NULL;
}
// LordHavoc: cleaned up Endy's coding style, and fixed Endy's bugs
// Ender: Extend (Colormod) [QSG - Begin]
// N.B: All messy code below is the sole fault of LordHavoc and
// his futile attempts to save bandwidth. :)
(*ent)->glow_size = s1->glow_size < 128 ? s1->glow_size * 8.0 :
(s1->glow_size - 256) * 8.0;
(*ent)->glow_color = s1->glow_color;
(*ent)->alpha = s1->alpha / 255.0;
(*ent)->scale = s1->scale / 16.0;
if (s1->colormod == 255) {
(*ent)->colormod[0] = (*ent)->colormod[1] =
(*ent)->colormod[2] = 1;
} else {
(*ent)->colormod[0] = (float) ((s1->colormod >> 5) & 7) * (1.0 /
7.0);
(*ent)->colormod[1] = (float) ((s1->colormod >> 2) & 7) * (1.0 /
7.0);
(*ent)->colormod[2] = (float) (s1->colormod & 3) * (1.0 / 3.0);
}
// Ender: Extend (Colormod) [QSG - End]
// set skin
(*ent)->skinnum = s1->skinnum;
// set frame
(*ent)->frame = s1->frame;
if ((*ent)->visframe != r_framecount - 1) {
(*ent)->pose1 = (*ent)->pose2 = -1;
}
(*ent)->visframe = r_framecount;
if (!model)
Host_Error ("null model: %d %s\n", s1->number,
cl.model_precache[s1->modelindex]->name);
if (model->flags & EF_ROTATE) { // rotate binary objects locally
(*ent)->angles[0] = 0;
(*ent)->angles[1] = anglemod (100 * cl.time);
(*ent)->angles[2] = 0;
} else {
VectorCopy(s1->angles, (*ent)->angles);
}
VectorCopy ((*ent)->origin, (*ent)->old_origin);
VectorCopy (s1->origin, (*ent)->origin);
// add automatic particle trails
if (!model->flags)
continue;
@ -599,12 +622,14 @@ CL_ParsePlayerinfo (void)
{
int flags, msec, num, i;
player_state_t *state;
entity_t *ent;
num = MSG_ReadByte (net_message);
if (num > MAX_CLIENTS)
if (num >= MAX_CLIENTS)
Host_Error ("CL_ParsePlayerinfo: bad num");
state = &cl.frames[parsecountmod].playerstate[num];
ent = &cl_entities[num + 1];
state->number = num;
flags = state->flags = MSG_ReadShort (net_message);
@ -613,8 +638,10 @@ CL_ParsePlayerinfo (void)
state->origin[0] = MSG_ReadCoord (net_message);
state->origin[1] = MSG_ReadCoord (net_message);
state->origin[2] = MSG_ReadCoord (net_message);
VectorCopy (state->origin, ent->origin);
state->frame = MSG_ReadByte (net_message);
ent->frame = state->frame;
// the other player's last move was likely some time
// before the packet was sent out, so accurately track
@ -639,11 +666,13 @@ CL_ParsePlayerinfo (void)
else
i = cl_playerindex;
state->modelindex = i;
ent->model = cl.model_precache[i];
if (flags & PF_SKINNUM)
state->skinnum = MSG_ReadByte (net_message);
else
state->skinnum = 0;
ent->skinnum = state->skinnum;
if (flags & PF_EFFECTS)
state->effects = MSG_ReadByte (net_message);
@ -656,6 +685,14 @@ CL_ParsePlayerinfo (void)
state->weaponframe = 0;
VectorCopy (state->command.angles, state->viewangles);
if (cl_entity_model_states[ent - cl_entities].model != ent->model
|| cl_entity_model_states[ent - cl_entities].skinnum != ent->skinnum) {
cl_entity_model_states[ent - cl_entities].model = ent->model;
cl_entity_model_states[ent - cl_entities].skinnum = ent->skinnum;
CL_SetColormap (ent, num);
}
//FIXME: players don't have extend stuff
}
/*
@ -765,7 +802,7 @@ CL_LinkPlayers (void)
// spawn light flashes, even ones coming from invisible objects
if (j == cl.playernum) {
VectorCopy (cl.simorg, org);
r_player_entity = &cl_player_ents[j];
r_player_entity = &cl_entities[j + 1];
} else
VectorCopy (state->origin, org);
@ -795,35 +832,7 @@ CL_LinkPlayers (void)
_ent = R_NewEntity ();
if (!_ent) // object list is full
break;
ent = *_ent = &cl_player_ents[j];
ent->frame = state->frame;
ent->model = cl.model_precache[state->modelindex];
ent->skinnum = state->skinnum;
ent->colormap = info->translations;
if (state->modelindex == cl_playerindex) { //XXX
// use custom skin
if (!info->skin)
Skin_Find (info);
if (info && info->skin) {
ent->skin = Skin_NewTempSkin ();
if (ent->skin) {
CL_NewTranslation (j, ent->skin);
}
} else {
ent->skin = NULL;
}
} else {
ent->skin = NULL;
}
// LordHavoc: more QSG VERSION 2 stuff, FIXME: players don't have
// extend stuff
ent->glow_size = 0;
ent->glow_color = 254;
ent->alpha = 1;
ent->scale = 1;
ent->colormod[0] = ent->colormod[1] = ent->colormod[2] = 1;
ent = *_ent = &cl_entities[j + 1];
// angles
if (j == cl.playernum)
@ -839,18 +848,19 @@ CL_LinkPlayers (void)
ent->angles[ROLL] = 0;
ent->angles[ROLL] = V_CalcRoll (ent->angles, state->velocity) * 4;
// only predict half the move to minimize overruns
msec = 500 * (playertime - state->state_time);
if (msec <= 0 || (!cl_predict_players->int_val)) {
VectorCopy (state->origin, ent->origin);
} else { // predict players movement
state->command.msec = msec = min (msec, 255);
if (cl_predict_players->int_val) {
// only predict half the move to minimize overruns
msec = 500 * (playertime - state->state_time);
if (msec > 0) {
// predict players movement
state->command.msec = msec = min (msec, 255);
oldphysent = pmove.numphysent;
CL_SetSolidPlayers (j);
CL_PredictUsercmd (state, &exact, &state->command, false);
pmove.numphysent = oldphysent;
VectorCopy (exact.origin, ent->origin);
oldphysent = pmove.numphysent;
CL_SetSolidPlayers (j);
CL_PredictUsercmd (state, &exact, &state->command, false);
pmove.numphysent = oldphysent;
VectorCopy (exact.origin, ent->origin);
}
}
if (state->effects & EF_FLAG1)
@ -1033,7 +1043,6 @@ CL_EmitEntities (void)
return;
R_ClearEnts ();
Skin_ClearTempSkins ();
CL_LinkPlayers ();
CL_LinkPacketEntities ();
@ -1046,6 +1055,10 @@ CL_Ents_Init (void)
{
int i;
for (i = 0; i < MAX_CLIENTS; i++)
CL_Init_Entity (&cl_flag_ents[i]);
for (i = 0; i < MAX_PROJECTILES; i++)
CL_Init_Entity (&cl_projectiles[i]);
for (i = 0; i < MAX_EDICTS; i++)
CL_Init_Entity (&cl_entities[i]);
}

View file

@ -416,6 +416,7 @@ CL_ClearState (void)
CL_ClearEnts ();
CL_ClearTEnts ();
Skin_ClearTempSkins ();
R_ClearEfrags ();
R_ClearDlights ();
@ -528,10 +529,10 @@ CL_User_f (void)
uid = atoi (Cmd_Argv (1));
for (i = 0; i < MAX_CLIENTS; i++) {
if (!cl.players[i].name[0])
if (!cl.players[i].name)
continue;
if (cl.players[i].userid == uid
|| !strcmp (cl.players[i].name, Cmd_Argv (1))) {
|| !strcmp (cl.players[i].name->value, Cmd_Argv (1))) {
Info_Print (cl.players[i].userinfo);
return;
}
@ -553,9 +554,9 @@ CL_Users_f (void)
Con_Printf ("userid frags name\n");
Con_Printf ("------ ----- ----\n");
for (i = 0; i < MAX_CLIENTS; i++) {
if (cl.players[i].name[0]) {
if (cl.players[i].name) {
Con_Printf ("%6i %4i %s\n", cl.players[i].userid,
cl.players[i].frags, cl.players[i].name);
cl.players[i].frags, cl.players[i].name->value);
c++;
}
}

View file

@ -800,7 +800,7 @@ CL_ParseModellist (void)
}
void
CL_ParseBaseline (entity_state_t *es)
CL_ParseBaseline (entity_state_t *es, entity_t *ent)
{
int i;
@ -819,6 +819,7 @@ CL_ParseBaseline (entity_state_t *es)
es->glow_color = 254;
es->glow_size = 0;
es->colormod = 255;
CL_EntFromBaseline (es, ent, ent - cl_entities);
}
/*
@ -833,20 +834,11 @@ CL_ParseStatic (void)
entity_t *ent;
entity_state_t es;
CL_ParseBaseline (&es);
if (cl.num_statics >= MAX_STATIC_ENTITIES)
Host_Error ("Too many static entities");
ent = &cl_static_entities[cl.num_statics++];
CL_Init_Entity (ent);
// copy it to the current state
ent->model = cl.model_precache[es.modelindex];
ent->frame = es.frame;
ent->skinnum = es.skinnum;
VectorCopy (es.origin, ent->origin);
VectorCopy (es.angles, ent->angles);
CL_ParseBaseline (&es, ent);
R_AddEfrags (ent);
}
@ -950,13 +942,12 @@ CL_ProcessUserInfo (int slot, player_info_t *player)
COM_StripExtension (s, skin); // FIXME buffer overflow
if (!strequal (s, skin))
Info_SetValueForKey (player->userinfo, "skin", skin, 1);
strncpy (player->name, Info_ValueForKey (player->userinfo, "name"),
sizeof (player->name) - 1);
player->_topcolor = player->_bottomcolor = -1;
player->topcolor = atoi (Info_ValueForKey (player->userinfo, "topcolor"));
player->bottomcolor =
atoi (Info_ValueForKey (player->userinfo, "bottomcolor"));
player->name = Hash_Find (player->userinfo->tab, "name");
while (!(player->team = Hash_Find (player->userinfo->tab, "team")))
Info_SetValueForKey (player->userinfo, "team", "", 1);
while (!(player->skinname = Hash_Find (player->userinfo->tab, "skin")))
@ -971,7 +962,9 @@ CL_ProcessUserInfo (int slot, player_info_t *player)
Skin_Find (player);
Sbar_Changed ();
//XXX CL_NewTranslation (slot);
if (!player->name)
return;
CL_SetColormap (&cl_entities[slot + 1], slot);
}
void
@ -1014,7 +1007,9 @@ CL_SetInfo (void)
strncpy (value, MSG_ReadString (net_message), sizeof (value) - 1);
key[sizeof (value) - 1] = 0;
Con_DPrintf ("SETINFO %s: %s=%s\n", player->name, key, value);
Con_DPrintf ("SETINFO %s: %s=%s\n", player->name ? player->name->value
: "<dead>",
key, value);
if (!player->userinfo)
player->userinfo = Info_ParseString ("", MAX_INFO_STRING);
@ -1276,7 +1271,7 @@ CL_ParseServerMessage (void)
case svc_spawnbaseline:
i = MSG_ReadShort (net_message);
CL_ParseBaseline (&cl_baselines[i]);
CL_ParseBaseline (&cl_baselines[i], &cl_entities[i]);
break;
case svc_spawnstatic:
CL_ParseStatic ();

View file

@ -44,8 +44,10 @@ static const char rcsid[] =
#include "QF/screen.h"
#include "QF/va.h"
#include "bothdefs.h"
#include "cl_parse.h"
#include "cl_skin.h"
#include "cl_tent.h"
#include "client.h"
#include "compat.h"
#include "host.h"
@ -71,7 +73,7 @@ Skin_NextDownload (void)
for (; cls.downloadnumber != MAX_CLIENTS; cls.downloadnumber++) {
sc = &cl.players[cls.downloadnumber];
if (!sc->name[0])
if (!sc->name)
continue;
Skin_Find (sc);
if (noskins->int_val) //XXX FIXME
@ -88,7 +90,7 @@ Skin_NextDownload (void)
// now load them in for real
for (i = 0; i < MAX_CLIENTS; i++) {
sc = &cl.players[i];
if (!sc->name[0])
if (!sc->name)
continue;
Skin_Find (sc);
Skin_Cache (sc->skin);
@ -209,7 +211,7 @@ CL_NewTranslation (int slot, skin_t *skin)
Host_Error ("CL_NewTranslation: slot > MAX_CLIENTS");
player = &cl.players[slot];
if (!player->name[0])
if (!player->name)
return;
if (player->skin && !strequal (player->skinname->value, player->skin->name))
@ -235,3 +237,27 @@ CL_NewTranslation (int slot, skin_t *skin)
// FIXME: breaks cache ownership
}
}
skin_t cl_skins[MAX_EDICTS];
void
CL_SetColormap (entity_t *ent, int slot)
{
player_info_t *info = &cl.players[slot];
if ((unsigned int)slot <= MAX_CLIENTS && info->name
&& ent->model && strequal (ent->model->name, "progs/player.mdl")) {
if (!info->skin)
Skin_Find (info);
if (info->skin) {
ent->skin = &cl_skins[ent - cl_entities];
CL_NewTranslation (slot, ent->skin);
} else {
ent->skin = NULL;
}
ent->colormap = info->translations;
} else {
ent->colormap = vid.colormap8;
ent->skin = NULL;
}
}

View file

@ -366,7 +366,7 @@ Sbar_SortFrags (qboolean includespec)
// sort by frags
scoreboardlines = 0;
for (i = 0; i < MAX_CLIENTS; i++) {
if (cl.players[i].name[0] && (!cl.players[i].spectator || includespec)) {
if (cl.players[i].name && (!cl.players[i].spectator || includespec)) {
fragsort[scoreboardlines] = i;
scoreboardlines++;
if (cl.players[i].spectator)
@ -404,7 +404,7 @@ Sbar_SortTeams (void)
for (i = 0; i < MAX_CLIENTS; i++) {
s = &cl.players[i];
if (!s->name[0])
if (!s->name)
continue;
if (s->spectator)
continue;
@ -589,7 +589,7 @@ Sbar_DrawFrags (void)
for (i = 0; i < l; i++) {
k = fragsort[i];
s = &cl.players[k];
if (!s->name[0])
if (!s->name)
continue;
if (s->spectator)
continue;
@ -739,7 +739,7 @@ Sbar_Draw (int swap)
// Sbar_DrawString (160-14*8+4,4, "SPECTATOR MODE - TRACK CAMERA");
snprintf (st, sizeof (st), "Tracking %-.13s, [JUMP] for next",
cl.players[spec_track].name);
cl.players[spec_track].name->value);
Sbar_DrawString (0, -8, st);
}
} else if (sb_showscores || cl.stats[STAT_HEALTH] <= 0)
@ -957,7 +957,7 @@ Sbar_DeathmatchOverlay (int start)
for (i = 0; i < l && y <= vid.height - 10; i++) {
k = fragsort[i];
s = &cl.players[k];
if (!s->name[0])
if (!s->name)
continue;
// draw ping
@ -983,9 +983,9 @@ Sbar_DeathmatchOverlay (int start)
Draw_String (x + 40, y, "(spectator)");
// draw name
if (cl.teamplay)
Draw_String (x + 152 + 40, y, s->name);
Draw_String (x + 152 + 40, y, s->name->value);
else
Draw_String (x + 152, y, s->name);
Draw_String (x + 152, y, s->name->value);
y += skip;
continue;
}
@ -1031,9 +1031,9 @@ Sbar_DeathmatchOverlay (int start)
}
// draw name
if (cl.teamplay)
Draw_String (x + 152 + 40, y, s->name);
Draw_String (x + 152 + 40, y, s->name->value);
else
Draw_String (x + 152, y, s->name);
Draw_String (x + 152, y, s->name->value);
y += skip;
}
@ -1098,7 +1098,7 @@ Sbar_MiniDeathmatchOverlay (void)
for ( /* */ ; i < scoreboardlines && y < vid.height - 8 + 1; i++) {
k = fragsort[i];
s = &cl.players[k];
if (!s->name[0])
if (!s->name)
continue;
// draw ping
@ -1130,7 +1130,7 @@ Sbar_MiniDeathmatchOverlay (void)
}
// draw name
name[16] = 0;
strncpy (name, s->name, 16);
strncpy (name, s->name->value, 16);
if (cl.teamplay)
Draw_String (x + 48 + 40, y, name);
else