Quake II RTX doxygen  1.0 dev
game.c File Reference
#include "server.h"

Go to the source code of this file.

Macros

#define CHECK_PARAMS
 

Functions

static void PF_configstring (int index, const char *val)
 
static int PF_FindIndex (const char *name, int start, int max)
 
static int PF_ModelIndex (const char *name)
 
static int PF_SoundIndex (const char *name)
 
static int PF_ImageIndex (const char *name)
 
static void PF_Unicast (edict_t *ent, qboolean reliable)
 
static void PF_bprintf (int level, const char *fmt,...)
 
static void PF_dprintf (const char *fmt,...)
 
static void PF_cprintf (edict_t *ent, int level, const char *fmt,...)
 
static void PF_centerprintf (edict_t *ent, const char *fmt,...)
 
static q_noreturn void PF_error (const char *fmt,...)
 
static void PF_setmodel (edict_t *ent, const char *name)
 
static void PF_WriteFloat (float f)
 
static qboolean PF_inVIS (vec3_t p1, vec3_t p2, int vis)
 
static qboolean PF_inPVS (vec3_t p1, vec3_t p2)
 
static qboolean PF_inPHS (vec3_t p1, vec3_t p2)
 
static void PF_StartSound (edict_t *edict, int channel, int soundindex, float volume, float attenuation, float timeofs)
 
static void PF_PositionedSound (vec3_t origin, edict_t *entity, int channel, int soundindex, float volume, float attenuation, float timeofs)
 
void PF_Pmove (pmove_t *pm)
 
static cvar_t * PF_cvar (const char *name, const char *value, int flags)
 
static void PF_AddCommandString (const char *string)
 
static void PF_SetAreaPortalState (int portalnum, qboolean open)
 
static qboolean PF_AreasConnected (int area1, int area2)
 
static voidPF_TagMalloc (size_t size, unsigned tag)
 
static void PF_FreeTags (unsigned tag)
 
static void PF_DebugGraph (float value, int color)
 
void SV_ShutdownGameProgs (void)
 
static void_SV_LoadGameLibrary (const char *path)
 
static voidSV_LoadGameLibrary (const char *game, const char *prefix)
 
void SV_InitGameProgs (void)
 

Variables

game_export_t * ge
 
static voidgame_library
 

Macro Definition Documentation

◆ CHECK_PARAMS

#define CHECK_PARAMS
Value:
if (volume < 0 || volume > 1.0) \
Com_Error(ERR_DROP, "%s: volume = %f", __func__, volume); \
if (attenuation < 0 || attenuation > 4) \
Com_Error(ERR_DROP, "%s: attenuation = %f", __func__, attenuation); \
if (timeofs < 0 || timeofs > 0.255) \
Com_Error(ERR_DROP, "%s: timeofs = %f", __func__, timeofs); \
if (soundindex < 0 || soundindex >= MAX_SOUNDS) \
Com_Error(ERR_DROP, "%s: soundindex = %d", __func__, soundindex);

Definition at line 501 of file game.c.

Function Documentation

◆ _SV_LoadGameLibrary()

static void* _SV_LoadGameLibrary ( const char *  path)
static

Definition at line 799 of file game.c.

800 {
801  void *entry;
802 
803  entry = Sys_LoadLibrary(path, "GetGameAPI", &game_library);
804  if (!entry)
805  Com_EPrintf("Failed to load game library: %s\n", Com_GetLastError());
806  else
807  Com_Printf("Loaded game library from %s\n", path);
808 
809  return entry;
810 }

Referenced by SV_InitGameProgs(), and SV_LoadGameLibrary().

◆ PF_AddCommandString()

static void PF_AddCommandString ( const char *  string)
static

Definition at line 727 of file game.c.

728 {
729  Cbuf_AddText(&cmd_buffer, string);
730 }

Referenced by SV_InitGameProgs().

◆ PF_AreasConnected()

static qboolean PF_AreasConnected ( int  area1,
int  area2 
)
static

Definition at line 740 of file game.c.

741 {
742  if (!sv.cm.cache) {
743  Com_Error(ERR_DROP, "%s: no map loaded", __func__);
744  }
745  return CM_AreasConnected(&sv.cm, area1, area2);
746 }

Referenced by SV_InitGameProgs().

◆ PF_bprintf()

static void PF_bprintf ( int  level,
const char *  fmt,
  ... 
)
static

Definition at line 140 of file game.c.

141 {
142  va_list argptr;
143  char string[MAX_STRING_CHARS];
144  client_t *client;
145  size_t len;
146  int i;
147 
148  va_start(argptr, fmt);
149  len = Q_vsnprintf(string, sizeof(string), fmt, argptr);
150  va_end(argptr);
151 
152  if (len >= sizeof(string)) {
153  Com_WPrintf("%s: overflow\n", __func__);
154  return;
155  }
156 
157  SV_MvdBroadcastPrint(level, string);
158 
159  MSG_WriteByte(svc_print);
161  MSG_WriteData(string, len + 1);
162 
163  // echo to console
164  if (COM_DEDICATED) {
165  // mask off high bits
166  for (i = 0; i < len; i++)
167  string[i] &= 127;
168  Com_Printf("%s", string);
169  }
170 
171  FOR_EACH_CLIENT(client) {
172  if (client->state != cs_spawned)
173  continue;
174  if (level >= client->messagelevel) {
176  }
177  }
178 
180 }

Referenced by SV_InitGameProgs().

◆ PF_centerprintf()

static void PF_centerprintf ( edict_t *  ent,
const char *  fmt,
  ... 
)
static

