[renderer] Support multiple entity queues

While there's currently only the one still, this will allow the entities
to be multiply queued for multi-pass rendering (eg, shadows). As the
avoidance of putting an entity in the same queue more than once relies
on the entity id, all entities now come from the scene (which is stored
in cl_world in the client code for nq and qw), thus the extensive
changes in the clients.
This commit is contained in:
Bill Currie 2022-03-05 01:48:10 +09:00
parent 6573acbc74
commit d69355f521
53 changed files with 741 additions and 618 deletions

View file

@ -119,7 +119,6 @@ typedef struct vid_render_funcs_s {
void (*R_RemoveEfrags) (entity_t *ent); void (*R_RemoveEfrags) (entity_t *ent);
void (*R_LineGraph) (int x, int y, int *h_vals, int count, int height); void (*R_LineGraph) (int x, int y, int *h_vals, int count, int height);
dlight_t *(*R_AllocDlight) (int key); dlight_t *(*R_AllocDlight) (int key);
entity_t *(*R_AllocEntity) (void);
void (*R_MaxDlightsCheck) (struct cvar_s *var); void (*R_MaxDlightsCheck) (struct cvar_s *var);
void (*R_DecayLights) (double frametime); void (*R_DecayLights) (double frametime);

View file

@ -155,7 +155,6 @@ typedef struct visibility_s {
struct mnode_s *topnode; // bmodels, first world node that struct mnode_s *topnode; // bmodels, first world node that
// splits bmodel, or NULL if not split // splits bmodel, or NULL if not split
// applies to other models, too // applies to other models, too
int visframe; // last frame this entity was
// found in an active leaf // found in an active leaf
int trivial_accept; // view clipping (frustum and depth) int trivial_accept; // view clipping (frustum and depth)
} visibility_t; } visibility_t;

View file

@ -33,6 +33,7 @@
#include "QF/darray.h" #include "QF/darray.h"
#include "QF/qtypes.h" #include "QF/qtypes.h"
#include "QF/set.h"
#include "QF/simd/vec4f.h" #include "QF/simd/vec4f.h"
#include "QF/simd/mat4f.h" #include "QF/simd/mat4f.h"
@ -46,6 +47,38 @@
#include "QF/render.h" //FIXME move entity_t here #include "QF/render.h" //FIXME move entity_t here
typedef struct entqueue_s {
set_t *queued_ents;
entityset_t *ent_queues;
int num_queues;
} entqueue_t;
#define ENTINLINE GNU89INLINE inline
entqueue_t *EntQueue_New (int num_queues);
void EntQueue_Delete (entqueue_t *queue);
ENTINLINE void EntQueue_AddEntity (entqueue_t *queue, entity_t *ent,
int queue_num);
void EntQueue_Clear (entqueue_t *queue);
#undef ENTINLINE
#ifndef IMPLEMENT_ENTITY_Funcs
#define ENTINLINE GNU89INLINE inline
#else
#define ENTINLINE VISIBLE
#endif
ENTINLINE
void
EntQueue_AddEntity (entqueue_t *queue, entity_t *ent, int queue_num)
{
if (!set_is_member (queue->queued_ents, ent->id)) {
// entity ids are negative (ones-complement)
set_add (queue->queued_ents, -ent->id);//FIXME use ~
DARRAY_APPEND (&queue->ent_queues[queue_num], ent);
}
}
///@} ///@}
#endif//__QF_scene_entity_h #endif//__QF_scene_entity_h

View file

