123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- /*
- Copyright (C) 1997-2001 Id Software, Inc.
- 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 the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- // sv_game.c -- interface to the game dll
- #include "server.h"
- game_export_t *ge;
- /*
- ===============
- PF_Unicast
- Sends the contents of the mutlicast buffer to a single client
- ===============
- */
- void PF_Unicast (edict_t *ent, qboolean reliable)
- {
- int p;
- client_t *client;
- if (!ent)
- return;
- p = NUM_FOR_EDICT(ent);
- if (p < 1 || p > maxclients->value)
- return;
- client = svs.clients + (p-1);
- if (reliable)
- SZ_Write (&client->netchan.message, sv.multicast.data, sv.multicast.cursize);
- else
- SZ_Write (&client->datagram, sv.multicast.data, sv.multicast.cursize);
- SZ_Clear (&sv.multicast);
- }
- /*
- ===============
- PF_dprintf
- Debug print to server console
- ===============
- */
- void PF_dprintf (char *fmt, ...)
- {
- char msg[1024];
- va_list argptr;
-
- va_start (argptr,fmt);
- vsprintf (msg, fmt, argptr);
- va_end (argptr);
- Com_Printf ("%s", msg);
- }
- /*
- ===============
- PF_cprintf
- Print to a single client
- ===============
- */
- void PF_cprintf (edict_t *ent, int level, char *fmt, ...)
- {
- char msg[1024];
- va_list argptr;
- int n;
- if (ent)
- {
- n = NUM_FOR_EDICT(ent);
- if (n < 1 || n > maxclients->value)
- Com_Error (ERR_DROP, "cprintf to a non-client");
- }
- va_start (argptr,fmt);
- vsprintf (msg, fmt, argptr);
- va_end (argptr);
- if (ent)
- SV_ClientPrintf (svs.clients+(n-1), level, "%s", msg);
- else
- Com_Printf ("%s", msg);
- }
- /*
- ===============
- PF_centerprintf
- centerprint to a single client
- ===============
- */
- void PF_centerprintf (edict_t *ent, char *fmt, ...)
- {
- char msg[1024];
- va_list argptr;
- int n;
-
- n = NUM_FOR_EDICT(ent);
- if (n < 1 || n > maxclients->value)
- return; // Com_Error (ERR_DROP, "centerprintf to a non-client");
- va_start (argptr,fmt);
- vsprintf (msg, fmt, argptr);
- va_end (argptr);
- MSG_WriteByte (&sv.multicast,svc_centerprint);
- MSG_WriteString (&sv.multicast,msg);
- PF_Unicast (ent, true);
- }
- /*
- ===============
- PF_error
- Abort the server with a game error
- ===============
- */
- void PF_error (char *fmt, ...)
- {
- char msg[1024];
- va_list argptr;
-
- va_start (argptr,fmt);
- vsprintf (msg, fmt, argptr);
- va_end (argptr);
- Com_Error (ERR_DROP, "Game Error: %s", msg);
- }
- /*
- =================
- PF_setmodel
- Also sets mins and maxs for inline bmodels
- =================
- */
- void PF_setmodel (edict_t *ent, char *name)
- {
- int i;
- cmodel_t *mod;
- if (!name)
- Com_Error (ERR_DROP, "PF_setmodel: NULL");
- i = SV_ModelIndex (name);
-
- // ent->model = name;
- ent->s.modelindex = i;
- // if it is an inline model, get the size information for it
- if (name[0] == '*')
- {
- mod = CM_InlineModel (name);
- VectorCopy (mod->mins, ent->mins);
- VectorCopy (mod->maxs, ent->maxs);
- SV_LinkEdict (ent);
- }
- }
- /*
- ===============
- PF_Configstring
- ===============
- */
- void PF_Configstring (int index, char *val)
- {
- if (index < 0 || index >= MAX_CONFIGSTRINGS)
- Com_Error (ERR_DROP, "configstring: bad index %i\n", index);
- if (!val)
- val = "";
- // change the string in sv
- strcpy (sv.configstrings[index], val);
-
- if (sv.state != ss_loading)
- { // send the update to everyone
- SZ_Clear (&sv.multicast);
- MSG_WriteChar (&sv.multicast, svc_configstring);
- MSG_WriteShort (&sv.multicast, index);
- MSG_WriteString (&sv.multicast, val);
- SV_Multicast (vec3_origin, MULTICAST_ALL_R);
- }
- }
- void PF_WriteChar (int c) {MSG_WriteChar (&sv.multicast, c);}
- void PF_WriteByte (int c) {MSG_WriteByte (&sv.multicast, c);}
- void PF_WriteShort (int c) {MSG_WriteShort (&sv.multicast, c);}
- void PF_WriteLong (int c) {MSG_WriteLong (&sv.multicast, c);}
- void PF_WriteFloat (float f) {MSG_WriteFloat (&sv.multicast, f);}
- void PF_WriteString (char *s) {MSG_WriteString (&sv.multicast, s);}
- void PF_WritePos (vec3_t pos) {MSG_WritePos (&sv.multicast, pos);}
- void PF_WriteDir (vec3_t dir) {MSG_WriteDir (&sv.multicast, dir);}
- void PF_WriteAngle (float f) {MSG_WriteAngle (&sv.multicast, f);}
- /*
- =================
- PF_inPVS
- Also checks portalareas so that doors block sight
- =================
- */
- qboolean PF_inPVS (vec3_t p1, vec3_t p2)
- {
- int leafnum;
- int cluster;
- int area1, area2;
- byte *mask;
- leafnum = CM_PointLeafnum (p1);
- cluster = CM_LeafCluster (leafnum);
- area1 = CM_LeafArea (leafnum);
- mask = CM_ClusterPVS (cluster);
- leafnum = CM_PointLeafnum (p2);
- cluster = CM_LeafCluster (leafnum);
- area2 = CM_LeafArea (leafnum);
- if ( mask && (!(mask[cluster>>3] & (1<<(cluster&7)) ) ) )
- return false;
- if (!CM_AreasConnected (area1, area2))
- return false; // a door blocks sight
- return true;
- }
- /*
- =================
- PF_inPHS
- Also checks portalareas so that doors block sound
- =================
- */
- qboolean PF_inPHS (vec3_t p1, vec3_t p2)
- {
- int leafnum;
- int cluster;
- int area1, area2;
- byte *mask;
- leafnum = CM_PointLeafnum (p1);
- cluster = CM_LeafCluster (leafnum);
- area1 = CM_LeafArea (leafnum);
- mask = CM_ClusterPHS (cluster);
- leafnum = CM_PointLeafnum (p2);
- cluster = CM_LeafCluster (leafnum);
- area2 = CM_LeafArea (leafnum);
- if ( mask && (!(mask[cluster>>3] & (1<<(cluster&7)) ) ) )
- return false; // more than one bounce away
- if (!CM_AreasConnected (area1, area2))
- return false; // a door blocks hearing
- return true;
- }
- void PF_StartSound (edict_t *entity, int channel, int sound_num, float volume,
- float attenuation, float timeofs)
- {
- if (!entity)
- return;
- SV_StartSound (NULL, entity, channel, sound_num, volume, attenuation, timeofs);
- }
- //==============================================
- /*
- ===============
- SV_ShutdownGameProgs
- Called when either the entire server is being killed, or
- it is changing to a different game directory.
- ===============
- */
- void SV_ShutdownGameProgs (void)
- {
- if (!ge)
- return;
- ge->Shutdown ();
- Sys_UnloadGame ();
- ge = NULL;
- }
- /*
- ===============
- SV_InitGameProgs
- Init the game subsystem for a new map
- ===============
- */
- void SCR_DebugGraph (float value, int color);
- void SV_InitGameProgs (void)
- {
- game_import_t import;
- // unload anything we have now
- if (ge)
- SV_ShutdownGameProgs ();
- // load a new game dll
- import.multicast = SV_Multicast;
- import.unicast = PF_Unicast;
- import.bprintf = SV_BroadcastPrintf;
- import.dprintf = PF_dprintf;
- import.cprintf = PF_cprintf;
- import.centerprintf = PF_centerprintf;
- import.error = PF_error;
- import.linkentity = SV_LinkEdict;
- import.unlinkentity = SV_UnlinkEdict;
- import.BoxEdicts = SV_AreaEdicts;
- import.trace = SV_Trace;
- import.pointcontents = SV_PointContents;
- import.setmodel = PF_setmodel;
- import.inPVS = PF_inPVS;
- import.inPHS = PF_inPHS;
- import.Pmove = Pmove;
- import.modelindex = SV_ModelIndex;
- import.soundindex = SV_SoundIndex;
- import.imageindex = SV_ImageIndex;
- import.configstring = PF_Configstring;
- import.sound = PF_StartSound;
- import.positioned_sound = SV_StartSound;
- import.WriteChar = PF_WriteChar;
- import.WriteByte = PF_WriteByte;
- import.WriteShort = PF_WriteShort;
- import.WriteLong = PF_WriteLong;
- import.WriteFloat = PF_WriteFloat;
- import.WriteString = PF_WriteString;
- import.WritePosition = PF_WritePos;
- import.WriteDir = PF_WriteDir;
- import.WriteAngle = PF_WriteAngle;
- import.TagMalloc = Z_TagMalloc;
- import.TagFree = Z_Free;
- import.FreeTags = Z_FreeTags;
- import.cvar = Cvar_Get;
- import.cvar_set = Cvar_Set;
- import.cvar_forceset = Cvar_ForceSet;
- import.argc = Cmd_Argc;
- import.argv = Cmd_Argv;
- import.args = Cmd_Args;
- import.AddCommandString = Cbuf_AddText;
- import.DebugGraph = SCR_DebugGraph;
- import.SetAreaPortalState = CM_SetAreaPortalState;
- import.AreasConnected = CM_AreasConnected;
- ge = (game_export_t *)Sys_GetGameAPI (&import);
- if (!ge)
- Com_Error (ERR_DROP, "failed to load game DLL");
- if (ge->apiversion != GAME_API_VERSION)
- Com_Error (ERR_DROP, "game is version %i, not %i", ge->apiversion,
- GAME_API_VERSION);
- ge->Init ();
- }
|