Definition at line 266 of file game.c.

267 {
268  char msg[MAX_STRING_CHARS];
269  va_list argptr;
270  int n;
271  size_t len;
272 
273  if (!ent) {
274  return;
275  }
276 
277  n = NUM_FOR_EDICT(ent);
278  if (n < 1 || n > sv_maxclients->integer) {
279  Com_WPrintf("%s to a non-client %d\n", __func__, n - 1);
280  return;
281  }
282 
283  va_start(argptr, fmt);
284  len = Q_vsnprintf(msg, sizeof(msg), fmt, argptr);
285  va_end(argptr);
286 
287  if (len >= sizeof(msg)) {
288  Com_WPrintf("%s: overflow\n", __func__);
289  return;
290  }
291 
292  MSG_WriteByte(svc_centerprint);
293  MSG_WriteData(msg, len + 1);
294 
295  PF_Unicast(ent, qtrue);
296 }

Referenced by SV_InitGameProgs().

◆ PF_configstring()

static void PF_configstring ( int  index,
const char *  val 
)
static

Definition at line 356 of file game.c.

357 {
358  size_t len, maxlen;
359  client_t *client;
360  char *dst;
361 
362  if (index < 0 || index >= MAX_CONFIGSTRINGS)
363  Com_Error(ERR_DROP, "%s: bad index: %d", __func__, index);
364 
365  if (sv.state == ss_dead) {
366  Com_WPrintf("%s: not yet initialized\n", __func__);
367  return;
368  }
369 
370  if (!val)
371  val = "";
372 
373  // error out entirely if it exceedes array bounds
374  len = strlen(val);
375  maxlen = (MAX_CONFIGSTRINGS - index) * MAX_QPATH;
376  if (len >= maxlen) {
377  Com_Error(ERR_DROP,
378  "%s: index %d overflowed: %"PRIz" > %"PRIz,
379  __func__, index, len, maxlen - 1);
380  }
381 
382  // print a warning and truncate everything else
383  maxlen = CS_SIZE(index);
384  if (len >= maxlen) {
385  Com_WPrintf(
386  "%s: index %d overflowed: %"PRIz" > %"PRIz"\n",
387  __func__, index, len, maxlen - 1);
388  len = maxlen - 1;
389  }
390 
391  dst = sv.configstrings[index];
392  if (!strncmp(dst, val, len)) {
393  return;
394  }
395 
396  // change the string in sv
397  memcpy(dst, val, len);
398  dst[len] = 0;
399 
400  if (sv.state == ss_loading) {
401  return;
402  }
403 
404  SV_MvdConfigstring(index, val, len);
405 
406  // send the update to everyone
407  MSG_WriteByte(svc_configstring);
408  MSG_WriteShort(index);
409  MSG_WriteData(val, len);
410  MSG_WriteByte(0);
411 
412  FOR_EACH_CLIENT(client) {
413  if (client->state < cs_primed) {
414  continue;
415  }
417  }
418 
420 }

Referenced by PF_FindIndex(), and SV_InitGameProgs().

◆ PF_cprintf()

static void PF_cprintf ( edict_t *  ent,
int  level,
const char *  fmt,
  ... 
)
static

Definition at line 211 of file game.c.

212 {
213  char msg[MAX_STRING_CHARS];
214  va_list argptr;
215  int clientNum;
216  size_t len;
217  client_t *client;
218 
219  va_start(argptr, fmt);
220  len = Q_vsnprintf(msg, sizeof(msg), fmt, argptr);
221  va_end(argptr);
222 
223  if (len >= sizeof(msg)) {
224  Com_WPrintf("%s: overflow\n", __func__);
225  return;
226  }
227 
228  if (!ent) {
229  Com_LPrintf(level == PRINT_CHAT ? PRINT_TALK : PRINT_ALL, "%s", msg);
230  return;
231  }
232 
233  clientNum = NUM_FOR_EDICT(ent) - 1;
234  if (clientNum < 0 || clientNum >= sv_maxclients->integer) {
235  Com_Error(ERR_DROP, "%s to a non-client %d", __func__, clientNum);
236  }
237 
238  client = svs.client_pool + clientNum;
239  if (client->state <= cs_zombie) {
240  Com_WPrintf("%s to a free/zombie client %d\n", __func__, clientNum);
241  return;
242  }
243 
244  MSG_WriteByte(svc_print);
246  MSG_WriteData(msg, len + 1);
247 
248  if (level >= client->messagelevel) {
250  }
251 
252  SV_MvdUnicast(ent, clientNum, qtrue);
253 
255 }

Referenced by SV_InitGameProgs().

◆ PF_cvar()

static cvar_t* PF_cvar ( const char *  name,
const char *  value,
int  flags 
)
static

Definition at line 717 of file game.c.

718 {
719  if (flags & CVAR_EXTENDED_MASK) {
720  Com_WPrintf("Game attemped to set extended flags on '%s', masked out.\n", name);
721  flags &= ~CVAR_EXTENDED_MASK;
722  }
723 
724  return Cvar_Get(name, value, flags | CVAR_GAME);
725 }

Referenced by SV_InitGameProgs().

◆ PF_DebugGraph()

static void PF_DebugGraph ( float  value,
int  color 
)
static

Definition at line 767 of file game.c.

768 {
769 #if (defined _DEBUG) && USE_CLIENT
770  SCR_DebugGraph(value, color);
771 #endif
772 }

Referenced by SV_InitGameProgs().

◆ PF_dprintf()