@ -31,9 +31,16 @@
#ifndef __client_entities_h #ifndef __client_entities_h
#define __client_entities_h #define __client_entities_h
#include "QF/darray.h"
#include "QF/msg.h"
#include "QF/qtypes.h" #include "QF/qtypes.h"
#include "QF/simd/types.h" #include "QF/simd/types.h"
typedef struct entitystateset_s DARRAY_TYPE (struct entity_state_s)
entitystateset_t;
extern entitystateset_t cl_static_entities;
// entity_state_t is the information conveyed from the server // entity_state_t is the information conveyed from the server
// in an update message // in an update message
typedef struct entity_state_s { typedef struct entity_state_s {

View file

@ -96,15 +96,12 @@ typedef enum TE_qwEffect {
//FIXME find a better way to get this info from the parser //FIXME find a better way to get this info from the parser
typedef struct TEntContext_s { typedef struct TEntContext_s {
vec4f_t simorg; vec4f_t simorg;
struct model_s *worldModel;
int playerEntity; int playerEntity;
} TEntContext_t; } TEntContext_t;
struct msg_s; struct msg_s;
struct entity_s; struct entity_s;
extern struct scene_s *cl_scene;
void CL_TEnts_Init (void); void CL_TEnts_Init (void);
void CL_Init_Entity (struct entity_s *ent); void CL_Init_Entity (struct entity_s *ent);
void CL_ClearTEnts (void); void CL_ClearTEnts (void);

70
include/client/world.h Normal file
View file

@ -0,0 +1,70 @@
/*
world.h
Client world scene management
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2022/3/4
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifndef __client_world_h
#define __client_world_h
#include "QF/darray.h"
#include "QF/msg.h"
#include "QF/qtypes.h"
#include "QF/simd/types.h"
typedef struct modelset_s DARRAY_TYPE (struct model_s *) modelset_t;
typedef struct worldscene_s {
struct scene_s *scene;
struct plitem_s *edicts;
struct plitem_s *worldspawn;
struct model_s *worldmodel;
modelset_t models;
} worldscene_t;
extern worldscene_t cl_world;
struct msg_s;
struct entity_state_s;
void CL_World_Init (void);
// PROTOCOL_FITZQUAKE -- flags for entity baseline messages
#define B_LARGEMODEL (1<<0) // modelindex is short instead of byte
#define B_LARGEFRAME (1<<1) // frame is short instead of byte
#define B_ALPHA (1<<2) // 1 byte, uses ENTALPHA_ENCODE, not sent if ENTALPHA_DEFAULT
void CL_ParseBaseline (struct msg_s *msg, struct entity_state_s *baseline,
int version);
/*
Static entities are non-interactive world objects like torches
*/
void CL_ParseStatic (struct msg_s *msg, int version);
void CL_MapCfg (const char *mapname);
void CL_World_NewMap (const char *mapname, const char *skyname);
#endif//__client_world_h

View file

@ -81,10 +81,6 @@ void R_SetVrect (const vrect_t *pvrect, vrect_t *pvrectin, int lineadj);
void R_LoadSkys (const char *); void R_LoadSkys (const char *);
void R_ClearEfrags (void); void R_ClearEfrags (void);
void R_ClearEnts (void);
void R_EnqueueEntity (struct entity_s *ent);
entity_t *R_AllocEntity (void);
void R_FreeAllEntities (void);
void R_FindNearLights (const vec3_t pos, int count, dlight_t **lights); void R_FindNearLights (const vec3_t pos, int count, dlight_t **lights);
dlight_t *R_AllocDlight (int key); dlight_t *R_AllocDlight (int key);

View file

@ -292,7 +292,7 @@ extern mleaf_t *r_viewleaf;
extern int r_clipflags; extern int r_clipflags;
extern int r_dlightframecount; extern int r_dlightframecount;
extern struct entity_s *r_ent_queue[mod_num_types]; extern struct entqueue_s *r_ent_queue;
struct dlight_s; struct dlight_s;
extern vec3_t lightspot; extern vec3_t lightspot;

View file

@ -10,6 +10,7 @@ libs_client_libQFclient_la_SOURCES= \
libs/client/cl_particles.c \ libs/client/cl_particles.c \
libs/client/cl_temp_entities.c \ libs/client/cl_temp_entities.c \
libs/client/cl_view.c \ libs/client/cl_view.c \
libs/client/cl_world.c \
libs/client/hud.c \ libs/client/hud.c \
libs/client/locs.c \ libs/client/locs.c \
libs/client/old_keys.c libs/client/old_keys.c

View file

@ -31,11 +31,18 @@
# include "config.h" # include "config.h"
#endif #endif
#include "QF/render.h" //FIXME for entity_t #include "QF/msg.h"
#include "QF/scene/entity.h" #include "QF/scene/entity.h"
#include "QF/scene/scene.h"
#include "QF/simd/vec4f.h" #include "QF/simd/vec4f.h"
#include "QF/plugin/vid_render.h" //FIXME
#include "client/entities.h" #include "client/entities.h"
#include "client/temp_entities.h"
entitystateset_t cl_static_entities = DARRAY_STATIC_INIT (32);
/* QW has a max of 512 entities and wants 64 frames of data per entity, plus /* QW has a max of 512 entities and wants 64 frames of data per entity, plus
the baseline data (512 * (64 + 1) = 33280), but NQ has a max of 32000 the baseline data (512 * (64 + 1) = 33280), but NQ has a max of 32000

View file

@ -52,10 +52,11 @@
#include "client/entities.h" #include "client/entities.h"
#include "client/particles.h" #include "client/particles.h"
#include "client/temp_entities.h" #include "client/temp_entities.h"
#include "client/world.h"
typedef struct tent_s { typedef struct tent_s {
struct tent_s *next; struct tent_s *next;
entity_t ent; entity_t *ent;
} tent_t; } tent_t;
typedef struct { typedef struct {
@ -86,7 +87,6 @@ typedef struct tent_obj_s {
static PR_RESMAP (tent_t) temp_entities; static PR_RESMAP (tent_t) temp_entities;
static PR_RESMAP (tent_obj_t) tent_objects; static PR_RESMAP (tent_obj_t) tent_objects;
scene_t *cl_scene;
static tent_obj_t *cl_beams; static tent_obj_t *cl_beams;
static tent_obj_t *cl_explosions; static tent_obj_t *cl_explosions;
@ -137,8 +137,6 @@ CL_TEnts_Precache (int phase)
void void
CL_TEnts_Init (void) CL_TEnts_Init (void)
{ {
cl_scene = Scene_NewScene ();
QFS_GamedirCallback (CL_TEnts_Precache); QFS_GamedirCallback (CL_TEnts_Precache);
CL_TEnts_Precache (1); CL_TEnts_Precache (1);
for (int i = 0; i < 360; i++) { for (int i = 0; i < 360; i++) {
@ -150,12 +148,12 @@ CL_TEnts_Init (void)
void void
CL_Init_Entity (entity_t *ent) CL_Init_Entity (entity_t *ent)
{ {
if (ent->transform) { memset (&ent->animation, 0, sizeof (ent->animation));
Transform_Delete (ent->transform); memset (&ent->visibility, 0, sizeof (ent->visibility));
} memset (&ent->renderer, 0, sizeof (ent->renderer));
memset (ent, 0, sizeof (*ent)); ent->active = 1;
ent->old_origin = (vec4f_t) {};
ent->transform = Transform_New (cl_scene, 0);
ent->renderer.skin = 0; ent->renderer.skin = 0;
QuatSet (1.0, 1.0, 1.0, 1.0, ent->renderer.colormod); QuatSet (1.0, 1.0, 1.0, 1.0, ent->renderer.colormod);
ent->animation.pose1 = ent->animation.pose2 = -1; ent->animation.pose1 = ent->animation.pose2 = -1;
@ -165,9 +163,9 @@ static tent_t *
new_temp_entity (void) new_temp_entity (void)
{ {
tent_t *tent = PR_RESNEW_NC (temp_entities); tent_t *tent = PR_RESNEW_NC (temp_entities);
tent->ent.transform = 0; tent->ent = Scene_CreateEntity (cl_world.scene);
tent->next = 0; tent->next = 0;
CL_Init_Entity (&tent->ent); CL_Init_Entity (tent->ent);
return tent; return tent;
} }
@ -177,7 +175,7 @@ free_temp_entities (tent_t *tents)
tent_t **t = &tents; tent_t **t = &tents;
while (*t) { while (*t) {
Transform_Delete ((*t)->ent.transform);//FIXME reuse? Scene_DestroyEntity (cl_world.scene, (*t)->ent);//FIXME reuse?
t = &(*t)->next; t = &(*t)->next;
} }
*t = temp_entities._free; *t = temp_entities._free;
@ -215,8 +213,8 @@ beam_clear (beam_t *b)
tent_t *t; tent_t *t;
for (t = b->tents; t; t = t->next) { for (t = b->tents; t; t = t->next) {
r_funcs->R_RemoveEfrags (&t->ent); r_funcs->R_RemoveEfrags (t->ent);
t->ent.visibility.efrag = 0; t->ent->visibility.efrag = 0;
} }
free_temp_entities (b->tents); free_temp_entities (b->tents);
b->tents = 0; b->tents = 0;
@ -263,17 +261,17 @@ beam_setup (beam_t *b, qboolean transform, double time, TEntContext_t *ctx)
vec4f_t position = org + d * dist; vec4f_t position = org + d * dist;
d += 1.0; d += 1.0;
tent->ent.renderer.model = b->model; tent->ent->renderer.model = b->model;
if (transform) { if (transform) {
seed = seed * BEAM_SEED_PRIME; seed = seed * BEAM_SEED_PRIME;
Transform_SetLocalTransform (tent->ent.transform, scale, Transform_SetLocalTransform (tent->ent->transform, scale,
qmulf (rotation, qmulf (rotation,
beam_rolls[seed % 360]), beam_rolls[seed % 360]),
position); position);
} else { } else {
Transform_SetLocalPosition (tent->ent.transform, position); Transform_SetLocalPosition (tent->ent->transform, position);
} }
r_funcs->R_AddEfrags (&ctx->worldModel->brush, &tent->ent); r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, tent->ent);
} }
} }
@ -377,8 +375,8 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx,
if (!cl_spr_explod->cache.data) { if (!cl_spr_explod->cache.data) {
cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true); cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true);
} }
ex->tent->ent.renderer.model = cl_spr_explod; ex->tent->ent->renderer.model = cl_spr_explod;
Transform_SetLocalPosition (ex->tent->ent.transform,//FIXME Transform_SetLocalPosition (ex->tent->ent->transform,//FIXME
(vec4f_t) {VectorExpand (position), 1}); (vec4f_t) {VectorExpand (position), 1});
break; break;
case TE_Explosion2: case TE_Explosion2:
@ -601,7 +599,7 @@ CL_UpdateBeams (double time, TEntContext_t *ctx)
// add new entities for the lightning // add new entities for the lightning
for (t = b->tents; t; t = t->next) { for (t = b->tents; t; t = t->next) {
seed = seed * BEAM_SEED_PRIME; seed = seed * BEAM_SEED_PRIME;
Transform_SetLocalRotation (t->ent.transform, Transform_SetLocalRotation (t->ent->transform,
qmulf (b->rotation, qmulf (b->rotation,
beam_rolls[seed % 360])); beam_rolls[seed % 360]));
} }
@ -618,7 +616,7 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx)
for (to = &cl_explosions; *to; ) { for (to = &cl_explosions; *to; ) {
ex = &(*to)->to.ex; ex = &(*to)->to.ex;
ent = &ex->tent->ent; ent = ex->tent->ent;
f = 10 * (time - ex->start); f = 10 * (time - ex->start);
if (f >= ent->renderer.model->numframes) { if (f >= ent->renderer.model->numframes) {
tent_obj_t *_to; tent_obj_t *_to;
@ -634,7 +632,7 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx)
ent->animation.frame = f; ent->animation.frame = f;
if (!ent->visibility.efrag) { if (!ent->visibility.efrag) {
r_funcs->R_AddEfrags (&ctx->worldModel->brush, ent); r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
} }
} }
} }
@ -675,8 +673,8 @@ CL_ClearProjectiles (void)
tent_t *tent; tent_t *tent;
for (tent = cl_projectiles; tent; tent = tent->next) { for (tent = cl_projectiles; tent; tent = tent->next) {
r_funcs->R_RemoveEfrags (&tent->ent); r_funcs->R_RemoveEfrags (tent->ent);
tent->ent.visibility.efrag = 0; tent->ent->visibility.efrag = 0;
} }
free_temp_entities (cl_projectiles); free_temp_entities (cl_projectiles);
cl_projectiles = 0; cl_projectiles = 0;
@ -712,7 +710,7 @@ CL_ParseProjectiles (qmsg_t *net_message, qboolean nail2, TEntContext_t *ctx)
*tail = tent; *tail = tent;
tail = &tent->next; tail = &tent->next;
pr = &tent->ent; pr = tent->ent;
pr->renderer.model = cl_spike; pr->renderer.model = cl_spike;
pr->renderer.skin = 0; pr->renderer.skin = 0;
position[0] = ((bits[0] + ((bits[1] & 15) << 8)) << 1) - 4096; position[0] = ((bits[0] + ((bits[1] & 15) << 8)) << 1) - 4096;
@ -721,9 +719,9 @@ CL_ParseProjectiles (qmsg_t *net_message, qboolean nail2, TEntContext_t *ctx)
angles[0] = (bits[4] >> 4) * (360.0 / 16.0); angles[0] = (bits[4] >> 4) * (360.0 / 16.0);
angles[1] = bits[5] * (360.0 / 256.0); angles[1] = bits[5] * (360.0 / 256.0);
angles[2] = 0; angles[2] = 0;
CL_TransformEntity (&tent->ent, 1, angles, position); CL_TransformEntity (tent->ent, 1, angles, position);
r_funcs->R_AddEfrags (&ctx->worldModel->brush, &tent->ent); r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, tent->ent);
} }
*tail = cl_projectiles; *tail = cl_projectiles;

View file

@ -43,8 +43,8 @@
#include "client/entities.h" #include "client/entities.h"
#include "client/hud.h" #include "client/hud.h"
#include "client/input.h" #include "client/input.h"
#include "client/temp_entities.h"//FIXME for cl_scene
#include "client/view.h" #include "client/view.h"
#include "client/world.h"
/* /*
The view is allowed to move slightly from it's true position for bobbing, The view is allowed to move slightly from it's true position for bobbing,
@ -763,7 +763,7 @@ V_Init (viewstate_t *viewstate)
"Used when you are underwater, hit, have the Ring of " "Used when you are underwater, hit, have the Ring of "
"Shadows, or Quad Damage. (v_cshift r g b intensity)"); "Shadows, or Quad Damage. (v_cshift r g b intensity)");
viewstate->camera_transform = Transform_New (cl_scene, 0); viewstate->camera_transform = Transform_New (cl_world.scene, 0);
} }
void void

224
libs/client/cl_world.c Normal file
View file

@ -0,0 +1,224 @@
/*
cl_entities.c
Client side entity management
Copyright (C) 2012 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2012/6/28
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "QF/cbuf.h"
#include "QF/cmd.h"
#include "QF/idparse.h"
#include "QF/quakefs.h"
#include "QF/plist.h"
#include "QF/progs.h"
#include "QF/msg.h"
#include "QF/scene/entity.h"
#include "QF/scene/scene.h"
#include "QF/simd/vec4f.h"
#include "QF/plugin/vid_render.h" //FIXME
#include "client/entities.h"
#include "client/temp_entities.h"
#include "client/world.h"
worldscene_t cl_world = {
.models = DARRAY_STATIC_INIT (32),
};
void
CL_World_Init (void)
{
cl_world.scene = Scene_NewScene ();
}
void
CL_ParseBaseline (qmsg_t *msg, entity_state_t *baseline, int version)
{
int bits = 0;
if (version == 2)
bits = MSG_ReadByte (msg);
if (bits & B_LARGEMODEL)
baseline->modelindex = MSG_ReadShort (msg);
else
baseline->modelindex = MSG_ReadByte (msg);
if (bits & B_LARGEFRAME)
baseline->frame = MSG_ReadShort (msg);
else
baseline->frame = MSG_ReadByte (msg);
baseline->colormap = MSG_ReadByte (msg);
baseline->skinnum = MSG_ReadByte (msg);
MSG_ReadCoordAngleV (msg, &baseline->origin[0], baseline->angles);
baseline->origin[3] = 1;//FIXME
if (bits & B_ALPHA)
baseline->alpha = MSG_ReadByte (msg);
else
baseline->alpha = 255;//FIXME alpha
baseline->scale = 16;
baseline->glow_size = 0;
baseline->glow_color = 254;
baseline->colormod = 255;
}
void
CL_ParseStatic (qmsg_t *msg, int version)
{
entity_t *ent;
entity_state_t es;
ent = Scene_CreateEntity (cl_world.scene);
CL_Init_Entity (ent);
CL_ParseBaseline (msg, &es, version);
DARRAY_APPEND (&cl_static_entities, es);
// copy it to the current state
ent->renderer.model = cl_world.models.a[es.modelindex];
ent->animation.frame = es.frame;
ent->renderer.skinnum = es.skinnum;
CL_TransformEntity (ent, es.scale / 16.0, es.angles, es.origin);
r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
}
static void
map_cfg (const char *mapname, int all)
{
char *name = malloc (strlen (mapname) + 4 + 1);
cbuf_t *cbuf = Cbuf_New (&id_interp);
QFile *f;
QFS_StripExtension (mapname, name);
strcat (name, ".cfg");
f = QFS_FOpenFile (name);
if (f) {
Qclose (f);
Cmd_Exec_File (cbuf, name, 1);
} else {
Cmd_Exec_File (cbuf, "maps_default.cfg", 1);
}
if (all) {
Cbuf_Execute_Stack (cbuf);
} else {
Cbuf_Execute_Sets (cbuf);
}
free (name);
Cbuf_Delete (cbuf);
}
void
CL_MapCfg (const char *mapname)
{
map_cfg (mapname, 0);
}
static plitem_t *
map_ent (const char *mapname)
{
static progs_t edpr;
char *name = malloc (strlen (mapname) + 4 + 1);
char *buf;
plitem_t *edicts = 0;
QFile *ent_file;
QFS_StripExtension (mapname, name);
strcat (name, ".ent");
ent_file = QFS_VOpenFile (name, 0, cl_world.models.a[1]->vpath);
if ((buf = (char *) QFS_LoadFile (ent_file, 0))) {
edicts = ED_Parse (&edpr, buf);
free (buf);
} else {
edicts = ED_Parse (&edpr, cl_world.models.a[1]->brush.entities);
}
free (name);
return edicts;
}
static void
CL_LoadSky (const char *name)
{
plitem_t *worldspawn = cl_world.worldspawn;
plitem_t *item;
static const char *sky_keys[] = {
"sky", // Q2/DarkPlaces
"skyname", // old QF
"qlsky", // QuakeLives
0
};
if (!name) {
if (!worldspawn) {
r_funcs->R_LoadSkys (0);
return;
}
for (const char **key = sky_keys; *key; key++) {
if ((item = PL_ObjectForKey (cl_world.worldspawn, *key))) {
name = PL_String (item);
break;
}
}
}
r_funcs->R_LoadSkys (name);
}
void
CL_World_NewMap (const char *mapname, const char *skyname)
{
cl_static_entities.size = 0;
r_funcs->R_NewMap (cl_world.worldmodel,
cl_world.models.a, cl_world.models.size);
if (cl_world.models.a[1] && cl_world.models.a[1]->brush.entities) {
if (cl_world.edicts) {
PL_Free (cl_world.edicts);
}
cl_world.edicts = map_ent (mapname);
if (cl_world.edicts) {
cl_world.worldspawn = PL_ObjectAtIndex (cl_world.edicts, 0);
CL_LoadSky (skyname);
if (r_funcs->Fog_ParseWorldspawn)
r_funcs->Fog_ParseWorldspawn (cl_world.worldspawn);
}
}
map_cfg (mapname, 1);
}

View file

@ -9,6 +9,7 @@ libs_scene_libQFscene_la_LIBADD= $(scene_deps)
libs_scene_libQFscene_la_DEPENDENCIES= $(scene_deps) libs_scene_libQFscene_la_DEPENDENCIES= $(scene_deps)
libs_scene_libQFscene_la_SOURCES= \ libs_scene_libQFscene_la_SOURCES= \
libs/scene/camera.c \ libs/scene/camera.c \
libs/scene/entity.c \
libs/scene/hierarchy.c \ libs/scene/hierarchy.c \
libs/scene/scene.c \ libs/scene/scene.c \
libs/scene/transform.c libs/scene/transform.c

71
libs/scene/entity.c Normal file
View file

@ -0,0 +1,71 @@
/*
entity.c
Entity management
Copyright (C) 2022 Bill Currke
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "QF/set.h"
#define IMPLEMENT_ENTITY_Funcs
#include "QF/scene/entity.h"
#include "QF/scene/scene.h"
#include "scn_internal.h"
entqueue_t *
EntQueue_New (int num_queues)
{
int size = sizeof (entqueue_t) + num_queues * sizeof (entityset_t);
entqueue_t *queue = calloc (1, size);
queue->queued_ents = set_new ();
queue->ent_queues = (entityset_t *) (queue + 1);
queue->num_queues = num_queues;
for (int i = 0; i < num_queues; i++) {
queue->ent_queues[i].grow = 64;
}
return queue;
}
void
EntQueue_Delete (entqueue_t *queue)
{
for (int i = 0; i < queue->num_queues; i++) {
DARRAY_CLEAR (&queue->ent_queues[i]);
}
set_delete (queue->queued_ents);
free (queue);
}
void
EntQueue_Clear (entqueue_t *queue)
{
for (int i = 0; i < queue->num_queues; i++) {
queue->ent_queues[i].size = 0;
}
set_empty (queue->queued_ents);
}

View file

@ -551,7 +551,6 @@ gl_overbright_f (cvar_t *var)
{ {
int num; int num;
model_t *m; model_t *m;
entity_t *ent;
mod_brush_t *brush; mod_brush_t *brush;
if (!var) if (!var)
@ -598,7 +597,8 @@ gl_overbright_f (cvar_t *var)
if (!gl_R_BuildLightMap) if (!gl_R_BuildLightMap)
return; return;
for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) { for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { \
entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; \
m = ent->renderer.model; m = ent->renderer.model;
if (m->path[0] == '*') if (m->path[0] == '*')
continue; continue;

View file

@ -193,8 +193,6 @@ gl_R_RotateForEntity (entity_t *e)
static void static void
R_DrawEntitiesOnList (void) R_DrawEntitiesOnList (void)
{ {
entity_t *ent;
if (!r_drawentities->int_val) if (!r_drawentities->int_val)
return; return;
@ -220,7 +218,8 @@ R_DrawEntitiesOnList (void)
qfglEnable (GL_NORMALIZE); qfglEnable (GL_NORMALIZE);
} }
for (ent = r_ent_queue[mod_alias]; ent; ent = ent->next) { for (size_t i = 0; i < r_ent_queue->ent_queues[mod_alias].size; i++) { \
entity_t *ent = r_ent_queue->ent_queues[mod_alias].a[i]; \
gl_R_DrawAliasModel (ent); gl_R_DrawAliasModel (ent);
} }
qfglColor3ubv (color_white); qfglColor3ubv (color_white);
@ -248,7 +247,8 @@ R_DrawEntitiesOnList (void)
qglActiveTexture (gl_mtex_enum + 0); qglActiveTexture (gl_mtex_enum + 0);
} }
for (ent = r_ent_queue[mod_iqm]; ent; ent = ent->next) { for (size_t i = 0; i < r_ent_queue->ent_queues[mod_iqm].size; i++) { \
entity_t *ent = r_ent_queue->ent_queues[mod_iqm].a[i]; \
gl_R_DrawIQMModel (ent); gl_R_DrawIQMModel (ent);
} }
qfglColor3ubv (color_white); qfglColor3ubv (color_white);
@ -257,7 +257,8 @@ R_DrawEntitiesOnList (void)
qfglEnable (GL_ALPHA_TEST); qfglEnable (GL_ALPHA_TEST);
if (gl_va_capable) if (gl_va_capable)
qfglInterleavedArrays (GL_T2F_C4UB_V3F, 0, gl_spriteVertexArray); qfglInterleavedArrays (GL_T2F_C4UB_V3F, 0, gl_spriteVertexArray);
for (ent = r_ent_queue[mod_sprite]; ent; ent = ent->next) { for (size_t i = 0; i < r_ent_queue->ent_queues[mod_sprite].size; i++) { \
entity_t *ent = r_ent_queue->ent_queues[mod_sprite].a[i]; \
R_DrawSpriteModel (ent); R_DrawSpriteModel (ent);
} }
qfglDisable (GL_ALPHA_TEST); qfglDisable (GL_ALPHA_TEST);
@ -328,7 +329,7 @@ void
gl_R_SetupFrame (void) gl_R_SetupFrame (void)
{ {
R_AnimateLight (); R_AnimateLight ();
R_ClearEnts (); EntQueue_Clear (r_ent_queue);
r_framecount++; r_framecount++;
gl_Fog_SetupFrame (); gl_Fog_SetupFrame ();

View file

@ -61,6 +61,8 @@
#include "QF/GL/qf_textures.h" #include "QF/GL/qf_textures.h"
#include "QF/GL/qf_vid.h" #include "QF/GL/qf_vid.h"
#include "QF/scene/entity.h"
#include "mod_internal.h" #include "mod_internal.h"
#include "r_internal.h" #include "r_internal.h"
#include "varrays.h" #include "varrays.h"
@ -140,6 +142,7 @@ gl_R_LoadSky_f (void)
void void
gl_R_Init (void) gl_R_Init (void)
{ {
r_ent_queue = EntQueue_New (mod_num_types);
R_Init_Cvars (); R_Init_Cvars ();
gl_R_Particles_Init_Cvars (); gl_R_Particles_Init_Cvars ();
@ -191,8 +194,6 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
r_worldentity.renderer.model = worldmodel; r_worldentity.renderer.model = worldmodel;
brush = &worldmodel->brush; brush = &worldmodel->brush;
R_FreeAllEntities ();
// clear out efrags in case the level hasn't been reloaded // clear out efrags in case the level hasn't been reloaded
for (unsigned i = 0; i < brush->modleafs; i++) for (unsigned i = 0; i < brush->modleafs; i++)
brush->leafs[i].efrags = NULL; brush->leafs[i].efrags = NULL;

View file

@ -740,8 +740,8 @@ gl_R_DrawWorld (void)
R_VisitWorldNodes (&bctx); R_VisitWorldNodes (&bctx);
if (r_drawentities->int_val) { if (r_drawentities->int_val) {
entity_t *ent; for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { \
for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) { entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; \
gl_R_DrawBrushModel (ent); gl_R_DrawBrushModel (ent);
} }
} }

View file

@ -1149,8 +1149,8 @@ glsl_R_DrawWorld (void)
R_VisitWorldNodes (&bctx); R_VisitWorldNodes (&bctx);
if (r_drawentities->int_val) { if (r_drawentities->int_val) {
entity_t *ent; for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) {
for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) { entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i];
R_DrawBrushModel (ent); R_DrawBrushModel (ent);
} }
} }

View file

@ -48,6 +48,8 @@
#include "QF/screen.h" #include "QF/screen.h"
#include "QF/sys.h" #include "QF/sys.h"
#include "QF/scene/entity.h"
#include "QF/GLSL/defines.h" #include "QF/GLSL/defines.h"
#include "QF/GLSL/funcs.h" #include "QF/GLSL/funcs.h"
#include "QF/GLSL/qf_alias.h" #include "QF/GLSL/qf_alias.h"
@ -95,7 +97,7 @@ void
glsl_R_SetupFrame (void) glsl_R_SetupFrame (void)
{ {
R_AnimateLight (); R_AnimateLight ();
R_ClearEnts (); EntQueue_Clear (r_ent_queue);
r_framecount++; r_framecount++;
VectorCopy (r_refdef.viewposition, r_origin); VectorCopy (r_refdef.viewposition, r_origin);
@ -141,7 +143,6 @@ R_SetupView (void)
static void static void
R_RenderEntities (void) R_RenderEntities (void)
{ {
entity_t *ent;
int begun; int begun;
if (!r_drawentities->int_val) if (!r_drawentities->int_val)
@ -149,7 +150,9 @@ R_RenderEntities (void)
#define RE_LOOP(type_name, Type) \ #define RE_LOOP(type_name, Type) \
do { \ do { \
begun = 0; \ begun = 0; \
for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \ for (size_t i = 0; i < r_ent_queue->ent_queues[mod_##type_name].size; \
i++) { \
entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \
if (!begun) { \ if (!begun) { \
glsl_R_##Type##Begin (); \ glsl_R_##Type##Begin (); \
begun = 1; \ begun = 1; \
@ -237,6 +240,7 @@ glsl_R_RenderView (void)
void void
glsl_R_Init (void) glsl_R_Init (void)
{ {
r_ent_queue = EntQueue_New (mod_num_types);
Cmd_AddCommand ("timerefresh", glsl_R_TimeRefresh_f, Cmd_AddCommand ("timerefresh", glsl_R_TimeRefresh_f,
"Test the current refresh rate for the current location."); "Test the current refresh rate for the current location.");
R_Init_Cvars (); R_Init_Cvars ();
@ -267,7 +271,6 @@ glsl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
r_viewleaf = NULL; r_viewleaf = NULL;
R_MarkLeaves (); R_MarkLeaves ();
R_FreeAllEntities ();
R_ClearParticles (); R_ClearParticles ();
glsl_R_RegisterTextures (models, num_models); glsl_R_RegisterTextures (models, num_models);
glsl_R_BuildLightmaps (models, num_models); glsl_R_BuildLightmaps (models, num_models);

View file

@ -235,11 +235,7 @@ R_StoreEfrags (const efrag_t *efrag)
case mod_brush: case mod_brush:
case mod_sprite: case mod_sprite:
case mod_iqm: case mod_iqm:
if (ent->visibility.visframe != r_framecount) { EntQueue_AddEntity (r_ent_queue, ent, model->type);
R_EnqueueEntity (ent);
// mark that we've recorded this entity for this frame
ent->visibility.visframe = r_framecount;
}
efrag = efrag->leafnext; efrag = efrag->leafnext;
break; break;

View file

@ -48,100 +48,7 @@
#include "r_internal.h" #include "r_internal.h"
#define ENT_POOL_SIZE 32 entqueue_t *r_ent_queue;
typedef struct entity_pool_s {
struct entity_pool_s *next;
entity_t entities[ENT_POOL_SIZE];
} entity_pool_t;
entity_t *r_ent_queue[mod_num_types];
static entity_t **vis_tail[mod_num_types] = {
[mod_brush] &r_ent_queue[mod_brush],
[mod_sprite] &r_ent_queue[mod_sprite],
[mod_alias] &r_ent_queue[mod_alias],
[mod_iqm] &r_ent_queue[mod_iqm],
};
static entity_pool_t *entity_pools = 0;
static entity_pool_t **entpool_tail = &entity_pools;
static entity_t *free_entities;
entity_t *
R_AllocEntity (void)
{
entity_pool_t *pool;
entity_t *ent;
int i;
if ((ent = free_entities)) {
free_entities = ent->next;
ent->next = 0;
ent->transform = 0;
return ent;
}
pool = malloc (sizeof (entity_pool_t));
pool->next = 0;
*entpool_tail = pool;
entpool_tail = &pool->next;
for (ent = pool->entities, i = 0; i < ENT_POOL_SIZE - 1; i++, ent++) {
ent->next = ent + 1;
ent->transform = 0;
}
ent->next = 0;
ent->transform = 0;
free_entities = pool->entities;
return R_AllocEntity ();
}
void
R_FreeAllEntities (void)
{
entity_pool_t *pool;
entity_t *ent;
int i;
for (pool = entity_pools; pool; pool = pool->next) {
for (ent = pool->entities, i = 0; i < ENT_POOL_SIZE - 1; i++, ent++) {
ent->next = ent + 1;
if (ent->transform) {
Transform_Delete (ent->transform);
ent->transform = 0;
}
}
ent->next = pool->next ? pool->next->entities : 0;
if (ent->transform) {
Transform_Delete (ent->transform);
ent->transform = 0;
}
}
free_entities = entity_pools ? entity_pools->entities : 0;
}
void
R_ClearEnts (void)
{
for (int i = 0; i < mod_num_types; i++) {
r_ent_queue[i] = 0;
vis_tail[i] = &r_ent_queue[i];
}
}
void
R_EnqueueEntity (entity_t *ent)
{
modtype_t type = ent->renderer.model->type;
if (type < 0 || type >= mod_num_types) {
Sys_Error ("R_EnqueueEntity: Bad entity model type %d", type);
}
ent->next = 0;
*vis_tail[type] = ent;
vis_tail[type] = &ent->next;
}
float float
R_EntityBlend (animation_t *animation, int pose, float interval) R_EntityBlend (animation_t *animation, int pose, float interval)

View file

@ -117,6 +117,8 @@ sw_R_Init (void)
{ {
int dummy; int dummy;
r_ent_queue = EntQueue_New (mod_num_types);
// get stack position so we can guess if we are going to overflow // get stack position so we can guess if we are going to overflow
r_stack_start = (byte *) & dummy; r_stack_start = (byte *) & dummy;
@ -167,8 +169,6 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
memset (&r_worldentity, 0, sizeof (r_worldentity)); memset (&r_worldentity, 0, sizeof (r_worldentity));
r_worldentity.renderer.model = worldmodel; r_worldentity.renderer.model = worldmodel;
R_FreeAllEntities ();
// clear out efrags in case the level hasn't been reloaded // clear out efrags in case the level hasn't been reloaded
for (unsigned i = 0; i < brush->modleafs; i++) for (unsigned i = 0; i < brush->modleafs; i++)
brush->leafs[i].efrags = NULL; brush->leafs[i].efrags = NULL;
@ -418,14 +418,14 @@ draw_iqm_entity (entity_t *ent)
static void static void
R_DrawEntitiesOnList (void) R_DrawEntitiesOnList (void)
{ {
entity_t *ent;
if (!r_drawentities->int_val) if (!r_drawentities->int_val)
return; return;
#define RE_LOOP(type_name) \ #define RE_LOOP(type_name) \
do { \ do { \
for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \ for (size_t i = 0; i < r_ent_queue->ent_queues[mod_##type_name].size; \
i++) { \
entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \
VectorCopy (Transform_GetWorldPosition (ent->transform), \ VectorCopy (Transform_GetWorldPosition (ent->transform), \
r_entorigin); \ r_entorigin); \
currententity = ent; \ currententity = ent; \
@ -566,7 +566,6 @@ R_DrawBEntitiesOnList (void)
vec3_t origin; vec3_t origin;
model_t *clmodel; model_t *clmodel;
float minmaxs[6]; float minmaxs[6];
entity_t *ent;
if (!r_drawentities->int_val) if (!r_drawentities->int_val)
return; return;
@ -574,12 +573,12 @@ R_DrawBEntitiesOnList (void)
VectorCopy (modelorg, oldorigin); VectorCopy (modelorg, oldorigin);
insubmodel = true; insubmodel = true;
for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) { for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) {
entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i];
currententity = ent; currententity = ent;
VectorCopy (Transform_GetWorldPosition (currententity->transform), VectorCopy (Transform_GetWorldPosition (ent->transform), origin);
origin); clmodel = ent->renderer.model;
clmodel = currententity->renderer.model;
// see if the bounding box lets us trivially reject, also // see if the bounding box lets us trivially reject, also
// sets trivial accept status // sets trivial accept status
@ -626,8 +625,8 @@ R_DrawBEntitiesOnList (void)
if (r_drawpolys | r_drawculledpolys) { if (r_drawpolys | r_drawculledpolys) {
R_ZDrawSubmodelPolys (clmodel); R_ZDrawSubmodelPolys (clmodel);
} else { } else {
if (currententity->visibility.topnode) { if (ent->visibility.topnode) {
mnode_t *topnode = currententity->visibility.topnode; mnode_t *topnode = ent->visibility.topnode;
if (topnode->contents >= 0) { if (topnode->contents >= 0) {
// not a leaf; has to be clipped to the world // not a leaf; has to be clipped to the world

View file

@ -35,6 +35,8 @@
#include "QF/sys.h" #include "QF/sys.h"
#include "QF/ui/view.h" #include "QF/ui/view.h"
#include "QF/scene/entity.h"
#include "compat.h" #include "compat.h"
#include "r_internal.h" #include "r_internal.h"
#include "vid_internal.h" #include "vid_internal.h"
@ -224,7 +226,7 @@ R_SetupFrame (void)
R_CheckVariables (); R_CheckVariables ();
R_AnimateLight (); R_AnimateLight ();
R_ClearEnts (); EntQueue_Clear (r_ent_queue);
r_framecount++; r_framecount++;
numbtofpolys = 0; numbtofpolys = 0;

View file

@ -142,6 +142,8 @@ sw32_R_Init (void)
{ {
int dummy; int dummy;
r_ent_queue = EntQueue_New (mod_num_types);
// get stack position so we can guess if we are going to overflow // get stack position so we can guess if we are going to overflow
r_stack_start = (byte *) & dummy; r_stack_start = (byte *) & dummy;
@ -182,8 +184,6 @@ sw32_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
memset (&r_worldentity, 0, sizeof (r_worldentity)); memset (&r_worldentity, 0, sizeof (r_worldentity));
r_worldentity.renderer.model = worldmodel; r_worldentity.renderer.model = worldmodel;
R_FreeAllEntities ();
// clear out efrags in case the level hasn't been reloaded // clear out efrags in case the level hasn't been reloaded
for (unsigned i = 0; i < brush->modleafs; i++) for (unsigned i = 0; i < brush->modleafs; i++)
brush->leafs[i].efrags = NULL; brush->leafs[i].efrags = NULL;
@ -425,14 +425,14 @@ draw_iqm_entity (entity_t *ent)
static void static void
R_DrawEntitiesOnList (void) R_DrawEntitiesOnList (void)
{ {
entity_t *ent;
if (!r_drawentities->int_val) if (!r_drawentities->int_val)
return; return;
#define RE_LOOP(type_name) \ #define RE_LOOP(type_name) \
do { \ do { \
for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \ for (size_t i = 0; i < r_ent_queue->ent_queues[mod_##type_name].size; \
i++) { \
entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \
VectorCopy (Transform_GetWorldPosition (ent->transform), \ VectorCopy (Transform_GetWorldPosition (ent->transform), \
r_entorigin); \ r_entorigin); \
currententity = ent; \ currententity = ent; \
@ -572,7 +572,6 @@ R_DrawBEntitiesOnList (void)
vec3_t origin; vec3_t origin;
model_t *clmodel; model_t *clmodel;
float minmaxs[6]; float minmaxs[6];
entity_t *ent;
if (!r_drawentities->int_val) if (!r_drawentities->int_val)
return; return;
@ -580,12 +579,12 @@ R_DrawBEntitiesOnList (void)
VectorCopy (modelorg, oldorigin); VectorCopy (modelorg, oldorigin);
insubmodel = true; insubmodel = true;
for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) { for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) {
entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i];
currententity = ent; currententity = ent;
VectorCopy (Transform_GetWorldPosition (currententity->transform), VectorCopy (Transform_GetWorldPosition (ent->transform), origin);
origin); clmodel = ent->renderer.model;
clmodel = currententity->renderer.model;
// see if the bounding box lets us trivially reject, also // see if the bounding box lets us trivially reject, also
// sets trivial accept status // sets trivial accept status
@ -632,8 +631,8 @@ R_DrawBEntitiesOnList (void)
if (sw32_r_drawpolys | sw32_r_drawculledpolys) { if (sw32_r_drawpolys | sw32_r_drawculledpolys) {
sw32_R_ZDrawSubmodelPolys (clmodel); sw32_R_ZDrawSubmodelPolys (clmodel);
} else { } else {
if (currententity->visibility.topnode) { if (ent->visibility.topnode) {
mnode_t *topnode = currententity->visibility.topnode; mnode_t *topnode = ent->visibility.topnode;
if (topnode->contents >= 0) { if (topnode->contents >= 0) {
// not a leaf; has to be clipped to the world // not a leaf; has to be clipped to the world

View file

@ -38,6 +38,8 @@
#include "QF/sys.h" #include "QF/sys.h"
#include "QF/ui/view.h" #include "QF/ui/view.h"
#include "QF/scene/entity.h"
#include "compat.h" #include "compat.h"
#include "r_internal.h" #include "r_internal.h"
#include "vid_internal.h" #include "vid_internal.h"
@ -220,7 +222,7 @@ sw32_R_SetupFrame (void)
R_CheckVariables (); R_CheckVariables ();
R_AnimateLight (); R_AnimateLight ();
R_ClearEnts (); EntQueue_Clear (r_ent_queue);
r_framecount++; r_framecount++;
sw32_numbtofpolys = 0; sw32_numbtofpolys = 0;

View file

@ -152,7 +152,6 @@ vid_render_funcs_t gl_vid_render_funcs = {
R_RemoveEfrags, R_RemoveEfrags,
gl_R_LineGraph, gl_R_LineGraph,
R_AllocDlight, R_AllocDlight,
R_AllocEntity,
R_MaxDlightsCheck, R_MaxDlightsCheck,
R_DecayLights, R_DecayLights,
gl_R_ViewChanged, gl_R_ViewChanged,

View file

@ -151,7 +151,6 @@ vid_render_funcs_t glsl_vid_render_funcs = {
R_RemoveEfrags, R_RemoveEfrags,
glsl_R_LineGraph, glsl_R_LineGraph,
R_AllocDlight, R_AllocDlight,
R_AllocEntity,
R_MaxDlightsCheck, R_MaxDlightsCheck,
R_DecayLights, R_DecayLights,
glsl_R_ViewChanged, glsl_R_ViewChanged,

View file

@ -148,7 +148,6 @@ vid_render_funcs_t sw_vid_render_funcs = {
R_RemoveEfrags, R_RemoveEfrags,
R_LineGraph, R_LineGraph,
R_AllocDlight, R_AllocDlight,
R_AllocEntity,
R_MaxDlightsCheck, R_MaxDlightsCheck,
R_DecayLights, R_DecayLights,
R_ViewChanged, R_ViewChanged,

View file

@ -153,7 +153,6 @@ vid_render_funcs_t sw32_vid_render_funcs = {
R_RemoveEfrags, R_RemoveEfrags,
sw32_R_LineGraph, sw32_R_LineGraph,
R_AllocDlight, R_AllocDlight,
R_AllocEntity,
R_MaxDlightsCheck, R_MaxDlightsCheck,
R_DecayLights, R_DecayLights,
sw32_R_ViewChanged, sw32_R_ViewChanged,

View file

@ -61,6 +61,8 @@
#include "QF/Vulkan/swapchain.h" #include "QF/Vulkan/swapchain.h"
#include "QF/ui/view.h" #include "QF/ui/view.h"
#include "QF/scene/entity.h"
#include "mod_internal.h" #include "mod_internal.h"
#include "r_internal.h" #include "r_internal.h"
#include "vid_internal.h" #include "vid_internal.h"
@ -100,6 +102,7 @@ vulkan_ParticleSystem (void)
static void static void
vulkan_R_Init (void) vulkan_R_Init (void)
{ {
r_ent_queue = EntQueue_New (mod_num_types);
Vulkan_CreateStagingBuffers (vulkan_ctx); Vulkan_CreateStagingBuffers (vulkan_ctx);
Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateSwapchain (vulkan_ctx);
Vulkan_CreateFrames (vulkan_ctx); Vulkan_CreateFrames (vulkan_ctx);
@ -679,7 +682,6 @@ vid_render_funcs_t vulkan_vid_render_funcs = {
R_RemoveEfrags, R_RemoveEfrags,
vulkan_R_LineGraph, vulkan_R_LineGraph,
R_AllocDlight, R_AllocDlight,
R_AllocEntity,
R_MaxDlightsCheck, R_MaxDlightsCheck,
R_DecayLights, R_DecayLights,
vulkan_R_ViewChanged, vulkan_R_ViewChanged,

View file

@ -1039,8 +1039,8 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame)
R_VisitWorldNodes (brush, ctx); R_VisitWorldNodes (brush, ctx);
if (r_drawentities->int_val) { if (r_drawentities->int_val) {
entity_t *ent; for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) {
for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) { entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i];
R_DrawBrushModel (ent, ctx); R_DrawBrushModel (ent, ctx);
} }
} }

View file

@ -45,6 +45,8 @@
#include "QF/screen.h" #include "QF/screen.h"
#include "QF/sys.h" #include "QF/sys.h"
#include "QF/scene/entity.h"
#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/qf_vid.h"
#include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_alias.h"
#include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_bsp.h"
@ -65,7 +67,7 @@ static void
setup_frame (vulkan_ctx_t *ctx) setup_frame (vulkan_ctx_t *ctx)
{ {
R_AnimateLight (); R_AnimateLight ();
R_ClearEnts (); EntQueue_Clear (r_ent_queue);
r_framecount++; r_framecount++;
VectorCopy (r_refdef.viewposition, r_origin); VectorCopy (r_refdef.viewposition, r_origin);
@ -85,9 +87,10 @@ Vulkan_RenderEntities (qfv_renderframe_t *rFrame)
return; return;
#define RE_LOOP(type_name, Type) \ #define RE_LOOP(type_name, Type) \
do { \ do { \
entity_t *ent; \
int begun = 0; \ int begun = 0; \
for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \ for (size_t i = 0; i < r_ent_queue->ent_queues[mod_##type_name].size; \
i++) { \
entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \
if (!begun) { \ if (!begun) { \
Vulkan_##Type##Begin (rFrame); \ Vulkan_##Type##Begin (rFrame); \
begun = 1; \ begun = 1; \
@ -122,7 +125,7 @@ Vulkan_DrawViewModel (vulkan_ctx_t *ctx)
|| !ent->renderer.model) || !ent->renderer.model)
return; return;
R_EnqueueEntity (ent); EntQueue_AddEntity (r_ent_queue, ent, ent->renderer.model->type);
} }
void void
@ -195,7 +198,6 @@ Vulkan_NewMap (model_t *worldmodel, struct model_s **models, int num_models,
r_viewleaf = NULL; r_viewleaf = NULL;
R_MarkLeaves (); R_MarkLeaves ();
R_FreeAllEntities ();
R_ClearParticles (); R_ClearParticles ();
Vulkan_RegisterTextures (models, num_models, ctx); Vulkan_RegisterTextures (models, num_models, ctx);
//Vulkan_BuildLightmaps (models, num_models, ctx); //Vulkan_BuildLightmaps (models, num_models, ctx);

View file

@ -180,14 +180,9 @@ typedef struct client_state_s {
/* information that is static for the entire time connected to a server */ /* information that is static for the entire time connected to a server */
struct model_s *model_precache[MAX_MODELS];
struct sfx_s *sound_precache[MAX_SOUNDS]; struct sfx_s *sound_precache[MAX_SOUNDS];
int nummodels;
int numsounds; int numsounds;
struct plitem_s *edicts;
struct plitem_s *worldspawn;
char levelname[40]; // for display on solo scoreboard char levelname[40]; // for display on solo scoreboard
int spectator; int spectator;
int playernum; int playernum;
@ -205,9 +200,7 @@ typedef struct client_state_s {
int fbskins; int fbskins;
// refresh related state // refresh related state
struct model_s *worldmodel; // cl_entitites[0].model
int num_entities; // held in cl_entities array int num_entities; // held in cl_entities array
entity_t viewent; // the weapon model
int cdtrack; // cd audio int cdtrack; // cd audio
@ -240,10 +233,9 @@ extern struct cvar_s *noskins;
extern client_state_t cl; extern client_state_t cl;
// FIXME, allocate dynamically extern entity_t *cl_entities[MAX_EDICTS];
extern entity_t cl_entities[MAX_EDICTS];
extern double cl_msgtime[MAX_EDICTS]; extern double cl_msgtime[MAX_EDICTS];
extern byte cl_forcelink[MAX_EDICTS]; extern struct set_s cl_forcelink;
extern int fps_count; extern int fps_count;
@ -299,6 +291,7 @@ void CL_NewTranslation (int slot, struct skin_s *skin);
void CL_SignonReply (void); void CL_SignonReply (void);
void CL_RelinkEntities (void); void CL_RelinkEntities (void);
void CL_ClearEnts (void); void CL_ClearEnts (void);
entity_t *CL_GetEntity (int num);
extern double realtime; extern double realtime;

View file

@ -48,6 +48,8 @@
#include "compat.h" #include "compat.h"
#include "client/world.h"
#include "nq/include/client.h" #include "nq/include/client.h"
#include "nq/include/host.h" #include "nq/include/host.h"
@ -338,8 +340,8 @@ demo_default_name (const char *argv1)
time (&tim); time (&tim);
strftime (timestring, 19, "%Y-%m-%d-%H-%M", localtime (&tim)); strftime (timestring, 19, "%Y-%m-%d-%H-%M", localtime (&tim));
// the leading path-name is to be removed from cl.worldmodel->name // the leading path-name is to be removed from cl_world.worldmodel->name
mapname = QFS_SkipPath (cl.worldmodel->path); mapname = QFS_SkipPath (cl_world.worldmodel->path);
// the map name is cut off after any "." because this would prevent // the map name is cut off after any "." because this would prevent
// an extension being appended // an extension being appended

View file

@ -44,11 +44,13 @@
#include "QF/plugin/vid_render.h" #include "QF/plugin/vid_render.h"
#include "QF/scene/entity.h" #include "QF/scene/entity.h"
#include "QF/scene/scene.h"
#include "compat.h" #include "compat.h"
#include "client/effects.h" #include "client/effects.h"
#include "client/temp_entities.h" #include "client/temp_entities.h"
#include "client/world.h"
#include "client/chase.h" #include "client/chase.h"
@ -57,9 +59,12 @@
#include "nq/include/host.h" #include "nq/include/host.h"
#include "nq/include/server.h" #include "nq/include/server.h"
entity_t cl_entities[MAX_EDICTS]; entity_t *cl_entities[MAX_EDICTS];
double cl_msgtime[MAX_EDICTS]; double cl_msgtime[MAX_EDICTS];
byte cl_forcelink[MAX_EDICTS]; static byte forcelink_bytes[SET_SIZE(MAX_EDICTS)];
#define alloc_forcelink(s) (set_bits_t *)forcelink_bytes
set_t cl_forcelink = SET_STATIC_INIT (MAX_EDICTS, alloc_forcelink);
#undef alloc_forcelink
void void
CL_ClearEnts (void) CL_ClearEnts (void)
@ -67,14 +72,27 @@ CL_ClearEnts (void)
size_t i; size_t i;
for (i = 0; i < MAX_EDICTS; i++) { for (i = 0; i < MAX_EDICTS; i++) {
CL_Init_Entity (cl_entities + i); if (cl_entities[i]) {
Scene_DestroyEntity (cl_world.scene, cl_entities[i]);
cl_entities[i] = 0;
}
} }
// clear other arrays // clear other arrays
i = nq_entstates.num_frames * nq_entstates.num_entities; i = nq_entstates.num_frames * nq_entstates.num_entities;
memset (nq_entstates.frame[0], 0, i * sizeof (entity_state_t)); memset (nq_entstates.frame[0], 0, i * sizeof (entity_state_t));
memset (cl_msgtime, 0, sizeof (cl_msgtime)); memset (cl_msgtime, 0, sizeof (cl_msgtime));
memset (cl_forcelink, 0, sizeof (cl_forcelink)); set_empty (&cl_forcelink);
}
entity_t *
CL_GetEntity (int num)
{
if (!cl_entities[num]) {
cl_entities[num] = Scene_CreateEntity (cl_world.scene);
CL_Init_Entity (cl_entities[num]);
}
return cl_entities[num];
} }
/* /*
@ -115,12 +133,12 @@ CL_LerpPoint (void)
} }
static void static void
set_entity_model (entity_t *ent, int modelindex) set_entity_model (int ent_ind, int modelindex)
{ {
int i = ent - cl_entities; entity_t *ent = cl_entities[ent_ind];
renderer_t *renderer = &ent->renderer; renderer_t *renderer = &ent->renderer;
animation_t *animation = &ent->animation; animation_t *animation = &ent->animation;
renderer->model = cl.model_precache[modelindex]; renderer->model = cl_world.models.a[modelindex];
// automatic animation (torches, etc) can be either all together // automatic animation (torches, etc) can be either all together
// or randomized // or randomized
if (renderer->model) { if (renderer->model) {
@ -130,11 +148,12 @@ set_entity_model (entity_t *ent, int modelindex)
animation->syncbase = 0.0; animation->syncbase = 0.0;
} }
} else { } else {
cl_forcelink[i] = true; // hack to make null model players work // hack to make null model players work
SET_ADD (&cl_forcelink, ent_ind);
} }
animation->nolerp = 1; // don't try to lerp when the model has changed animation->nolerp = 1; // don't try to lerp when the model has changed
if (i <= cl.maxclients) { if (ent_ind <= cl.maxclients) {
renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin, i); renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin, ent_ind);
} }
} }
@ -150,8 +169,6 @@ CL_RelinkEntities (void)
int entvalid; int entvalid;
int model_flags; int model_flags;
r_data->player_entity = &cl_entities[cl.viewentity];
// determine partial update time // determine partial update time
frac = CL_LerpPoint (); frac = CL_LerpPoint ();
@ -180,7 +197,7 @@ CL_RelinkEntities (void)
for (i = 1; i < cl.num_entities; i++) { for (i = 1; i < cl.num_entities; i++) {
new = &nq_entstates.frame[0 + cl.frameIndex][i]; new = &nq_entstates.frame[0 + cl.frameIndex][i];
old = &nq_entstates.frame[1 - cl.frameIndex][i]; old = &nq_entstates.frame[1 - cl.frameIndex][i];
ent = &cl_entities[i]; ent = CL_GetEntity (i);
renderer = &ent->renderer; renderer = &ent->renderer;
animation = &ent->animation; animation = &ent->animation;
@ -200,20 +217,24 @@ CL_RelinkEntities (void)
continue; continue;
} }
if (cl_forcelink[i]) if (SET_TEST_MEMBER (&cl_forcelink, i)) {
*old = *new; *old = *new;
}
if (cl_forcelink[i] || new->modelindex != old->modelindex) { if (SET_TEST_MEMBER (&cl_forcelink, i)
|| new->modelindex != old->modelindex) {
old->modelindex = new->modelindex; old->modelindex = new->modelindex;
set_entity_model (ent, new->modelindex); set_entity_model (i, new->modelindex);
} }
animation->frame = new->frame; animation->frame = new->frame;
if (cl_forcelink[i] || new->colormap != old->colormap) { if (SET_TEST_MEMBER (&cl_forcelink, i)
|| new->colormap != old->colormap) {
old->colormap = new->colormap; old->colormap = new->colormap;
renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin, renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin,
new->colormap); new->colormap);
} }
if (cl_forcelink[i] || new->skinnum != old->skinnum) { if (SET_TEST_MEMBER (&cl_forcelink, i)
|| new->skinnum != old->skinnum) {
old->skinnum = new->skinnum; old->skinnum = new->skinnum;
renderer->skinnum = new->skinnum; renderer->skinnum = new->skinnum;
if (i <= cl.maxclients) { if (i <= cl.maxclients) {
@ -232,7 +253,7 @@ CL_RelinkEntities (void)
model_flags = renderer->model->flags; model_flags = renderer->model->flags;
} }
if (cl_forcelink[i]) { if (SET_TEST_MEMBER (&cl_forcelink, i)) {
// The entity was not updated in the last message so move to the // The entity was not updated in the last message so move to the
// final spot // final spot
animation->pose1 = animation->pose2 = -1; animation->pose1 = animation->pose2 = -1;
@ -242,7 +263,7 @@ CL_RelinkEntities (void)
if (ent->visibility.efrag) { if (ent->visibility.efrag) {
r_funcs->R_RemoveEfrags (ent); r_funcs->R_RemoveEfrags (ent);
} }
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
} }
ent->old_origin = new->origin; ent->old_origin = new->origin;
} else { } else {
@ -278,10 +299,10 @@ CL_RelinkEntities (void)
= Transform_GetWorldPosition (ent->transform); = Transform_GetWorldPosition (ent->transform);
if (!VectorCompare (org, ent->old_origin)) {//FIXME if (!VectorCompare (org, ent->old_origin)) {//FIXME
r_funcs->R_RemoveEfrags (ent); r_funcs->R_RemoveEfrags (ent);
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
} }
} else { } else {
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
} }
} }
} }
@ -303,8 +324,10 @@ CL_RelinkEntities (void)
if (model_flags & ~EF_ROTATE) if (model_flags & ~EF_ROTATE)
CL_ModelEffects (ent, i, new->glow_color, cl.time); CL_ModelEffects (ent, i, new->glow_color, cl.time);
cl_forcelink[i] = false; SET_REMOVE (&cl_forcelink, i);
} }
r_data->player_entity = CL_GetEntity (cl.viewentity);
cl.viewstate.player_entity = CL_GetEntity (cl.viewentity);
cl.viewstate.player_origin cl.viewstate.player_origin
= Transform_GetWorldPosition (cl_entities[cl.viewentity].transform); = Transform_GetWorldPosition (cl.viewstate.player_entity->transform);
} }

View file

@ -48,14 +48,16 @@
#include "QF/plugin/console.h" #include "QF/plugin/console.h"
#include "QF/plugin/vid_render.h" #include "QF/plugin/vid_render.h"
#include "QF/scene/entity.h" #include "QF/scene/entity.h"
#include "QF/scene/scene.h"
#include "compat.h" #include "compat.h"
#include "sbar.h" #include "sbar.h"
#include "client/chase.h"
#include "client/particles.h" #include "client/particles.h"
#include "client/temp_entities.h" #include "client/temp_entities.h"
#include "client/world.h"
#include "client/chase.h"
#include "nq/include/cl_skin.h" #include "nq/include/cl_skin.h"
#include "nq/include/client.h" #include "nq/include/client.h"
#include "nq/include/host.h" #include "nq/include/host.h"
@ -188,9 +190,9 @@ CL_ClearState (void)
if (!sv.active) if (!sv.active)
Host_ClearMemory (); Host_ClearMemory ();
if (cl.edicts) if (cl.viewstate.weapon_entity) {
PL_Free (cl.edicts); Scene_DestroyEntity (cl_world.scene, cl.viewstate.weapon_entity);
}
if (cl.players) { if (cl.players) {
int i; int i;
@ -202,6 +204,7 @@ CL_ClearState (void)
__auto_type cam = cl.viewstate.camera_transform; __auto_type cam = cl.viewstate.camera_transform;
memset (&cl, 0, sizeof (cl)); memset (&cl, 0, sizeof (cl));
cl.viewstate.camera_transform = cam; cl.viewstate.camera_transform = cam;
cl.viewstate.player_origin = (vec4f_t) {0, 0, 0, 1}; cl.viewstate.player_origin = (vec4f_t) {0, 0, 0, 1};
cl.viewstate.chase = 1; cl.viewstate.chase = 1;
cl.viewstate.chasestate = &cl.chasestate; cl.viewstate.chasestate = &cl.chasestate;
@ -210,10 +213,6 @@ CL_ClearState (void)
r_data->force_fullscreen = 0; r_data->force_fullscreen = 0;
r_data->lightstyle = cl.lightstyle; r_data->lightstyle = cl.lightstyle;
CL_Init_Entity (&cl.viewent);
cl.viewstate.weapon_entity = &cl.viewent;
r_data->view_model = &cl.viewent;
SZ_Clear (&cls.message); SZ_Clear (&cls.message);
CL_ClearTEnts (); CL_ClearTEnts ();
@ -221,6 +220,10 @@ CL_ClearState (void)
r_funcs->R_ClearState (); r_funcs->R_ClearState ();
CL_ClearEnts (); CL_ClearEnts ();
cl.viewstate.weapon_entity = Scene_CreateEntity (cl_world.scene);
CL_Init_Entity (cl.viewstate.weapon_entity);
r_data->view_model = cl.viewstate.weapon_entity;
} }
/* /*
@ -276,7 +279,7 @@ CL_Disconnect (void)
Host_ShutdownServer (false); Host_ShutdownServer (false);
} }
cl.worldmodel = NULL; cl_world.worldmodel = NULL;
cl.intermission = 0; cl.intermission = 0;
cl.viewstate.intermission = 0; cl.viewstate.intermission = 0;
} }
@ -389,18 +392,18 @@ CL_NextDemo (void)
static void static void
pointfile_f (void) pointfile_f (void)
{ {
CL_LoadPointFile (cl.worldmodel); CL_LoadPointFile (cl_world.worldmodel);
} }
static void static void
CL_PrintEntities_f (void) CL_PrintEntities_f (void)
{ {
entity_t *ent;
int i; int i;
for (i = 0, ent = cl_entities; i < cl.num_entities; i++, ent++) { for (i = 0; i < cl.num_entities; i++) {
entity_t *ent = cl_entities[i];
Sys_Printf ("%3i:", i); Sys_Printf ("%3i:", i);
if (!ent->renderer.model) { if (!ent || !ent->renderer.model) {
Sys_Printf ("EMPTY\n"); Sys_Printf ("EMPTY\n");
continue; continue;
} }
@ -422,8 +425,8 @@ CL_ReadFromServer (void)
{ {
int ret; int ret;
TEntContext_t tentCtx = { TEntContext_t tentCtx = {
Transform_GetWorldPosition (cl_entities[cl.viewentity].transform), cl.viewstate.player_origin,
cl.worldmodel, cl.viewentity cl.viewentity
}; };
cl.oldtime = cl.time; cl.oldtime = cl.time;
@ -571,6 +574,7 @@ CL_Init (cbuf_t *cbuf)
CL_Init_Input (cbuf); CL_Init_Input (cbuf);
CL_Particles_Init (); CL_Particles_Init ();
CL_TEnts_Init (); CL_TEnts_Init ();
CL_World_Init ();
CL_ClearState (); CL_ClearState ();
V_Init (&cl.viewstate); V_Init (&cl.viewstate);

View file

@ -51,10 +51,13 @@
#include "QF/sound.h" // FIXME: DEFAULT_SOUND_PACKET_* #include "QF/sound.h" // FIXME: DEFAULT_SOUND_PACKET_*
#include "QF/va.h" #include "QF/va.h"
#include "QF/scene/scene.h"
#include "QF/plugin/vid_render.h" #include "QF/plugin/vid_render.h"
#include "QF/scene/entity.h" #include "QF/scene/entity.h"
#include "client/temp_entities.h" #include "client/temp_entities.h"
#include "client/world.h"
#include "compat.h" #include "compat.h"
#include "sbar.h" #include "sbar.h"
@ -125,24 +128,6 @@ const char *svc_strings[] = {
dstring_t *centerprint; dstring_t *centerprint;
static void
CL_LoadSky (void)
{
plitem_t *item;
const char *name = 0;
if (!cl.worldspawn) {
r_funcs->R_LoadSkys (0);
return;
}
if ((item = PL_ObjectForKey (cl.worldspawn, "sky")) // Q2/DarkPlaces
|| (item = PL_ObjectForKey (cl.worldspawn, "skyname")) // old QF
|| (item = PL_ObjectForKey (cl.worldspawn, "qlsky"))) /* QuakeLives */ {
name = PL_String (item);
}
r_funcs->R_LoadSkys (name);
}
/* /*
CL_EntityNum CL_EntityNum
@ -263,72 +248,13 @@ CL_KeepaliveMessage (void)
SZ_Clear (&cls.message); SZ_Clear (&cls.message);
} }
static void
map_cfg (const char *mapname, int all)
{
char *name = malloc (strlen (mapname) + 4 + 1);
cbuf_t *cbuf = Cbuf_New (&id_interp);
QFile *f;
QFS_StripExtension (mapname, name);
strcat (name, ".cfg");
f = QFS_FOpenFile (name);
if (f) {
Qclose (f);
Cmd_Exec_File (cbuf, name, 1);
} else {
Cmd_Exec_File (cbuf, "maps_default.cfg", 1);
}
if (all) {
Cbuf_Execute_Stack (cbuf);
} else {
Cbuf_Execute_Sets (cbuf);
}
free (name);
Cbuf_Delete (cbuf);
}
static plitem_t *
map_ent (const char *mapname)
{
static progs_t edpr;
char *name = malloc (strlen (mapname) + 4 + 1);
char *buf;
plitem_t *edicts = 0;
QFile *ent_file;
QFS_StripExtension (mapname, name);
strcat (name, ".ent");
ent_file = QFS_VOpenFile (name, 0, cl.model_precache[1]->vpath);
if ((buf = (char *) QFS_LoadFile (ent_file, 0))) {
edicts = ED_Parse (&edpr, buf);
free (buf);
} else {
edicts = ED_Parse (&edpr, cl.model_precache[1]->brush.entities);
}
free (name);
return edicts;
}
static void static void
CL_NewMap (const char *mapname) CL_NewMap (const char *mapname)
{ {
r_funcs->R_NewMap (cl.worldmodel, cl.model_precache, cl.nummodels);
Con_NewMap (); Con_NewMap ();
Hunk_Check (0); // make sure nothing is hurt Hunk_Check (0); // make sure nothing is hurt
Sbar_CenterPrint (0); Sbar_CenterPrint (0);
CL_World_NewMap (mapname, 0);
if (cl.model_precache[1] && cl.model_precache[1]->brush.entities) {
cl.edicts = map_ent (mapname);
if (cl.edicts) {
cl.worldspawn = PL_ObjectAtIndex (cl.edicts, 0);
CL_LoadSky ();
if (r_funcs->Fog_ParseWorldspawn)
r_funcs->Fog_ParseWorldspawn (cl.worldspawn);
}
}
map_cfg (mapname, 1);
} }
static void static void
@ -338,6 +264,7 @@ CL_ParseServerInfo (void)
char sound_precache[MAX_SOUNDS][MAX_QPATH]; char sound_precache[MAX_SOUNDS][MAX_QPATH];
const char *str; const char *str;
int i; int i;
int nummodels;
Sys_MaskPrintf (SYS_dev, "Serverinfo packet received.\n"); Sys_MaskPrintf (SYS_dev, "Serverinfo packet received.\n");
@ -394,16 +321,17 @@ CL_ParseServerInfo (void)
// needlessly purge it // needlessly purge it
// precache models // precache models
memset (cl.model_precache, 0, sizeof (cl.model_precache)); cl_world.models.size = 0;
for (cl.nummodels = 1;; cl.nummodels++) { DARRAY_APPEND (&cl_world.models, 0); // ind 0 is null model
for (nummodels = 1;; nummodels++) {
str = MSG_ReadString (net_message); str = MSG_ReadString (net_message);
if (!str[0]) if (!str[0])
break; break;
if (cl.nummodels >= MAX_MODELS) { if (nummodels >= MAX_MODELS) {
Sys_Printf ("Server sent too many model precaches\n"); Sys_Printf ("Server sent too many model precaches\n");
goto done; goto done;
} }
strcpy (model_precache[cl.nummodels], str); strcpy (model_precache[nummodels], str);
Mod_TouchModel (str); Mod_TouchModel (str);
} }
@ -421,12 +349,12 @@ CL_ParseServerInfo (void)
} }
// now we try to load everything else until a cache allocation fails // now we try to load everything else until a cache allocation fails
if (model_precache[1]) CL_MapCfg (model_precache[1]);
map_cfg (model_precache[1], 0);
for (i = 1; i < cl.nummodels; i++) { for (i = 1; i < nummodels; i++) {
cl.model_precache[i] = Mod_ForName (model_precache[i], false); DARRAY_APPEND (&cl_world.models,
if (cl.model_precache[i] == NULL) { Mod_ForName (model_precache[i], false));
if (cl_world.models.a[i] == NULL) {
Sys_Printf ("Model %s not found\n", model_precache[i]); Sys_Printf ("Model %s not found\n", model_precache[i]);
goto done; goto done;
} }
@ -439,8 +367,8 @@ CL_ParseServerInfo (void)
} }
// local state // local state
cl_entities[0].renderer.model = cl.worldmodel = cl.model_precache[1]; cl_world.worldmodel = cl_world.models.a[1];
cl.chasestate.worldmodel = cl.worldmodel; cl.chasestate.worldmodel = cl_world.worldmodel;
if (!centerprint) if (!centerprint)
centerprint = dstring_newstr (); centerprint = dstring_newstr ();
else else
@ -600,44 +528,10 @@ CL_ParseUpdate (int bits)
//VectorCopy (state->msg_angles[0], state->msg_angles[1]); //VectorCopy (state->msg_angles[0], state->msg_angles[1]);
//CL_TransformEntity (ent, state->msg_angles[0]); //CL_TransformEntity (ent, state->msg_angles[0]);
//state->forcelink = true; //state->forcelink = true;
cl_forcelink[num] = true; SET_ADD (&cl_forcelink, num);
} }
} }
static void
CL_ParseBaseline (entity_state_t *baseline, int version)
{
int bits = 0;
if (version == 2)
bits = MSG_ReadByte (net_message);
if (bits & B_LARGEMODEL)
baseline->modelindex = MSG_ReadShort (net_message);
else
baseline->modelindex = MSG_ReadByte (net_message);
if (bits & B_LARGEFRAME)
baseline->frame = MSG_ReadShort (net_message);
else
baseline->frame = MSG_ReadByte (net_message);
baseline->colormap = MSG_ReadByte (net_message);
baseline->skinnum = MSG_ReadByte (net_message);
MSG_ReadCoordAngleV (net_message, &baseline->origin[0], baseline->angles);
baseline->origin[3] = 1;//FIXME
if (bits & B_ALPHA)
baseline->alpha = MSG_ReadByte (net_message);
else
baseline->alpha = 255;//FIXME alpha
baseline->scale = 16;
baseline->glow_size = 0;
baseline->glow_color = 254;
baseline->colormod = 255;
}
/* /*
CL_ParseClientdata CL_ParseClientdata
@ -723,7 +617,7 @@ CL_ParseClientdata (void)
if (cl.stats[STAT_WEAPON] != i) { if (cl.stats[STAT_WEAPON] != i) {
cl.stats[STAT_WEAPON] = i; cl.stats[STAT_WEAPON] = i;
Sbar_Changed (); Sbar_Changed ();
cl.viewstate.weapon_model = cl.model_precache[cl.stats[STAT_WEAPON]]; cl.viewstate.weapon_model = cl_world.models.a[cl.stats[STAT_WEAPON]];
} }
i = (short) MSG_ReadShort (net_message); i = (short) MSG_ReadShort (net_message);
@ -779,38 +673,13 @@ CL_ParseClientdata (void)
cl.stats[STAT_WEAPONFRAME] |= MSG_ReadByte (net_message) << 8; cl.stats[STAT_WEAPONFRAME] |= MSG_ReadByte (net_message) << 8;
if (bits & SU_WEAPONALPHA) { if (bits & SU_WEAPONALPHA) {
byte alpha = MSG_ReadByte (net_message); byte alpha = MSG_ReadByte (net_message);
cl.viewent.renderer.colormod[3] = ENTALPHA_DECODE (alpha); float a = ENTALPHA_DECODE (alpha);
cl.viewstate.weapon_entity->renderer.colormod[3] = a;
} else { } else {
cl.viewent.renderer.colormod[3] = 1.0; cl.viewstate.weapon_entity->renderer.colormod[3] = 1;
} }
} }
static void
CL_ParseStatic (int version)
{
entity_state_t baseline;
entity_t *ent;
ent = r_funcs->R_AllocEntity ();
CL_Init_Entity (ent);
CL_ParseBaseline (&baseline, version);
// copy it to the current state
//FIXME alpha & lerp
ent->renderer.model = cl.model_precache[baseline.modelindex];
ent->animation.frame = baseline.frame;
ent->renderer.skin = 0;
ent->renderer.skinnum = baseline.skinnum;
VectorCopy (ent_colormod[baseline.colormod], ent->renderer.colormod);
ent->renderer.colormod[3] = ENTALPHA_DECODE (baseline.alpha);
CL_TransformEntity (ent, baseline.scale / 16.0, baseline.angles,
baseline.origin);
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent);
}
static void static void
CL_ParseStaticSound (int version) CL_ParseStaticSound (int version)
{ {
@ -850,8 +719,8 @@ CL_ParseServerMessage (void)
cl.last_servermessage = realtime; cl.last_servermessage = realtime;
TEntContext_t tentCtx = { TEntContext_t tentCtx = {
Transform_GetWorldPosition (cl_entities[cl.viewentity].transform), cl.viewstate.player_origin,
cl.worldmodel, cl.viewentity cl.viewentity
}; };
// if recording demos, copy the message out // if recording demos, copy the message out
@ -921,7 +790,6 @@ CL_ParseServerMessage (void)
case svc_setview: case svc_setview:
cl.viewentity = MSG_ReadShort (net_message); cl.viewentity = MSG_ReadShort (net_message);
cl.viewstate.player_entity = &cl_entities[cl.viewentity];
break; break;
case svc_sound: case svc_sound:
@ -1035,7 +903,7 @@ CL_ParseServerMessage (void)
Host_Error ("CL_ParseServerMessage: svc_updatecolors > " Host_Error ("CL_ParseServerMessage: svc_updatecolors > "
"MAX_SCOREBOARD"); "MAX_SCOREBOARD");
} else { } else {
entity_t *ent = &cl_entities[i+1]; entity_t *ent = CL_GetEntity (i + 1);
byte col = MSG_ReadByte (net_message); byte col = MSG_ReadByte (net_message);
byte top = col >> 4; byte top = col >> 4;
byte bot = col & 0xf; byte bot = col & 0xf;
@ -1061,7 +929,7 @@ CL_ParseServerMessage (void)
break; break;
case svc_spawnstatic: case svc_spawnstatic:
CL_ParseStatic (1); CL_ParseStatic (net_message, 1);
break; break;
// svc_spawnbinary // svc_spawnbinary
@ -1069,7 +937,7 @@ CL_ParseServerMessage (void)
case svc_spawnbaseline: case svc_spawnbaseline:
i = MSG_ReadShort (net_message); i = MSG_ReadShort (net_message);
// must use CL_EntityNum () to force cl.num_entities up // must use CL_EntityNum () to force cl.num_entities up
CL_ParseBaseline (CL_EntityNum (i), 1); CL_ParseBaseline (net_message, CL_EntityNum (i), 1);
break; break;
case svc_temp_entity: case svc_temp_entity:
@ -1205,10 +1073,10 @@ CL_ParseServerMessage (void)
case svc_spawnbaseline2: case svc_spawnbaseline2:
i = MSG_ReadShort (net_message); i = MSG_ReadShort (net_message);
// must use CL_EntityNum() to force cl.num_entities up // must use CL_EntityNum() to force cl.num_entities up
CL_ParseBaseline (CL_EntityNum(i), 2); CL_ParseBaseline (net_message, CL_EntityNum(i), 2);
break; break;
case svc_spawnstatic2: case svc_spawnstatic2:
CL_ParseStatic (2); CL_ParseStatic (net_message, 2);
break; break;
case svc_spawnstaticsound2: case svc_spawnstaticsound2:
CL_ParseStaticSound (2); CL_ParseStaticSound (2);

View file

@ -51,6 +51,8 @@
#include "sbar.h" #include "sbar.h"
#include "client/world.h"
#include "nq/include/client.h" #include "nq/include/client.h"
static view_t *net_view; static view_t *net_view;
@ -75,11 +77,11 @@ SCR_CShift (void)
mleaf_t *leaf; mleaf_t *leaf;
int contents = CONTENTS_EMPTY; int contents = CONTENTS_EMPTY;
if (cls.state == ca_active && cl.worldmodel) { if (cls.state == ca_active && cl_world.worldmodel) {
vec4f_t origin; vec4f_t origin;
origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); origin = Transform_GetWorldPosition (cl.viewstate.camera_transform);
//FIXME //FIXME
leaf = Mod_PointInLeaf (&origin[0], cl.worldmodel); leaf = Mod_PointInLeaf (&origin[0], cl_world.worldmodel);
contents = leaf->contents; contents = leaf->contents;
} }
V_SetContentsColor (&cl.viewstate, contents); V_SetContentsColor (&cl.viewstate, contents);

View file

@ -60,6 +60,7 @@
#include "compat.h" #include "compat.h"
#include "client/chase.h" #include "client/chase.h"
#include "client/world.h"
#include "nq/include/host.h" #include "nq/include/host.h"
#include "nq/include/server.h" #include "nq/include/server.h"
@ -612,7 +613,7 @@ Host_ClientFrame (void)
vec4f_t origin; vec4f_t origin;
origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); origin = Transform_GetWorldPosition (cl.viewstate.camera_transform);
l = Mod_PointInLeaf (&origin[0], cl.worldmodel);//FIXME l = Mod_PointInLeaf (&origin[0], cl_world.worldmodel);//FIXME
if (l) if (l)
asl = l->ambient_sound_level; asl = l->ambient_sound_level;
S_Update (cl.viewstate.camera_transform, asl); S_Update (cl.viewstate.camera_transform, asl);

View file

@ -50,6 +50,8 @@
#include "QF/sys.h" #include "QF/sys.h"
#include "QF/va.h" #include "QF/va.h"
#include "client/world.h"
#include "compat.h" #include "compat.h"
#include "world.h" #include "world.h"
@ -1320,7 +1322,7 @@ Host_Viewmodel_f (void)
} }
SVfloat (e, frame) = 0; SVfloat (e, frame) = 0;
cl.model_precache[(int) SVfloat (e, modelindex)] = m; cl_world.models.a[(int) SVfloat (e, modelindex)] = m;
} }
static void static void
@ -1333,7 +1335,7 @@ Host_Viewframe_f (void)
e = FindViewthing (); e = FindViewthing ();
if (!e) if (!e)
return; return;
m = cl.model_precache[(int) SVfloat (e, modelindex)]; m = cl_world.models.a[(int) SVfloat (e, modelindex)];
f = atoi (Cmd_Argv (1)); f = atoi (Cmd_Argv (1));
if (f >= m->numframes) if (f >= m->numframes)
@ -1366,7 +1368,7 @@ Host_Viewnext_f (void)
e = FindViewthing (); e = FindViewthing ();
if (!e) if (!e)
return; return;
m = cl.model_precache[(int) SVfloat (e, modelindex)]; m = cl_world.models.a[(int) SVfloat (e, modelindex)];
SVfloat (e, frame) = SVfloat (e, frame) + 1; SVfloat (e, frame) = SVfloat (e, frame) + 1;
if (SVfloat (e, frame) >= m->numframes) if (SVfloat (e, frame) >= m->numframes)
@ -1385,7 +1387,7 @@ Host_Viewprev_f (void)
if (!e) if (!e)
return; return;
m = cl.model_precache[(int) SVfloat (e, modelindex)]; m = cl_world.models.a[(int) SVfloat (e, modelindex)];
SVfloat (e, frame) = SVfloat (e, frame) - 1; SVfloat (e, frame) = SVfloat (e, frame) - 1;
if (SVfloat (e, frame) < 0) if (SVfloat (e, frame) < 0)

View file

@ -36,12 +36,16 @@
#include "QF/plugin/vid_render.h" #include "QF/plugin/vid_render.h"
#include "client/world.h"
#include "nq/include/host.h" #include "nq/include/host.h"
#include "nq/include/server.h" #include "nq/include/server.h"
client_state_t cl; client_state_t cl;
client_static_t cls; client_static_t cls;
worldscene_t cl_world;
cvar_t *cl_name; cvar_t *cl_name;
cvar_t *cl_writecfg; cvar_t *cl_writecfg;
cvar_t *demo_speed; cvar_t *demo_speed;

View file

@ -41,12 +41,9 @@ void CL_ParsePacketEntities (qboolean delta);
void CL_SetSolidEntities (void); void CL_SetSolidEntities (void);
void CL_ParsePlayerinfo (void); void CL_ParsePlayerinfo (void);
void CL_Ents_Init (void); void CL_Ents_Init (void);
entity_t *CL_GetEntity (int num);
extern struct cvar_s *cl_deadbodyfilter; extern struct cvar_s *cl_deadbodyfilter;
extern struct cvar_s *cl_gibfilter; extern struct cvar_s *cl_gibfilter;
extern entity_t cl_player_ents[];
extern entity_t cl_flag_ents[];
extern entity_t cl_packet_ents[];
#endif #endif

View file

@ -222,14 +222,10 @@ typedef struct client_state_s {
char model_name[MAX_MODELS][MAX_QPATH]; char model_name[MAX_MODELS][MAX_QPATH];
char sound_name[MAX_SOUNDS][MAX_QPATH]; char sound_name[MAX_SOUNDS][MAX_QPATH];
struct model_s *model_precache[MAX_MODELS];
struct sfx_s *sound_precache[MAX_SOUNDS]; struct sfx_s *sound_precache[MAX_SOUNDS];
int nummodels; int nummodels;
int numsounds; int numsounds;
struct plitem_s *edicts;
struct plitem_s *worldspawn;
char levelname[40]; // for display on solo scoreboard char levelname[40]; // for display on solo scoreboard
int spectator; int spectator;
int playernum; int playernum;
@ -247,9 +243,7 @@ typedef struct client_state_s {
int fbskins; int fbskins;
// refresh related state // refresh related state
struct model_s *worldmodel; // cl_entitites[0].model
int num_entities; // held in cl_entities array int num_entities; // held in cl_entities array
entity_t viewent; // the weapon model
int cdtrack; // cd audio int cdtrack; // cd audio
@ -288,10 +282,7 @@ extern struct cvar_s *cl_fb_players;
extern client_state_t cl; extern client_state_t cl;
typedef struct entitystateset_s DARRAY_TYPE (struct entity_state_s) extern entity_t *cl_entities[512];
entitystateset_t;
extern entitystateset_t cl_static_entities;
extern entity_t cl_entities[512];
extern byte cl_entity_valid[2][512]; extern byte cl_entity_valid[2][512];
extern qboolean nomaster; extern qboolean nomaster;

View file

@ -56,6 +56,8 @@
#include "compat.h" #include "compat.h"
#include "client/world.h"
#include "qw/include/cl_cam.h" #include "qw/include/cl_cam.h"
#include "qw/include/cl_demo.h" #include "qw/include/cl_demo.h"
#include "qw/include/cl_ents.h" #include "qw/include/cl_ents.h"
@ -633,8 +635,8 @@ demo_default_name (const char *argv1)
time (&tim); time (&tim);
strftime (timestring, 19, "%Y-%m-%d-%H-%M", localtime (&tim)); strftime (timestring, 19, "%Y-%m-%d-%H-%M", localtime (&tim));
// the leading path-name is to be removed from cl.worldmodel->name // the leading path-name is to be removed from cl_world.worldmodel->name
mapname = QFS_SkipPath (cl.worldmodel->path); mapname = QFS_SkipPath (cl_world.worldmodel->path);
// the map name is cut off after any "." because this would prevent // the map name is cut off after any "." because this would prevent
// an extension being appended // an extension being appended

View file

@ -45,6 +45,7 @@
#include "client/temp_entities.h" #include "client/temp_entities.h"
#include "client/view.h" #include "client/view.h"
#include "client/world.h"
#include "qw/msg_ucmd.h" #include "qw/msg_ucmd.h"
#include "qw/pmove.h" #include "qw/pmove.h"
@ -481,7 +482,7 @@ CL_ParsePlayerinfo (void)
byte val; byte val;
entity_t *ent; entity_t *ent;
ent = &cl_player_ents[num]; ent = CL_GetEntity (num + 1);
bits = MSG_ReadByte (net_message); bits = MSG_ReadByte (net_message);
if (bits & PF_ALPHA) { if (bits & PF_ALPHA) {
val = MSG_ReadByte (net_message); val = MSG_ReadByte (net_message);
@ -529,7 +530,7 @@ CL_SetSolidEntities (void)
frame_t *frame; frame_t *frame;
packet_entities_t *pak; packet_entities_t *pak;
pmove.physents[0].model = cl.worldmodel; pmove.physents[0].model = cl_world.worldmodel;
VectorZero (pmove.physents[0].origin); VectorZero (pmove.physents[0].origin);
VectorZero (pmove.physents[0].angles); VectorZero (pmove.physents[0].angles);
pmove.physents[0].info = 0; pmove.physents[0].info = 0;
@ -543,17 +544,17 @@ CL_SetSolidEntities (void)
if (!state->modelindex) if (!state->modelindex)
continue; continue;
if (!cl.model_precache[state->modelindex]) if (!cl_world.models.a[state->modelindex])
continue; continue;
if (cl.model_precache[state->modelindex]->brush.hulls[1].firstclipnode if (cl_world.models.a[state->modelindex]->brush.hulls[1].firstclipnode
|| cl.model_precache[state->modelindex]->clipbox) { || cl_world.models.a[state->modelindex]->clipbox) {
if (pmove.numphysent == MAX_PHYSENTS) { if (pmove.numphysent == MAX_PHYSENTS) {
Sys_Printf ("WARNING: entity physent overflow, email " Sys_Printf ("WARNING: entity physent overflow, email "
"quakeforge-devel@lists.quakeforge.net\n"); "quakeforge-devel@lists.quakeforge.net\n");
break; break;
} }
pmove.physents[pmove.numphysent].model = pmove.physents[pmove.numphysent].model =
cl.model_precache[state->modelindex]; cl_world.models.a[state->modelindex];
VectorCopy (state->origin, VectorCopy (state->origin,
pmove.physents[pmove.numphysent].origin); pmove.physents[pmove.numphysent].origin);
VectorCopy (state->angles, VectorCopy (state->angles,

View file

@ -42,6 +42,7 @@
#include "QF/sys.h" #include "QF/sys.h"
#include "QF/scene/entity.h" #include "QF/scene/entity.h"
#include "QF/scene/scene.h"
#include "compat.h" #include "compat.h"
#include "d_iface.h" #include "d_iface.h"
@ -50,6 +51,7 @@
#include "client/locs.h" #include "client/locs.h"
#include "client/temp_entities.h" #include "client/temp_entities.h"
#include "client/view.h" #include "client/view.h"
#include "client/world.h"
#include "qw/bothdefs.h" #include "qw/bothdefs.h"
#include "qw/msg_ucmd.h" #include "qw/msg_ucmd.h"
@ -62,9 +64,8 @@
#include "qw/include/cl_pred.h" #include "qw/include/cl_pred.h"
#include "qw/include/host.h" #include "qw/include/host.h"
entity_t cl_player_ents[MAX_CLIENTS]; entity_t *cl_flag_ents[MAX_CLIENTS];
entity_t cl_flag_ents[MAX_CLIENTS]; entity_t *cl_entities[512]; // FIXME: magic number
entity_t cl_entities[512]; // FIXME: magic number
byte cl_entity_valid[2][512]; byte cl_entity_valid[2][512];
void void
@ -72,15 +73,32 @@ CL_ClearEnts (void)
{ {
size_t i; size_t i;
for (i = 0; i < MAX_CLIENTS; i++) {
if (cl_flag_ents[i]) {
Scene_DestroyEntity (cl_world.scene, cl_flag_ents[i]);
cl_flag_ents[i] = 0;
}
}
for (i = 0; i < 512; i++) {
if (cl_entities[i]) {
Scene_DestroyEntity (cl_world.scene, cl_entities[i]);
cl_entities[i] = 0;
}
}
i = qw_entstates.num_frames * qw_entstates.num_entities; i = qw_entstates.num_frames * qw_entstates.num_entities;
memset (qw_entstates.frame[0], 0, i * sizeof (entity_state_t)); memset (qw_entstates.frame[0], 0, i * sizeof (entity_state_t));
memset (cl_entity_valid, 0, sizeof (cl_entity_valid)); memset (cl_entity_valid, 0, sizeof (cl_entity_valid));
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++) entity_t *
CL_Init_Entity (&cl_flag_ents[i]); CL_GetEntity (int num)
for (i = 0; i < sizeof (cl_player_ents) / sizeof (cl_player_ents[0]); i++) {
CL_Init_Entity (&cl_player_ents[i]); if (!cl_entities[num]) {
cl_entities[num] = Scene_CreateEntity (cl_world.scene);
CL_Init_Entity (cl_entities[num]);
}
return cl_entities[num];
} }
// Hack hack hack // Hack hack hack
@ -110,7 +128,7 @@ set_entity_model (entity_t *ent, int modelindex)
{ {
renderer_t *renderer = &ent->renderer; renderer_t *renderer = &ent->renderer;
animation_t *animation = &ent->animation; animation_t *animation = &ent->animation;
renderer->model = cl.model_precache[modelindex]; renderer->model = cl_world.models.a[modelindex];
// automatic animation (torches, etc) can be either all together // automatic animation (torches, etc) can be either all together
// or randomized // or randomized
if (renderer->model) { if (renderer->model) {
@ -134,10 +152,10 @@ CL_LinkPacketEntities (void)
animation_t *animation; animation_t *animation;
frac = 1; frac = 1;
for (i = 0; i < 512; i++) { for (i = MAX_CLIENTS + 1; i < 512; i++) {
new = &qw_entstates.frame[cl.link_sequence & UPDATE_MASK][i]; new = &qw_entstates.frame[cl.link_sequence & UPDATE_MASK][i];
old = &qw_entstates.frame[cl.prev_sequence & UPDATE_MASK][i]; old = &qw_entstates.frame[cl.prev_sequence & UPDATE_MASK][i];
ent = &cl_entities[i]; ent = CL_GetEntity (i);
renderer = &ent->renderer; renderer = &ent->renderer;
animation = &ent->animation; animation = &ent->animation;
forcelink = cl_entity_valid[0][i] != cl_entity_valid[1][i]; forcelink = cl_entity_valid[0][i] != cl_entity_valid[1][i];
@ -216,7 +234,7 @@ CL_LinkPacketEntities (void)
if (ent->visibility.efrag) { if (ent->visibility.efrag) {
r_funcs->R_RemoveEfrags (ent); r_funcs->R_RemoveEfrags (ent);
} }
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
} }
} else { } else {
vec4f_t delta = new->origin - old->origin; vec4f_t delta = new->origin - old->origin;
@ -248,15 +266,15 @@ CL_LinkPacketEntities (void)
= Transform_GetWorldPosition (ent->transform); = Transform_GetWorldPosition (ent->transform);
if (!VectorCompare (org, ent->old_origin)) {//FIXME if (!VectorCompare (org, ent->old_origin)) {//FIXME
r_funcs->R_RemoveEfrags (ent); r_funcs->R_RemoveEfrags (ent);
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
} }
} else { } else {
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
} }
} }
} }
if (!ent->visibility.efrag) { if (!ent->visibility.efrag) {
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
} }
// rotate binary objects locally // rotate binary objects locally
@ -288,7 +306,7 @@ CL_UpdateFlagModels (entity_t *ent, int key)
float f; float f;
entity_t *fent; entity_t *fent;
fent = &cl_flag_ents[key]; fent = cl_flag_ents[key];
if (!fent->active) { if (!fent->active) {
return; return;
@ -322,7 +340,7 @@ CL_AddFlagModels (entity_t *ent, int team, int key)
{ {
entity_t *fent; entity_t *fent;
fent = &cl_flag_ents[key]; fent = cl_flag_ents[key];
if (cl_flagindex == -1) { if (cl_flagindex == -1) {
fent->active = 0; fent->active = 0;
@ -336,7 +354,7 @@ CL_AddFlagModels (entity_t *ent, int team, int key)
} }
CL_UpdateFlagModels (ent, key); CL_UpdateFlagModels (ent, key);
fent->renderer.model = cl.model_precache[cl_flagindex]; fent->renderer.model = cl_world.models.a[cl_flagindex];
fent->renderer.skinnum = team; fent->renderer.skinnum = team;
return fent; return fent;
@ -347,7 +365,7 @@ CL_RemoveFlagModels (int key)
{ {
entity_t *fent; entity_t *fent;
fent = &cl_flag_ents[key]; fent = cl_flag_ents[key];
fent->active = 0; fent->active = 0;
Transform_SetParent (fent->transform, 0); Transform_SetParent (fent->transform, 0);
} }
@ -380,7 +398,7 @@ CL_LinkPlayers (void)
for (j = 0, player = cl.players, state = frame->playerstate; for (j = 0, player = cl.players, state = frame->playerstate;
j < MAX_CLIENTS; j++, player++, state++) { j < MAX_CLIENTS; j++, player++, state++) {
ent = &cl_player_ents[j]; ent = CL_GetEntity (j + 1);
if (ent->visibility.efrag) if (ent->visibility.efrag)
r_funcs->R_RemoveEfrags (ent); r_funcs->R_RemoveEfrags (ent);
if (player->flag_ent && player->flag_ent->visibility.efrag) { if (player->flag_ent && player->flag_ent->visibility.efrag) {
@ -395,7 +413,8 @@ CL_LinkPlayers (void)
// spawn light flashes, even ones coming from invisible objects // spawn light flashes, even ones coming from invisible objects
if (j == cl.playernum) { if (j == cl.playernum) {
org = cl.viewstate.player_origin; org = cl.viewstate.player_origin;
r_data->player_entity = &cl_player_ents[j]; r_data->player_entity = ent;
cl.viewstate.player_entity = ent;
clientplayer = true; clientplayer = true;
} else { } else {
org = state->pls.es.origin; org = state->pls.es.origin;
@ -453,8 +472,8 @@ CL_LinkPlayers (void)
ang[ROLL] = V_CalcRoll (ang, state->pls.es.velocity) * 4.0; ang[ROLL] = V_CalcRoll (ang, state->pls.es.velocity) * 4.0;
if (ent->renderer.model if (ent->renderer.model
!= cl.model_precache[state->pls.es.modelindex]) { != cl_world.models.a[state->pls.es.modelindex]) {
ent->renderer.model = cl.model_precache[state->pls.es.modelindex]; ent->renderer.model = cl_world.models.a[state->pls.es.modelindex];
ent->animation.nolerp = 1; ent->animation.nolerp = 1;
} }
ent->animation.frame = state->pls.es.frame; ent->animation.frame = state->pls.es.frame;
@ -492,10 +511,10 @@ CL_LinkPlayers (void)
} }
// stuff entity in map // stuff entity in map
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
if (player->flag_ent) { if (player->flag_ent) {
CL_UpdateFlagModels (ent, j); CL_UpdateFlagModels (ent, j);
r_funcs->R_AddEfrags (&cl.worldmodel->brush, player->flag_ent); r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, player->flag_ent);
} }
} }
} }
@ -516,7 +535,7 @@ CL_EmitEntities (void)
return; return;
TEntContext_t tentCtx = { TEntContext_t tentCtx = {
cl.viewstate.player_origin, cl.worldmodel, cl.viewentity cl.viewstate.player_origin, cl.viewentity
}; };
CL_LinkPlayers (); CL_LinkPlayers ();
@ -530,5 +549,4 @@ CL_EmitEntities (void)
void void
CL_Ents_Init (void) CL_Ents_Init (void)
{ {
r_data->view_model = &cl.viewent;
} }

View file

@ -91,6 +91,7 @@
#include "QF/plugin/console.h" #include "QF/plugin/console.h"
#include "QF/scene/transform.h" #include "QF/scene/transform.h"
#include "QF/scene/scene.h"
#include "buildnum.h" #include "buildnum.h"
#include "compat.h" #include "compat.h"
@ -99,6 +100,7 @@
#include "client/particles.h" #include "client/particles.h"
#include "client/temp_entities.h" #include "client/temp_entities.h"
#include "client/view.h" #include "client/view.h"
#include "client/world.h"
#include "qw/bothdefs.h" #include "qw/bothdefs.h"
#include "qw/pmove.h" #include "qw/pmove.h"
@ -229,7 +231,7 @@ CL_Quit_f (void)
static void static void
pointfile_f (void) pointfile_f (void)
{ {
CL_LoadPointFile (cl.worldmodel); CL_LoadPointFile (cl_world.worldmodel);
} }
static void static void
@ -385,6 +387,9 @@ CL_ClearState (void)
S_StopAllSounds (); S_StopAllSounds ();
if (cl.viewstate.weapon_entity) {
Scene_DestroyEntity (cl_world.scene, cl.viewstate.weapon_entity);
}
// wipe the entire cl structure // wipe the entire cl structure
if (cl.serverinfo) if (cl.serverinfo)
Info_Destroy (cl.serverinfo); Info_Destroy (cl.serverinfo);
@ -402,7 +407,6 @@ CL_ClearState (void)
cl.chasestate.viewstate = &cl.viewstate; cl.chasestate.viewstate = &cl.viewstate;
cl.viewstate.punchangle = (vec4f_t) {0, 0, 0, 1}; cl.viewstate.punchangle = (vec4f_t) {0, 0, 0, 1};
// Note: we should probably hack around this and give diff values for // Note: we should probably hack around this and give diff values for
// diff gamedirs // diff gamedirs
cl.fpd = FPD_DEFAULT; cl.fpd = FPD_DEFAULT;
@ -412,9 +416,6 @@ CL_ClearState (void)
cl.frames[i].packet_entities.entities = qw_entstates.frame[i]; cl.frames[i].packet_entities.entities = qw_entstates.frame[i];
cl.serverinfo = Info_ParseString ("", MAX_INFO_STRING, 0); cl.serverinfo = Info_ParseString ("", MAX_INFO_STRING, 0);
CL_Init_Entity (&cl.viewent);
cl.viewstate.weapon_entity = &cl.viewent;
Sys_MaskPrintf (SYS_dev, "Clearing memory\n"); Sys_MaskPrintf (SYS_dev, "Clearing memory\n");
VID_ClearMemory (); VID_ClearMemory ();
Mod_ClearAll (); Mod_ClearAll ();
@ -424,6 +425,10 @@ CL_ClearState (void)
CL_ClearEnts (); CL_ClearEnts ();
CL_ClearTEnts (); CL_ClearTEnts ();
cl.viewstate.weapon_entity = Scene_CreateEntity (cl_world.scene);
CL_Init_Entity (cl.viewstate.weapon_entity);
r_data->view_model = cl.viewstate.weapon_entity;
r_funcs->R_ClearState (); r_funcs->R_ClearState ();
SZ_Clear (&cls.netchan.message); SZ_Clear (&cls.netchan.message);
@ -519,7 +524,7 @@ CL_Disconnect (void)
Info_Destroy (cl.players[i].userinfo); Info_Destroy (cl.players[i].userinfo);
memset (&cl.players[i], 0, sizeof (cl.players[i])); memset (&cl.players[i], 0, sizeof (cl.players[i]));
} }
cl.worldmodel = NULL; cl_world.worldmodel = NULL;
cl.validsequence = 0; cl.validsequence = 0;
} }
@ -1216,6 +1221,7 @@ CL_Init (void)
CL_Ents_Init (); CL_Ents_Init ();
CL_Particles_Init (); CL_Particles_Init ();
CL_TEnts_Init (); CL_TEnts_Init ();
CL_World_Init ();
CL_ClearState (); CL_ClearState ();
Pmove_Init (); Pmove_Init ();
@ -1725,7 +1731,7 @@ Host_Frame (float time)
vec4f_t origin; vec4f_t origin;
origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); origin = Transform_GetWorldPosition (cl.viewstate.camera_transform);
l = Mod_PointInLeaf (&origin[0], cl.worldmodel);//FIXME l = Mod_PointInLeaf (&origin[0], cl_world.worldmodel);//FIXME
if (l) if (l)
asl = l->ambient_sound_level; asl = l->ambient_sound_level;
S_Update (cl.viewstate.camera_transform, asl); S_Update (cl.viewstate.camera_transform, asl);

View file

@ -61,12 +61,15 @@
#include "QF/teamplay.h" #include "QF/teamplay.h"
#include "QF/va.h" #include "QF/va.h"
#include "QF/scene/scene.h"
#include "compat.h" #include "compat.h"
#include "sbar.h" #include "sbar.h"
#include "client/effects.h" #include "client/effects.h"
#include "client/temp_entities.h" #include "client/temp_entities.h"
#include "client/view.h" #include "client/view.h"
#include "client/world.h"
#include "qw/bothdefs.h" #include "qw/bothdefs.h"
#include "qw/pmove.h" #include "qw/pmove.h"
@ -170,40 +173,6 @@ int packet_latency[NET_TIMINGS];
extern cvar_t *hud_scoreboard_uid; extern cvar_t *hud_scoreboard_uid;
entitystateset_t cl_static_entities = DARRAY_STATIC_INIT (32);
static void
CL_LoadSky (void)
{
plitem_t *item;
const char *name = 0;
static const char *sky_keys[] = {
"sky", // Q2/DarkPlaces
"skyname", // old QF
"qlsky", // QuakeLives
0
};
// R_LoadSkys does the right thing with null pointers.
if (cl.serverinfo) {
name = Info_ValueForKey (cl.serverinfo, "sky");
}
if (!name) {
if (!cl.worldspawn) {
r_funcs->R_LoadSkys (0);
return;
}
for (const char **key = sky_keys; *key; key++) {
if ((item = PL_ObjectForKey (cl.worldspawn, *key))) {
name = PL_String (item);
break;
}
}
}
r_funcs->R_LoadSkys (name);
}
int int
CL_CalcNet (void) CL_CalcNet (void)
{ {
@ -290,49 +259,20 @@ CL_CheckOrDownloadFile (const char *filename)
return false; return false;
} }
static plitem_t *
map_ent (const char *mapname)
{
static progs_t edpr;
char *name = malloc (strlen (mapname) + 4 + 1);
char *buf;
plitem_t *edicts = 0;
QFile *ent_file;
QFS_StripExtension (mapname, name);
strcat (name, ".ent");
ent_file = QFS_VOpenFile (name, 0, cl.model_precache[1]->vpath);
if ((buf = (char *) QFS_LoadFile (ent_file, 0))) {
edicts = ED_Parse (&edpr, buf);
free (buf);
} else {
edicts = ED_Parse (&edpr, cl.model_precache[1]->brush.entities);
}
free (name);
return edicts;
}
static void static void
CL_NewMap (const char *mapname) CL_NewMap (const char *mapname)
{ {
cl_static_entities.size = 0;
r_funcs->R_NewMap (cl.worldmodel, cl.model_precache, cl.nummodels);
Team_NewMap (); Team_NewMap ();
Con_NewMap (); Con_NewMap ();
Hunk_Check (0); // make sure nothing is hurt Hunk_Check (0); // make sure nothing is hurt
Sbar_CenterPrint (0); Sbar_CenterPrint (0);
if (cl.model_precache[1] && cl.model_precache[1]->brush.entities) { const char *skyname = 0;
cl.edicts = map_ent (mapname); // R_LoadSkys does the right thing with null pointers.
if (cl.edicts) { if (cl.serverinfo) {
cl.worldspawn = PL_ObjectAtIndex (cl.edicts, 0); skyname = Info_ValueForKey (cl.serverinfo, "sky");
CL_LoadSky ();
if (r_funcs->Fog_ParseWorldspawn)
r_funcs->Fog_ParseWorldspawn (cl.worldspawn);
}
} }
CL_World_NewMap (mapname, skyname);
map_cfg (mapname, 1);
} }
static void static void
@ -357,7 +297,7 @@ Model_NextDownload (void)
} }
if (cl.model_name[1]) if (cl.model_name[1])
map_cfg (cl.model_name[1], 0); CL_MapCfg (cl.model_name[1]);
for (i = 1; i < cl.nummodels; i++) { for (i = 1; i < cl.nummodels; i++) {
const char *info_key = 0; const char *info_key = 0;
@ -365,9 +305,10 @@ Model_NextDownload (void)
if (!cl.model_name[i][0]) if (!cl.model_name[i][0])
break; break;
cl.model_precache[i] = Mod_ForName (cl.model_name[i], false); DARRAY_APPEND (&cl_world.models,
Mod_ForName (cl.model_name[i], false));
if (!cl.model_precache[i]) { if (!cl_world.models.a[i]) {
Sys_Printf ("\nThe required model file '%s' could not be found or " Sys_Printf ("\nThe required model file '%s' could not be found or "
"downloaded.\n\n", cl.model_name[i]); "downloaded.\n\n", cl.model_name[i]);
Sys_Printf ("You may need to download or purchase a %s client " Sys_Printf ("You may need to download or purchase a %s client "
@ -378,18 +319,18 @@ Model_NextDownload (void)
} }
if (strequal (cl.model_name[i], "progs/player.mdl") if (strequal (cl.model_name[i], "progs/player.mdl")
&& cl.model_precache[i]->type == mod_alias) { && cl_world.models.a[i]->type == mod_alias) {
info_key = pmodel_name; info_key = pmodel_name;
//XXX mod_funcs->Skin_Player_Model (cl.model_precache[i]); //XXX mod_funcs->Skin_Player_Model (cl_world.models.a[i]);
} }
if (strequal (cl.model_name[i], "progs/eyes.mdl") if (strequal (cl.model_name[i], "progs/eyes.mdl")
&& cl.model_precache[i]->type == mod_alias) && cl_world.models.a[i]->type == mod_alias)
info_key = emodel_name; info_key = emodel_name;
if (info_key && cl_model_crcs->int_val) { if (info_key && cl_model_crcs->int_val) {
aliashdr_t *ahdr = cl.model_precache[i]->aliashdr; aliashdr_t *ahdr = cl_world.models.a[i]->aliashdr;
if (!ahdr) if (!ahdr)
ahdr = Cache_Get (&cl.model_precache[i]->cache); ahdr = Cache_Get (&cl_world.models.a[i]->cache);
Info_SetValueForKey (cls.userinfo, info_key, va (0, "%d", Info_SetValueForKey (cls.userinfo, info_key, va (0, "%d",
ahdr->crc), ahdr->crc),
0); 0);
@ -398,14 +339,14 @@ Model_NextDownload (void)
SZ_Print (&cls.netchan.message, va (0, "setinfo %s %d", SZ_Print (&cls.netchan.message, va (0, "setinfo %s %d",
info_key, ahdr->crc)); info_key, ahdr->crc));
} }
if (!cl.model_precache[i]->aliashdr) if (!cl_world.models.a[i]->aliashdr)
Cache_Release (&cl.model_precache[i]->cache); Cache_Release (&cl_world.models.a[i]->cache);
} }
} }
// Something went wrong (probably in the server, probably a TF server) // Something went wrong (probably in the server, probably a TF server)
// We need to disconnect gracefully. // We need to disconnect gracefully.
if (!cl.model_precache[1]) { if (!cl_world.models.a[1]) {
Sys_Printf ("\nThe server has failed to provide the map name.\n\n"); Sys_Printf ("\nThe server has failed to provide the map name.\n\n");
Sys_Printf ("Disconnecting to prevent a crash.\n\n"); Sys_Printf ("Disconnecting to prevent a crash.\n\n");
CL_Disconnect (); CL_Disconnect ();
@ -413,8 +354,8 @@ Model_NextDownload (void)
} }
// all done // all done
cl.worldmodel = cl.model_precache[1]; cl_world.worldmodel = cl_world.models.a[1];
cl.chasestate.worldmodel = cl.worldmodel; cl.chasestate.worldmodel = cl_world.worldmodel;
CL_NewMap (cl.model_name[1]); CL_NewMap (cl.model_name[1]);
// done with modellist, request first of static signon messages // done with modellist, request first of static signon messages
@ -422,7 +363,7 @@ Model_NextDownload (void)
MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
MSG_WriteString (&cls.netchan.message, MSG_WriteString (&cls.netchan.message,
va (0, prespawn_name, cl.servercount, va (0, prespawn_name, cl.servercount,
cl.worldmodel->brush.checksum2)); cl_world.worldmodel->brush.checksum2));
} }
} }
@ -453,7 +394,8 @@ Sound_NextDownload (void)
} }
// done with sounds, request models now // done with sounds, request models now
memset (cl.model_precache, 0, sizeof (cl.model_precache)); cl_world.models.size = 0;
DARRAY_APPEND (&cl_world.models, 0);// ind 0 is null model
cl_playerindex = -1; cl_playerindex = -1;
cl_flagindex = -1; cl_flagindex = -1;
cl_h_playerindex = -1; cl_h_playerindex = -1;
@ -832,7 +774,6 @@ CL_ParseServerData (void)
} }
cl.viewentity = cl.playernum + 1; cl.viewentity = cl.playernum + 1;
cl.viewstate.player_entity = &cl_entities[cl.viewentity];
cl.viewstate.bob_enabled = !cl.spectator; cl.viewstate.bob_enabled = !cl.spectator;
// get the full level name // get the full level name
@ -957,54 +898,6 @@ CL_ParseModellist (void)
Model_NextDownload (); Model_NextDownload ();
} }
static void
CL_ParseBaseline (entity_state_t *es)
{
es->modelindex = MSG_ReadByte (net_message);
es->frame = MSG_ReadByte (net_message);
es->colormap = MSG_ReadByte (net_message);
es->skinnum = MSG_ReadByte (net_message);
MSG_ReadCoordAngleV (net_message, &es->origin[0], es->angles);//FIXME
es->origin[3] = 1;
// LordHavoc: set up baseline to for new effects (alpha, colormod, etc)
es->colormod = 255;
es->alpha = 255;
es->scale = 16;
es->glow_size = 0;
es->glow_color = 254;
}
/*
CL_ParseStatic
Static entities are non-interactive world objects
like torches
*/
static void
CL_ParseStatic (void)
{
entity_t *ent;
entity_state_t es;
CL_ParseBaseline (&es);
ent = r_funcs->R_AllocEntity ();
CL_Init_Entity (ent);
DARRAY_APPEND (&cl_static_entities, es);
// copy it to the current state
ent->renderer.model = cl.model_precache[es.modelindex];
ent->animation.frame = es.frame;
ent->renderer.skinnum = es.skinnum;
CL_TransformEntity (ent, es.scale / 16.0, es.angles, es.origin);
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent);
}
static void static void
CL_ParseStaticSound (void) CL_ParseStaticSound (void)
{ {
@ -1275,7 +1168,7 @@ CL_SetStat (int stat, int value)
break; break;
} }
cl.stats[stat] = value; cl.stats[stat] = value;
cl.viewstate.weapon_model = cl.model_precache[cl.stats[STAT_WEAPON]]; cl.viewstate.weapon_model = cl_world.models.a[cl.stats[STAT_WEAPON]];
} }
static void static void
@ -1318,7 +1211,7 @@ CL_ParseServerMessage (void)
const char *str; const char *str;
static dstring_t *stuffbuf; static dstring_t *stuffbuf;
TEntContext_t tentCtx = { TEntContext_t tentCtx = {
cl.viewstate.player_origin, cl.worldmodel, cl.viewentity cl.viewstate.player_origin, cl.viewentity
}; };
received_framecount = host_framecount; received_framecount = host_framecount;
@ -1513,14 +1406,14 @@ CL_ParseServerMessage (void)
break; break;
case svc_spawnstatic: case svc_spawnstatic:
CL_ParseStatic (); CL_ParseStatic (net_message, 1);
break; break;
// svc_spawnbinary // svc_spawnbinary
case svc_spawnbaseline: case svc_spawnbaseline:
i = MSG_ReadShort (net_message); i = MSG_ReadShort (net_message);
CL_ParseBaseline (&qw_entstates.baseline[i]); CL_ParseBaseline (net_message, &qw_entstates.baseline[i], 1);
break; break;
case svc_temp_entity: case svc_temp_entity:

