sv_game.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // sv_game.c -- interface to the game dll
  16. #include "server.h"
  17. game_export_t *ge;
  18. /*
  19. ===============
  20. PF_Unicast
  21. Sends the contents of the mutlicast buffer to a single client
  22. ===============
  23. */
  24. void PF_Unicast (edict_t *ent, qboolean reliable)
  25. {
  26. int p;
  27. client_t *client;
  28. if (!ent)
  29. return;
  30. p = NUM_FOR_EDICT(ent);
  31. if (p < 1 || p > maxclients->value)
  32. return;
  33. client = svs.clients + (p-1);
  34. if (reliable)
  35. SZ_Write (&client->netchan.message, sv.multicast.data, sv.multicast.cursize);
  36. else
  37. SZ_Write (&client->datagram, sv.multicast.data, sv.multicast.cursize);
  38. SZ_Clear (&sv.multicast);
  39. }
  40. /*
  41. ===============
  42. PF_dprintf
  43. Debug print to server console
  44. ===============
  45. */
  46. void PF_dprintf (char *fmt, ...)
  47. {
  48. char msg[1024];
  49. va_list argptr;
  50. va_start (argptr,fmt);
  51. vsprintf (msg, fmt, argptr);
  52. va_end (argptr);
  53. Com_Printf ("%s", msg);
  54. }
  55. /*
  56. ===============
  57. PF_cprintf
  58. Print to a single client
  59. ===============
  60. */
  61. void PF_cprintf (edict_t *ent, int level, char *fmt, ...)
  62. {
  63. char msg[1024];
  64. va_list argptr;
  65. int n;
  66. if (ent)
  67. {
  68. n = NUM_FOR_EDICT(ent);
  69. if (n < 1 || n > maxclients->value)
  70. Com_Error (ERR_DROP, "cprintf to a non-client");
  71. }
  72. va_start (argptr,fmt);
  73. vsprintf (msg, fmt, argptr);
  74. va_end (argptr);
  75. if (ent)
  76. SV_ClientPrintf (svs.clients+(n-1), level, "%s", msg);
  77. else
  78. Com_Printf ("%s", msg);
  79. }
  80. /*
  81. ===============
  82. PF_centerprintf
  83. centerprint to a single client
  84. ===============
  85. */
  86. void PF_centerprintf (edict_t *ent, char *fmt, ...)
  87. {
  88. char msg[1024];
  89. va_list argptr;
  90. int n;
  91. n = NUM_FOR_EDICT(ent);
  92. if (n < 1 || n > maxclients->value)
  93. return; // Com_Error (ERR_DROP, "centerprintf to a non-client");
  94. va_start (argptr,fmt);
  95. vsprintf (msg, fmt, argptr);
  96. va_end (argptr);
  97. MSG_WriteByte (&sv.multicast,svc_centerprint);
  98. MSG_WriteString (&sv.multicast,msg);
  99. PF_Unicast (ent, true);
  100. }
  101. /*
  102. ===============
  103. PF_error
  104. Abort the server with a game error
  105. ===============
  106. */
  107. void PF_error (char *fmt, ...)
  108. {
  109. char msg[1024];
  110. va_list argptr;
  111. va_start (argptr,fmt);
  112. vsprintf (msg, fmt, argptr);
  113. va_end (argptr);
  114. Com_Error (ERR_DROP, "Game Error: %s", msg);
  115. }
  116. /*
  117. =================
  118. PF_setmodel
  119. Also sets mins and maxs for inline bmodels
  120. =================
  121. */
  122. void PF_setmodel (edict_t *ent, char *name)
  123. {
  124. int i;
  125. cmodel_t *mod;
  126. if (!name)
  127. Com_Error (ERR_DROP, "PF_setmodel: NULL");
  128. i = SV_ModelIndex (name);
  129. // ent->model = name;
  130. ent->s.modelindex = i;
  131. // if it is an inline model, get the size information for it
  132. if (name[0] == '*')
  133. {
  134. mod = CM_InlineModel (name);
  135. VectorCopy (mod->mins, ent->mins);
  136. VectorCopy (mod->maxs, ent->maxs);
  137. SV_LinkEdict (ent);
  138. }
  139. }
  140. /*
  141. ===============
  142. PF_Configstring
  143. ===============
  144. */
  145. void PF_Configstring (int index, char *val)
  146. {
  147. if (index < 0 || index >= MAX_CONFIGSTRINGS)
  148. Com_Error (ERR_DROP, "configstring: bad index %i\n", index);
  149. if (!val)
  150. val = "";
  151. // change the string in sv
  152. strcpy (sv.configstrings[index], val);
  153. if (sv.state != ss_loading)
  154. { // send the update to everyone
  155. SZ_Clear (&sv.multicast);
  156. MSG_WriteChar (&sv.multicast, svc_configstring);
  157. MSG_WriteShort (&sv.multicast, index);
  158. MSG_WriteString (&sv.multicast, val);
  159. SV_Multicast (vec3_origin, MULTICAST_ALL_R);
  160. }
  161. }
  162. void PF_WriteChar (int c) {MSG_WriteChar (&sv.multicast, c);}
  163. void PF_WriteByte (int c) {MSG_WriteByte (&sv.multicast, c);}
  164. void PF_WriteShort (int c) {MSG_WriteShort (&sv.multicast, c);}
  165. void PF_WriteLong (int c) {MSG_WriteLong (&sv.multicast, c);}
  166. void PF_WriteFloat (float f) {MSG_WriteFloat (&sv.multicast, f);}
  167. void PF_WriteString (char *s) {MSG_WriteString (&sv.multicast, s);}
  168. void PF_WritePos (vec3_t pos) {MSG_WritePos (&sv.multicast, pos);}
  169. void PF_WriteDir (vec3_t dir) {MSG_WriteDir (&sv.multicast, dir);}
  170. void PF_WriteAngle (float f) {MSG_WriteAngle (&sv.multicast, f);}
  171. /*
  172. =================
  173. PF_inPVS
  174. Also checks portalareas so that doors block sight
  175. =================
  176. */
  177. qboolean PF_inPVS (vec3_t p1, vec3_t p2)
  178. {
  179. int leafnum;
  180. int cluster;
  181. int area1, area2;
  182. byte *mask;
  183. leafnum = CM_PointLeafnum (p1);
  184. cluster = CM_LeafCluster (leafnum);
  185. area1 = CM_LeafArea (leafnum);
  186. mask = CM_ClusterPVS (cluster);
  187. leafnum = CM_PointLeafnum (p2);
  188. cluster = CM_LeafCluster (leafnum);
  189. area2 = CM_LeafArea (leafnum);
  190. if ( mask && (!(mask[cluster>>3] & (1<<(cluster&7)) ) ) )
  191. return false;
  192. if (!CM_AreasConnected (area1, area2))
  193. return false; // a door blocks sight
  194. return true;
  195. }
  196. /*
  197. =================
  198. PF_inPHS
  199. Also checks portalareas so that doors block sound
  200. =================
  201. */
  202. qboolean PF_inPHS (vec3_t p1, vec3_t p2)
  203. {
  204. int leafnum;
  205. int cluster;
  206. int area1, area2;
  207. byte *mask;
  208. leafnum = CM_PointLeafnum (p1);
  209. cluster = CM_LeafCluster (leafnum);
  210. area1 = CM_LeafArea (leafnum);
  211. mask = CM_ClusterPHS (cluster);
  212. leafnum = CM_PointLeafnum (p2);
  213. cluster = CM_LeafCluster (leafnum);
  214. area2 = CM_LeafArea (leafnum);
  215. if ( mask && (!(mask[cluster>>3] & (1<<(cluster&7)) ) ) )
  216. return false; // more than one bounce away
  217. if (!CM_AreasConnected (area1, area2))
  218. return false; // a door blocks hearing
  219. return true;
  220. }
  221. void PF_StartSound (edict_t *entity, int channel, int sound_num, float volume,
  222. float attenuation, float timeofs)
  223. {
  224. if (!entity)
  225. return;
  226. SV_StartSound (NULL, entity, channel, sound_num, volume, attenuation, timeofs);
  227. }
  228. //==============================================
  229. /*
  230. ===============
  231. SV_ShutdownGameProgs
  232. Called when either the entire server is being killed, or
  233. it is changing to a different game directory.
  234. ===============
  235. */
  236. void SV_ShutdownGameProgs (void)
  237. {
  238. if (!ge)
  239. return;
  240. ge->Shutdown ();
  241. Sys_UnloadGame ();
  242. ge = NULL;
  243. }
  244. /*
  245. ===============
  246. SV_InitGameProgs
  247. Init the game subsystem for a new map
  248. ===============
  249. */
  250. void SCR_DebugGraph (float value, int color);
  251. void SV_InitGameProgs (void)
  252. {
  253. game_import_t import;
  254. // unload anything we have now
  255. if (ge)
  256. SV_ShutdownGameProgs ();
  257. // load a new game dll
  258. import.multicast = SV_Multicast;
  259. import.unicast = PF_Unicast;
  260. import.bprintf = SV_BroadcastPrintf;
  261. import.dprintf = PF_dprintf;
  262. import.cprintf = PF_cprintf;
  263. import.centerprintf = PF_centerprintf;
  264. import.error = PF_error;
  265. import.linkentity = SV_LinkEdict;
  266. import.unlinkentity = SV_UnlinkEdict;
  267. import.BoxEdicts = SV_AreaEdicts;
  268. import.trace = SV_Trace;
  269. import.pointcontents = SV_PointContents;
  270. import.setmodel = PF_setmodel;
  271. import.inPVS = PF_inPVS;
  272. import.inPHS = PF_inPHS;
  273. import.Pmove = Pmove;
  274. import.modelindex = SV_ModelIndex;
  275. import.soundindex = SV_SoundIndex;
  276. import.imageindex = SV_ImageIndex;
  277. import.configstring = PF_Configstring;
  278. import.sound = PF_StartSound;
  279. import.positioned_sound = SV_StartSound;
  280. import.WriteChar = PF_WriteChar;
  281. import.WriteByte = PF_WriteByte;
  282. import.WriteShort = PF_WriteShort;
  283. import.WriteLong = PF_WriteLong;
  284. import.WriteFloat = PF_WriteFloat;
  285. import.WriteString = PF_WriteString;
  286. import.WritePosition = PF_WritePos;
  287. import.WriteDir = PF_WriteDir;
  288. import.WriteAngle = PF_WriteAngle;
  289. import.TagMalloc = Z_TagMalloc;
  290. import.TagFree = Z_Free;
  291. import.FreeTags = Z_FreeTags;
  292. import.cvar = Cvar_Get;
  293. import.cvar_set = Cvar_Set;
  294. import.cvar_forceset = Cvar_ForceSet;
  295. import.argc = Cmd_Argc;
  296. import.argv = Cmd_Argv;
  297. import.args = Cmd_Args;
  298. import.AddCommandString = Cbuf_AddText;
  299. import.DebugGraph = SCR_DebugGraph;
  300. import.SetAreaPortalState = CM_SetAreaPortalState;
  301. import.AreasConnected = CM_AreasConnected;
  302. ge = (game_export_t *)Sys_GetGameAPI (&import);
  303. if (!ge)
  304. Com_Error (ERR_DROP, "failed to load game DLL");
  305. if (ge->apiversion != GAME_API_VERSION)
  306. Com_Error (ERR_DROP, "game is version %i, not %i", ge->apiversion,
  307. GAME_API_VERSION);
  308. ge->Init ();
  309. }