static void PF_dprintf ( const char *  fmt,
  ... 
)
static

Definition at line 190 of file game.c.

191 {
192  char msg[MAXPRINTMSG];
193  va_list argptr;
194 
195  va_start(argptr, fmt);
196  Q_vsnprintf(msg, sizeof(msg), fmt, argptr);
197  va_end(argptr);
198 
199  Com_Printf("%s", msg);
200 }

Referenced by SV_InitGameProgs().

◆ PF_error()

static q_noreturn void PF_error ( const char *  fmt,
  ... 
)
static

Definition at line 306 of file game.c.

307 {
308  char msg[MAXERRORMSG];
309  va_list argptr;
310 
311  va_start(argptr, fmt);
312  Q_vsnprintf(msg, sizeof(msg), fmt, argptr);
313  va_end(argptr);
314 
315  Com_Error(ERR_DROP, "Game Error: %s", msg);
316 }

Referenced by SV_InitGameProgs().

◆ PF_FindIndex()

static int PF_FindIndex ( const char *  name,
int  start,
int  max 
)
static

Definition at line 32 of file game.c.

33 {
34  char *string;
35  int i;
36 
37  if (!name || !name[0])
38  return 0;
39 
40  for (i = 1; i < max; i++) {
41  string = sv.configstrings[start + i];
42  if (!string[0]) {
43  break;
44  }
45  if (!strcmp(string, name)) {
46  return i;
47  }
48  }
49 
50  if (i == max)
51  Com_Error(ERR_DROP, "PF_FindIndex: overflow");
52 
53  PF_configstring(i + start, name);
54 
55  return i;
56 }

Referenced by PF_ImageIndex(), PF_ModelIndex(), and PF_SoundIndex().

◆ PF_FreeTags()

static void PF_FreeTags ( unsigned  tag)
static

Definition at line 759 of file game.c.

760 {
761  if (tag + TAG_MAX < tag) {
762  Com_Error(ERR_FATAL, "%s: bad tag", __func__);
763  }
764  Z_FreeTags(tag + TAG_MAX);
765 }

Referenced by SV_InitGameProgs().

◆ PF_ImageIndex()

static int PF_ImageIndex ( const char *  name)
static

Definition at line 68 of file game.c.

69 {
70  return PF_FindIndex(name, CS_IMAGES, MAX_IMAGES);
71 }

Referenced by SV_InitGameProgs().

◆ PF_inPHS()

static qboolean PF_inPHS ( vec3_t  p1,
vec3_t  p2 
)
static

Definition at line 469 of file game.c.

470 {
471  return PF_inVIS(p1, p2, DVIS_PHS);
472 }

Referenced by SV_InitGameProgs().

◆ PF_inPVS()

static qboolean PF_inPVS ( vec3_t  p1,
vec3_t  p2 
)
static

Definition at line 457 of file game.c.

458 {
459  return PF_inVIS(p1, p2, DVIS_PVS);
460 }

Referenced by SV_InitGameProgs().

◆ PF_inVIS()

static qboolean PF_inVIS ( vec3_t  p1,
vec3_t  p2,
int  vis 
)
static

Definition at line 427 of file game.c.

428 {
429  mleaf_t *leaf1, *leaf2;
430  byte mask[VIS_MAX_BYTES];
431  bsp_t *bsp = sv.cm.cache;
432 
433  if (!bsp) {
434  Com_Error(ERR_DROP, "%s: no map loaded", __func__);
435  }
436 
437  leaf1 = BSP_PointLeaf(bsp->nodes, p1);
438  BSP_ClusterVis(bsp, mask, leaf1->cluster, vis);
439 
440  leaf2 = BSP_PointLeaf(bsp->nodes, p2);
441  if (leaf2->cluster == -1)
442  return qfalse;
443  if (!Q_IsBitSet(mask, leaf2->cluster))
444  return qfalse;
445  if (!CM_AreasConnected(&sv.cm, leaf1->area, leaf2->area))
446  return qfalse; // a door blocks it
447  return qtrue;
448 }

Referenced by PF_inPHS(), and PF_inPVS().

◆ PF_ModelIndex()

static int PF_ModelIndex ( const char *  name)
static

Definition at line 58 of file game.c.

59 {
60  return PF_FindIndex(name, CS_MODELS, MAX_MODELS);
61 }

Referenced by PF_setmodel(), and SV_InitGameProgs().

◆ PF_Pmove()

void PF_Pmove ( pmove_t *  pm)

Definition at line 708 of file game.c.

709 {
710  if (sv_client) {
711  Pmove(pm, &sv_client->pmp);
712  } else {
713  Pmove(pm, &sv_pmp);
714  }
715 }

Referenced by MVD_GameClientThink(), and SV_InitGameProgs().

◆ PF_PositionedSound()

static void PF_PositionedSound ( vec3_t  origin,
edict_t *  entity,
int  channel,
int  soundindex,
float  volume,
float  attenuation,
float  timeofs 
)
static

Definition at line 651 of file game.c.