View file

@ -51,6 +51,7 @@
#include "client/hud.h" #include "client/hud.h"
#include "client/view.h" #include "client/view.h"
#include "client/world.h"
#include "qw/include/client.h" #include "qw/include/client.h"
#include "qw/include/cl_parse.h" #include "qw/include/cl_parse.h"
@ -77,11 +78,11 @@ SCR_CShift (void)
mleaf_t *leaf; mleaf_t *leaf;
int contents = CONTENTS_EMPTY; int contents = CONTENTS_EMPTY;
if (cls.state == ca_active && cl.worldmodel) { if (cls.state == ca_active && cl_world.worldmodel) {
vec4f_t origin; vec4f_t origin;
origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); origin = Transform_GetWorldPosition (cl.viewstate.camera_transform);
//FIXME //FIXME
leaf = Mod_PointInLeaf (&origin[0], cl.worldmodel); leaf = Mod_PointInLeaf (&origin[0], cl_world.worldmodel);
contents = leaf->contents; contents = leaf->contents;
} }
V_SetContentsColor (&cl.viewstate, contents); V_SetContentsColor (&cl.viewstate, contents);

View file

@ -58,6 +58,7 @@
#include "compat.h" #include "compat.h"
#include "client/hud.h" #include "client/hud.h"
#include "client/world.h"
#include "qw/bothdefs.h" #include "qw/bothdefs.h"
#include "qw/include/cl_cam.h" #include "qw/include/cl_cam.h"
@ -1109,8 +1110,8 @@ Sbar_LogFrags (void)
if (t) if (t)
Qwrite (file, t, strlen (t)); Qwrite (file, t, strlen (t));
Qprintf (file, "%s\n%s %s\n", cls.servername->str, cl.worldmodel->path, Qprintf (file, "%s\n%s %s\n", cls.servername->str,
cl.levelname); cl_world.worldmodel->path, cl.levelname);
// scores // scores
Sbar_SortFrags (true); Sbar_SortFrags (true);

