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