654 {
655  int sendchan;
656  int flags;
657  int ent;
658 
659  if (!origin)
660  Com_Error(ERR_DROP, "%s: NULL origin", __func__);
662 
663  ent = NUM_FOR_EDICT(entity);
664 
665  sendchan = (ent << 3) | (channel & 7);
666 
667  // always send the entity number for channel overrides
668  flags = SND_ENT | SND_POS;
669  if (volume != DEFAULT_SOUND_PACKET_VOLUME)
670  flags |= SND_VOLUME;
671  if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
672  flags |= SND_ATTENUATION;
673  if (timeofs)
674  flags |= SND_OFFSET;
675 
676  MSG_WriteByte(svc_sound);
677  MSG_WriteByte(flags);
678  MSG_WriteByte(soundindex);
679 
680  if (flags & SND_VOLUME)
681  MSG_WriteByte(volume * 255);
682  if (flags & SND_ATTENUATION)
683  MSG_WriteByte(attenuation * 64);
684  if (flags & SND_OFFSET)
685  MSG_WriteByte(timeofs * 1000);
686 
687  MSG_WriteShort(sendchan);
689 
690  // if the sound doesn't attenuate,send it to everyone
691  // (global radio chatter, voiceovers, etc)
692  if (attenuation == ATTN_NONE || (channel & CHAN_NO_PHS_ADD)) {
693  if (channel & CHAN_RELIABLE) {
694  SV_Multicast(NULL, MULTICAST_ALL_R);
695  } else {
696  SV_Multicast(NULL, MULTICAST_ALL);
697  }
698  } else {
699  if (channel & CHAN_RELIABLE) {
700  SV_Multicast(origin, MULTICAST_PHS_R);
701  } else {
702  SV_Multicast(origin, MULTICAST_PHS);
703  }
704  }
705 }

Referenced by SV_InitGameProgs().

◆ PF_SetAreaPortalState()

static void PF_SetAreaPortalState ( int  portalnum,
qboolean  open 
)
static

Definition at line 732 of file game.c.

733 {
734  if (!sv.cm.cache) {
735  Com_Error(ERR_DROP, "%s: no map loaded", __func__);
736  }
737  CM_SetAreaPortalState(&sv.cm, portalnum, open);
738 }

Referenced by SV_InitGameProgs().

◆ PF_setmodel()

static void PF_setmodel ( edict_t *  ent,
const char *  name 
)
static

Definition at line 326 of file game.c.

327 {
328  int i;
329  mmodel_t *mod;
330 
331  if (!name)
332  Com_Error(ERR_DROP, "PF_setmodel: NULL");
333 
334  i = PF_ModelIndex(name);
335 
336  ent->s.modelindex = i;
337 
338 // if it is an inline model, get the size information for it
339  if (name[0] == '*') {
340  mod = CM_InlineModel(&sv.cm, name);
341  VectorCopy(mod->mins, ent->mins);
342  VectorCopy(mod->maxs, ent->maxs);
343  PF_LinkEdict(ent);
344  }
345 
346 }

Referenced by SV_InitGameProgs().

◆ PF_SoundIndex()

static int PF_SoundIndex ( const char *  name)
static

Definition at line 63 of file game.c.

64 {
65  return PF_FindIndex(name, CS_SOUNDS, MAX_SOUNDS);
66 }

Referenced by SV_InitGameProgs().

◆ PF_StartSound()

static void PF_StartSound ( edict_t *  edict,
int  channel,
int  soundindex,
float  volume,
float  attenuation,
float  timeofs 
)
static

Definition at line 511 of file game.c.

514 {
515  int sendchan;
516  int flags;
517  int ent;
518  vec3_t origin;
519  client_t *client;
520  byte mask[VIS_MAX_BYTES];
521  mleaf_t *leaf;
522  int area;
523  player_state_t *ps;
525  int i;
526 
527  if (!edict)
528  return;
529 
531 
532  ent = NUM_FOR_EDICT(edict);
533 
534  if ((g_features->integer & GMF_PROPERINUSE) && !edict->inuse) {
535  Com_DPrintf("%s: entnum not in use: %d\n", __func__, ent);
536  return;
537  }
538 
539  sendchan = (ent << 3) | (channel & 7);
540 
541  // always send the entity number for channel overrides
542  flags = SND_ENT;
543  if (volume != DEFAULT_SOUND_PACKET_VOLUME)
544  flags |= SND_VOLUME;
545  if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
546  flags |= SND_ATTENUATION;
547  if (timeofs)
548  flags |= SND_OFFSET;
549 
550  // if the sound doesn't attenuate,send it to everyone
551  // (global radio chatter, voiceovers, etc)
552  if (attenuation == ATTN_NONE) {
553  channel |= CHAN_NO_PHS_ADD;
554  }
555 
556  FOR_EACH_CLIENT(client) {
557  // do not send sounds to connecting clients
558  if (client->state != cs_spawned || client->download || client->nodata) {
559  continue;
560  }
561 
562  // PHS cull this sound
563  if (!(channel & CHAN_NO_PHS_ADD)) {
564  // get client viewpos
565  ps = &client->edict->client->ps;
566  VectorMA(ps->viewoffset, 0.125f, ps->pmove.origin, origin);
567  leaf = CM_PointLeaf(&sv.cm, origin);
568  area = CM_LeafArea(leaf);
569  if (!CM_AreasConnected(&sv.cm, area, edict->areanum)) {
570  // doors can legally straddle two areas, so
571  // we may need to check another one
572  if (!edict->areanum2 || !CM_AreasConnected(&sv.cm, area, edict->areanum2)) {
573  continue; // blocked by a door
574  }
575  }
576  BSP_ClusterVis(sv.cm.cache, mask, leaf->cluster, DVIS_PHS);
577  if (!SV_EdictIsVisible(&sv.cm, edict, mask)) {
578  continue; // not in PHS
579  }
580  }
581 
582  // use the entity origin unless it is a bmodel
583  if (edict->solid == SOLID_BSP) {
584  VectorAvg(edict->mins, edict->maxs, origin);
585  VectorAdd(edict->s.origin, origin, origin);
586  } else {
587  VectorCopy(edict->s.origin, origin);
588  }
589 
590  // reliable sounds will always have position explicitly set,
591  // as no one gurantees reliables to be delivered in time
592  if (channel & CHAN_RELIABLE) {
593  MSG_WriteByte(svc_sound);
594  MSG_WriteByte(flags | SND_POS);
595  MSG_WriteByte(soundindex);
596 
597  if (flags & SND_VOLUME)
598  MSG_WriteByte(volume * 255);
599  if (flags & SND_ATTENUATION)
600  MSG_WriteByte(attenuation * 64);
601  if (flags & SND_OFFSET)
602  MSG_WriteByte(timeofs * 1000);
603 
604  MSG_WriteShort(sendchan);
606 
608  continue;
609  }
610 
611  if (LIST_EMPTY(&client->msg_free_list)) {
612  Com_WPrintf("%s: %s: out of message slots\n",
613  __func__, client->name);
614  continue;
615  }
616 
617  // send origin for invisible entities
618  if (edict->svflags & SVF_NOCLIENT) {
619  flags |= SND_POS;
620  }
621 
622  // default client doesn't know that bmodels have weird origins
623  if (edict->solid == SOLID_BSP && client->protocol == PROTOCOL_VERSION_DEFAULT) {
624  flags |= SND_POS;
625  }
626 
627  msg = LIST_FIRST(message_packet_t, &client->msg_free_list, entry);
628 
629  msg->cursize = 0;
630  msg->flags = flags;
631  msg->index = soundindex;
632  msg->volume = volume * 255;
633  msg->attenuation = attenuation * 64;
634  msg->timeofs = timeofs * 1000;
635  msg->sendchan = sendchan;
636  for (i = 0; i < 3; i++) {
637  msg->pos[i] = origin[i] * 8;
638  }
639 
640  List_Remove(&msg->entry);
641  List_Append(&client->msg_unreliable_list, &msg->entry);
643 
644  flags &= ~SND_POS;
645  }
646 
647  SV_MvdStartSound(ent, channel, flags, soundindex,
648  volume * 255, attenuation * 64, timeofs * 1000);
649 }