View file

@ -52,6 +52,7 @@
#include "compat.h" #include "compat.h"
#include "client/locs.h" #include "client/locs.h"
#include "client/world.h"
#include "qw/bothdefs.h" #include "qw/bothdefs.h"
#include "qw/include/cl_input.h" #include "qw/include/cl_input.h"
@ -289,8 +290,8 @@ Team_NewMap (void)
died = false; died = false;
recorded_location = false; recorded_location = false;
mapname = strdup (cl.worldmodel->path); mapname = strdup (cl_world.worldmodel->path);
t2 = malloc (sizeof (cl.worldmodel->path)); t2 = malloc (sizeof (cl_world.worldmodel->path));
if (!mapname || !t2) if (!mapname || !t2)
Sys_Error ("Can't duplicate mapname!"); Sys_Error ("Can't duplicate mapname!");
map_to_loc (mapname,t2); map_to_loc (mapname,t2);
@ -340,16 +341,16 @@ locs_loc (void)
"parameter\n"); "parameter\n");
return; return;
} }
if (!cl.worldmodel) { if (!cl_world.worldmodel) {
Sys_Printf ("No map loaded. Unable to work with location markers.\n"); Sys_Printf ("No map loaded. Unable to work with location markers.\n");
return; return;
} }
if (Cmd_Argc () >= 3) if (Cmd_Argc () >= 3)
desc = Cmd_Args (2); desc = Cmd_Args (2);
mapname = malloc (sizeof (cl.worldmodel->path)); mapname = malloc (sizeof (cl_world.worldmodel->path));
if (!mapname) if (!mapname)
Sys_Error ("Can't duplicate mapname!"); Sys_Error ("Can't duplicate mapname!");
map_to_loc (cl.worldmodel->path, mapname); map_to_loc (cl_world.worldmodel->path, mapname);
snprintf (locfile, sizeof (locfile), "%s/%s", snprintf (locfile, sizeof (locfile), "%s/%s",
qfs_gamedir->dir.def, mapname); qfs_gamedir->dir.def, mapname);
free (mapname); free (mapname);