Referenced by SV_InitGameProgs().

◆ PF_TagMalloc()

static void* PF_TagMalloc ( size_t  size,
unsigned  tag 
)
static

Definition at line 748 of file game.c.

749 {
750  if (tag + TAG_MAX < tag) {
751  Com_Error(ERR_FATAL, "%s: bad tag", __func__);
752  }
753  if (!size) {
754  return NULL;
755  }
756  return memset(Z_TagMalloc(size, tag + TAG_MAX), 0, size);
757 }

Referenced by SV_InitGameProgs().

◆ PF_Unicast()

static void PF_Unicast ( edict_t *  ent,
qboolean  reliable 
)
static

Definition at line 81 of file game.c.

82 {
83  client_t *client;
84  int cmd, flags, clientNum;
85 
86  if (!ent) {
87  goto clear;
88  }
89 
90  clientNum = NUM_FOR_EDICT(ent) - 1;
91  if (clientNum < 0 || clientNum >= sv_maxclients->integer) {
92  Com_WPrintf("%s to a non-client %d\n", __func__, clientNum);
93  goto clear;
94  }
95 
96  client = svs.client_pool + clientNum;
97  if (client->state <= cs_zombie) {
98  Com_WPrintf("%s to a free/zombie client %d\n", __func__, clientNum);
99  goto clear;
100  }
101 
102  if (!msg_write.cursize) {
103  Com_DPrintf("%s with empty data\n", __func__);
104  goto clear;
105  }
106 
107  cmd = msg_write.data[0];
108 
109  flags = 0;
110  if (reliable) {
111  flags |= MSG_RELIABLE;
112  }
113 
114  if (cmd == svc_layout) {
115  flags |= MSG_COMPRESS;
116  }
117 
118  SV_ClientAddMessage(client, flags);
119 
120  // fix anti-kicking exploit for broken mods
121  if (cmd == svc_disconnect) {
122  client->drop_hack = qtrue;
123  goto clear;
124  }
125 
126  SV_MvdUnicast(ent, clientNum, reliable);
127 
128 clear:
130 }

Referenced by PF_centerprintf(), and SV_InitGameProgs().

◆ PF_WriteFloat()

static void PF_WriteFloat ( float  f)
static

Definition at line 422 of file game.c.

423 {
424  Com_Error(ERR_DROP, "PF_WriteFloat not implemented");
425 }

Referenced by SV_InitGameProgs().

◆ SV_InitGameProgs()

void SV_InitGameProgs ( void  )

Definition at line 841 of file game.c.

842 {
843  game_import_t import;
844  game_export_t *(*entry)(game_import_t *) = NULL;
845 
846  // unload anything we have now
848 
849  // for debugging or `proxy' mods
850  if (sys_forcegamelib->string[0])
851  entry = _SV_LoadGameLibrary(sys_forcegamelib->string);
852 
853  // try game first
854  if (!entry && fs_game->string[0]) {
855  entry = SV_LoadGameLibrary(fs_game->string, "q2pro_");
856  if (!entry)
857  entry = SV_LoadGameLibrary(fs_game->string, "");
858  }
859 
860  // then try baseq2
861  if (!entry) {
862  entry = SV_LoadGameLibrary(BASEGAME, "q2pro_");
863  if (!entry)
864  entry = SV_LoadGameLibrary(BASEGAME, "");
865  }
866 
867  // all paths failed
868  if (!entry)
869  Com_Error(ERR_DROP, "Failed to load game library");
870 
871  // load a new game dll
872  import.multicast = SV_Multicast;
873  import.unicast = PF_Unicast;
874  import.bprintf = PF_bprintf;
875  import.dprintf = PF_dprintf;
876  import.cprintf = PF_cprintf;
877  import.centerprintf = PF_centerprintf;
878  import.error = PF_error;
879 
880  import.linkentity = PF_LinkEdict;
881  import.unlinkentity = PF_UnlinkEdict;
882  import.BoxEdicts = SV_AreaEdicts;
883  import.trace = SV_Trace;
884  import.pointcontents = SV_PointContents;
885  import.setmodel = PF_setmodel;
886  import.inPVS = PF_inPVS;
887  import.inPHS = PF_inPHS;
888  import.Pmove = PF_Pmove;
889 
890  import.modelindex = PF_ModelIndex;
891  import.soundindex = PF_SoundIndex;
892  import.imageindex = PF_ImageIndex;
893 
894  import.configstring = PF_configstring;
895  import.sound = PF_StartSound;
896  import.positioned_sound = PF_PositionedSound;
897 
898  import.WriteChar = MSG_WriteChar;
899  import.WriteByte = MSG_WriteByte;
900  import.WriteShort = MSG_WriteShort;
901  import.WriteLong = MSG_WriteLong;
902  import.WriteFloat = PF_WriteFloat;
903  import.WriteString = MSG_WriteString;
904  import.WritePosition = MSG_WritePos;
905  import.WriteDir = MSG_WriteDir;
906  import.WriteAngle = MSG_WriteAngle;
907 
908  import.TagMalloc = PF_TagMalloc;
909  import.TagFree = Z_Free;
910  import.FreeTags = PF_FreeTags;
911 
912  import.cvar = PF_cvar;
913  import.cvar_set = Cvar_UserSet;
914  import.cvar_forceset = Cvar_Set;
915 
916  import.argc = Cmd_Argc;
917  import.argv = Cmd_Argv;
918  // original Cmd_Args() did actually return raw arguments
919  import.args = Cmd_RawArgs;
920  import.AddCommandString = PF_AddCommandString;
921 
922  import.DebugGraph = PF_DebugGraph;
923  import.SetAreaPortalState = PF_SetAreaPortalState;
924  import.AreasConnected = PF_AreasConnected;
925 
926  ge = entry(&import);
927  if (!ge) {
928  Com_Error(ERR_DROP, "Game DLL returned NULL exports");
929  }
930 
931  if (ge->apiversion != GAME_API_VERSION) {
932  Com_Error(ERR_DROP, "Game DLL is version %d, expected %d",
933  ge->apiversion, GAME_API_VERSION);
934  }
935 
936  // initialize
937  ge->Init();
938 
939  // sanitize edict_size
940  if (ge->edict_size < sizeof(edict_t) || ge->edict_size > SIZE_MAX / MAX_EDICTS) {
941  Com_Error(ERR_DROP, "Game DLL returned bad size of edict_t");
942  }
943 
944  // sanitize max_edicts
945  if (ge->max_edicts <= sv_maxclients->integer || ge->max_edicts > MAX_EDICTS) {
946  Com_Error(ERR_DROP, "Game DLL returned bad number of max_edicts");
947  }
948 }

Referenced by SV_InitGame().

◆ SV_LoadGameLibrary()

static void* SV_LoadGameLibrary ( const char *  game,
const char *  prefix 
)
static

Definition at line 812 of file game.c.

813 {
814  char path[MAX_OSPATH];
815  size_t len;
816 
817  len = Q_concat(path, sizeof(path), sys_libdir->string,
818  PATH_SEP_STRING, game, PATH_SEP_STRING,
819  prefix, "game" CPUSTRING LIBSUFFIX, NULL);
820  if (len >= sizeof(path)) {
821  Com_EPrintf("Game library path length exceeded\n");
822  return NULL;
823  }
824 
825  if (os_access(path, F_OK)) {
826  if (!*prefix)
827  Com_Printf("Can't access %s: %s\n", path, strerror(errno));
828  return NULL;
829  }
830 
831  return _SV_LoadGameLibrary(path);
832 }

Referenced by SV_InitGameProgs().

◆ SV_ShutdownGameProgs()

void SV_ShutdownGameProgs ( void  )

Definition at line 786 of file game.c.

787 {
788  if (ge) {
789  ge->Shutdown();
790  ge = NULL;
791  }
792  if (game_library) {
794  game_library = NULL;
795  }
796  Cvar_Set("g_features", "0");
797 }

Referenced by SV_InitGame(), SV_InitGameProgs(), and SV_Shutdown().

Variable Documentation

◆ game_library

void* game_library
static

Definition at line 776 of file game.c.

Referenced by _SV_LoadGameLibrary(), and SV_ShutdownGameProgs().

◆ ge

PF_inPVS
static qboolean PF_inPVS(vec3_t p1, vec3_t p2)
Definition: game.c:457
Cvar_Set
cvar_t * Cvar_Set(const char *var_name, const char *value)
Definition: cvar.c:466
cs_spawned
@ cs_spawned
Definition: server.h:192
SV_MvdStartSound
void SV_MvdStartSound(int entnum, int channel, int flags, int soundindex, int volume, int attenuation, int timeofs)
Definition: mvd.c:1257
pm
static pmove_t * pm
Definition: pmove.c:44
svs
server_static_t svs
Definition: init.c:21
PF_inVIS
static qboolean PF_inVIS(vec3_t p1, vec3_t p2, int vis)
Definition: game.c:427
client_s::protocol
int protocol
Definition: server.h:324
message_packet_t
Definition: server.h:220
PF_AddCommandString
static void PF_AddCommandString(const char *string)
Definition: game.c:727
client_s::msg_free_list
list_t msg_free_list
Definition: server.h:332
Cvar_Get
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags)
Definition: cvar.c:257
BSP_ClusterVis
byte * BSP_ClusterVis(bsp_t *bsp, byte *mask, int cluster, int vis)
Definition: bsp.c:1339
client_s::state
clstate_t state
Definition: server.h:260
MSG_CLEAR
#define MSG_CLEAR
Definition: server.h:215
PF_bprintf
static void PF_bprintf(int level, const char *fmt,...)
Definition: game.c:140
sys_libdir
cvar_t * sys_libdir
Definition: system.c:51
PF_cvar
static cvar_t * PF_cvar(const char *name, const char *value, int flags)
Definition: game.c:717
MSG_RELIABLE
#define MSG_RELIABLE
Definition: server.h:214
_SV_LoadGameLibrary
static void * _SV_LoadGameLibrary(const char *path)
Definition: game.c:799
SV_MvdUnicast
void SV_MvdUnicast(edict_t *ent, int clientNum, qboolean reliable)
Definition: mvd.c:1184
PF_PositionedSound
static void PF_PositionedSound(vec3_t origin, edict_t *entity, int channel, int soundindex, float volume, float attenuation, float timeofs)
Definition: game.c:651
Q_vsnprintf
size_t Q_vsnprintf(char *dest, size_t size, const char *fmt, va_list argptr)
Definition: shared.c:791
sv_client
client_t * sv_client
Definition: main.c:32
PF_ImageIndex
static int PF_ImageIndex(const char *name)
Definition: game.c:68
MSG_WriteByte
void MSG_WriteByte(int c)
Definition: msg.c:107
Cmd_Argv
char * Cmd_Argv(int arg)
Definition: cmd.c:899
SCR_DebugGraph
void SCR_DebugGraph(float value, int color)
SV_Multicast
void SV_Multicast(vec3_t origin, multicast_t to)
Definition: send.c:255
PF_setmodel
static void PF_setmodel(edict_t *ent, const char *name)
Definition: game.c:326
BSP_PointLeaf
mleaf_t * BSP_PointLeaf(mnode_t *node, vec3_t p)
Definition: bsp.c:1439
PF_LinkEdict
void PF_LinkEdict(edict_t *ent)
Definition: world.c:264
Cmd_Argc
int Cmd_Argc(void)
Definition: cmd.c:889
SV_ClientAddMessage
void SV_ClientAddMessage(client_t *client, int flags)
Definition: send.c:399
client_s::drop_hack
qboolean drop_hack
Definition: server.h:268
FOR_EACH_CLIENT
#define FOR_EACH_CLIENT(client)
Definition: server.h:239
SV_AreaEdicts
int SV_AreaEdicts(vec3_t mins, vec3_t maxs, edict_t **list, int maxcount, int areatype)
Definition: world.c:407
CM_AreasConnected
qboolean CM_AreasConnected(cm_t *cm, int area1, int area2)
Definition: cmodel.c:890
PF_SetAreaPortalState
static void PF_SetAreaPortalState(int portalnum, qboolean open)
Definition: game.c:732
cmd_buffer
cmdbuf_t cmd_buffer
Definition: cmd.c:49
MSG_WritePos
void MSG_WritePos(const vec3_t pos)
Definition: msg.c:198
client_s::nodata
qboolean nodata
Definition: server.h:266
Z_TagMalloc
void * Z_TagMalloc(size_t size, memtag_t tag)
Definition: zone.c:275
sv_pmp
pmoveParams_t sv_pmp
Definition: main.c:22
MSG_COMPRESS
#define MSG_COMPRESS
Definition: server.h:216
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
PF_error
static q_noreturn void PF_error(const char *fmt,...)
Definition: game.c:306
client_s::download
byte * download
Definition: server.h:315
NUM_FOR_EDICT
#define NUM_FOR_EDICT(e)
Definition: server.h:174
sv
server_t sv
Definition: init.c:22
PF_Pmove
void PF_Pmove(pmove_t *pm)
Definition: game.c:708
msg_write
sizebuf_t msg_write
Definition: msg.c:34
Cbuf_AddText
void Cbuf_AddText(cmdbuf_t *buf, const char *text)
Definition: cmd.c:95
Z_Free
void Z_Free(void *ptr)
Definition: zone.c:147
Pmove
void Pmove(pmove_t *pmove, pmoveParams_t *params)
Definition: pmove.c:1127
server_static_s::client_pool
client_t * client_pool
Definition: server.h:456
game
game_locals_t game
Definition: g_main.c:21
cs_zombie
@ cs_zombie
Definition: server.h:187
PF_UnlinkEdict
void PF_UnlinkEdict(edict_t *ent)
Definition: world.c:256
origin
static vec3_t origin
Definition: mesh.c:27
PF_ModelIndex
static int PF_ModelIndex(const char *name)
Definition: game.c:58
PF_centerprintf
static void PF_centerprintf(edict_t *ent, const char *fmt,...)
Definition: game.c:266
fs_game
cvar_t * fs_game
Definition: files.c:202
PF_DebugGraph
static void PF_DebugGraph(float value, int color)
Definition: game.c:767
Com_LPrintf
void Com_LPrintf(print_type_t type, const char *fmt,...)
Definition: g_main.c:242
Com_GetLastError
char * Com_GetLastError(void)
Definition: common.c:391
MSG_WriteShort
void MSG_WriteShort(int c)
Definition: msg.c:125
ge
game_export_t * ge
Definition: game.c:22
client_s::messagelevel
int messagelevel
Definition: server.h:277
Cvar_UserSet
cvar_t * Cvar_UserSet(const char *var_name, const char *value)
Definition: cvar.c:476
PF_dprintf
static void PF_dprintf(const char *fmt,...)
Definition: game.c:190
PF_WriteFloat
static void PF_WriteFloat(float f)
Definition: game.c:422
Sys_LoadLibrary
void * Sys_LoadLibrary(const char *path, const char *sym, void **handle)
Definition: system.c:794
server_t::cm
cm_t cm
Definition: server.h:161
MSG_WriteString
void MSG_WriteString(const char *string)
Definition: msg.c:160
MSG_WriteLong
void MSG_WriteLong(int c)
Definition: msg.c:144
PF_inPHS
static qboolean PF_inPHS(vec3_t p1, vec3_t p2)
Definition: game.c:469
CHECK_PARAMS
#define CHECK_PARAMS
Definition: game.c:501
sys_forcegamelib
cvar_t * sys_forcegamelib
Definition: system.c:53
CM_PointLeaf
mleaf_t * CM_PointLeaf(cm_t *cm, vec3_t p)
Definition: cmodel.c:209
SV_PointContents
int SV_PointContents(vec3_t p)
Definition: world.c:454
MAX_SOUND_PACKET
#define MAX_SOUND_PACKET
Definition: server.h:218
g_features
cvar_t * g_features
Definition: main.c:99
PF_SoundIndex
static int PF_SoundIndex(const char *name)
Definition: game.c:63
PF_FindIndex
static int PF_FindIndex(const char *name, int start, int max)
Definition: game.c:32
level
level_locals_t level
Definition: g_main.c:22
SV_ShutdownGameProgs
void SV_ShutdownGameProgs(void)
Definition: game.c:786
cs_primed
@ cs_primed
Definition: server.h:191
PF_Unicast
static void PF_Unicast(edict_t *ent, qboolean reliable)
Definition: game.c:81
server_t::state
server_state_t state
Definition: server.h:146
Z_FreeTags
void Z_FreeTags(memtag_t tag)
Definition: zone.c:257
MSG_WriteChar
void MSG_WriteChar(int c)
Definition: msg.c:89
client_s::msg_unreliable_bytes
size_t msg_unreliable_bytes
Definition: server.h:336
msg
const char * msg
Definition: win.h:25
client_s::msg_unreliable_list
list_t msg_unreliable_list
Definition: server.h:333
SV_MvdConfigstring
void SV_MvdConfigstring(int index, const char *string, size_t len)
Definition: mvd.c:1226
client_s
Definition: server.h:256
svc_layout
#define svc_layout
Definition: g_local.h:39
color
static vec4_t color
Definition: mesh.c:33
PF_TagMalloc
static void * PF_TagMalloc(size_t size, unsigned tag)
Definition: game.c:748
Q_concat
size_t Q_concat(char *dest, size_t size,...)
Definition: shared.c:758
SV_LoadGameLibrary
static void * SV_LoadGameLibrary(const char *game, const char *prefix)
Definition: game.c:812
Sys_FreeLibrary
void Sys_FreeLibrary(void *handle)
Definition: system.c:787
PF_cprintf
static void PF_cprintf(edict_t *ent, int level, const char *fmt,...)
Definition: game.c:211
server_t::configstrings
char configstrings[MAX_CONFIGSTRINGS][MAX_QPATH]
Definition: server.h:164
SV_EdictIsVisible
qboolean SV_EdictIsVisible(cm_t *cm, edict_t *ent, byte *mask)
Definition: world.c:129
SV_Trace
trace_t q_gameabi SV_Trace(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passedict, int contentmask)
Definition: world.c:546
PF_StartSound
static void PF_StartSound(edict_t *edict, int channel, int soundindex, float volume, float attenuation, float timeofs)
Definition: game.c:511
MSG_WriteDir
void MSG_WriteDir(const vec3_t dir)
Definition: msg.c:460
MSG_WriteAngle
void MSG_WriteAngle(float f)
Definition: msg.c:214
CM_SetAreaPortalState
void CM_SetAreaPortalState(cm_t *cm, int portalnum, qboolean open)
Definition: cmodel.c:869
PF_configstring
static void PF_configstring(int index, const char *val)
Definition: game.c:356
client_s::pmp
pmoveParams_t pmp
Definition: server.h:328
SZ_Clear
void SZ_Clear(sizebuf_t *buf)
Definition: sizebuf.c:40
PF_AreasConnected
static qboolean PF_AreasConnected(int area1, int area2)
Definition: game.c:740
game_library
static void * game_library
Definition: game.c:776
PF_FreeTags
static void PF_FreeTags(unsigned tag)
Definition: game.c:759
SV_MvdBroadcastPrint
void SV_MvdBroadcastPrint(int level, const char *string)
Definition: mvd.c:1241
client_s::name
char name[MAX_CLIENT_NAME]
Definition: server.h:276
client_s::edict
edict_t * edict
Definition: server.h:261
sv_maxclients
cvar_t * sv_maxclients
Definition: main.c:58
Cmd_RawArgs
char * Cmd_RawArgs(void)
Definition: cmd.c:951