|
|
1.1 ! root 1: ! 2: #include "server.h" ! 3: ! 4: /* ! 5: ============================================================================= ! 6: ! 7: Encode a client frame onto the network channel ! 8: ! 9: ============================================================================= ! 10: */ ! 11: ! 12: ! 13: /* ! 14: ============= ! 15: SV_EmitPacketEntities ! 16: ! 17: Writes a delta update of an entity_state_t list to the message. ! 18: ============= ! 19: */ ! 20: void SV_EmitPacketEntities (client_frame_t *from, client_frame_t *to, sizebuf_t *msg) ! 21: { ! 22: entity_state_t *oldent, *newent; ! 23: int oldindex, newindex; ! 24: int oldnum, newnum; ! 25: int from_num_entities; ! 26: int bits; ! 27: ! 28: MSG_WriteByte (msg, svc_packetentities); ! 29: ! 30: if (!from) ! 31: from_num_entities = 0; ! 32: else ! 33: from_num_entities = from->num_entities; ! 34: ! 35: newindex = 0; ! 36: oldindex = 0; ! 37: while (newindex < to->num_entities || oldindex < from_num_entities) ! 38: { ! 39: if (newindex >= to->num_entities) ! 40: newnum = 9999; ! 41: else ! 42: { ! 43: newent = &svs.client_entities[(to->first_entity+newindex)%svs.num_client_entities]; ! 44: newnum = newent->number; ! 45: } ! 46: ! 47: if (oldindex >= from_num_entities) ! 48: oldnum = 9999; ! 49: else ! 50: { ! 51: oldent = &svs.client_entities[(from->first_entity+oldindex)%svs.num_client_entities]; ! 52: oldnum = oldent->number; ! 53: } ! 54: ! 55: if (newnum == oldnum) ! 56: { // delta update from old position ! 57: // because the force parm is false, this will not result ! 58: // in any bytes being emited if the entity has not changed at all ! 59: MSG_WriteDeltaEntity (oldent, newent, msg, false); ! 60: oldindex++; ! 61: newindex++; ! 62: continue; ! 63: } ! 64: ! 65: if (newnum < oldnum) ! 66: { // this is a new entity, send it from the baseline ! 67: MSG_WriteDeltaEntity (&sv.baselines[newnum], newent, msg, true); ! 68: newindex++; ! 69: continue; ! 70: } ! 71: ! 72: if (newnum > oldnum) ! 73: { // the old entity isn't present in the new message ! 74: bits = U_REMOVE; ! 75: if (oldnum >= 256) ! 76: bits |= U_NUMBER16 | U_MOREBITS1; ! 77: ! 78: MSG_WriteByte (msg, bits&255 ); ! 79: if (bits & 0x0000ff00) ! 80: MSG_WriteByte (msg, (bits>>8)&255 ); ! 81: ! 82: if (bits & U_NUMBER16) ! 83: MSG_WriteShort (msg, oldnum); ! 84: else ! 85: MSG_WriteByte (msg, oldnum); ! 86: ! 87: oldindex++; ! 88: continue; ! 89: } ! 90: } ! 91: ! 92: MSG_WriteShort (msg, 0); // end of packetentities ! 93: } ! 94: ! 95: ! 96: ! 97: /* ! 98: ============= ! 99: SV_WritePlayerstateToClient ! 100: ! 101: ============= ! 102: */ ! 103: void SV_WritePlayerstateToClient (client_frame_t *from, client_frame_t *to, sizebuf_t *msg) ! 104: { ! 105: int i; ! 106: int pflags; ! 107: player_state_t *ps, *ops; ! 108: player_state_t dummy; ! 109: int statbits; ! 110: ! 111: ps = &to->ps; ! 112: if (!from) ! 113: { ! 114: memset (&dummy, 0, sizeof(dummy)); ! 115: ops = &dummy; ! 116: } ! 117: else ! 118: ops = &from->ps; ! 119: ! 120: // ! 121: // determine what needs to be sent ! 122: // ! 123: pflags = 0; ! 124: ! 125: if (ps->pmove.pm_type != ops->pmove.pm_type) ! 126: pflags |= PS_M_TYPE; ! 127: ! 128: if (ps->pmove.origin[0] != ops->pmove.origin[0] ! 129: || ps->pmove.origin[1] != ops->pmove.origin[1] ! 130: || ps->pmove.origin[2] != ops->pmove.origin[2] ) ! 131: pflags |= PS_M_ORIGIN; ! 132: ! 133: if (ps->pmove.velocity[0] != ops->pmove.velocity[0] ! 134: || ps->pmove.velocity[1] != ops->pmove.velocity[1] ! 135: || ps->pmove.velocity[2] != ops->pmove.velocity[2] ) ! 136: pflags |= PS_M_VELOCITY; ! 137: ! 138: if (ps->pmove.pm_time != ops->pmove.pm_time) ! 139: pflags |= PS_M_TIME; ! 140: ! 141: if (ps->pmove.pm_flags != ops->pmove.pm_flags) ! 142: pflags |= PS_M_FLAGS; ! 143: ! 144: if (ps->pmove.gravity != ops->pmove.gravity) ! 145: pflags |= PS_M_GRAVITY; ! 146: ! 147: if (ps->pmove.delta_angles[0] != ops->pmove.delta_angles[0] ! 148: || ps->pmove.delta_angles[1] != ops->pmove.delta_angles[1] ! 149: || ps->pmove.delta_angles[2] != ops->pmove.delta_angles[2] ) ! 150: pflags |= PS_M_DELTA_ANGLES; ! 151: ! 152: ! 153: if (ps->viewoffset[0] != ops->viewoffset[0] ! 154: || ps->viewoffset[1] != ops->viewoffset[1] ! 155: || ps->viewoffset[2] != ops->viewoffset[2] ) ! 156: pflags |= PS_VIEWOFFSET; ! 157: ! 158: if (ps->viewangles[0] != ops->viewangles[0] ! 159: || ps->viewangles[1] != ops->viewangles[1] ! 160: || ps->viewangles[2] != ops->viewangles[2] ) ! 161: pflags |= PS_VIEWANGLES; ! 162: ! 163: if (ps->kick_angles[0] != ops->kick_angles[0] ! 164: || ps->kick_angles[1] != ops->kick_angles[1] ! 165: || ps->kick_angles[2] != ops->kick_angles[2] ) ! 166: pflags |= PS_KICKANGLES; ! 167: ! 168: if (ps->blend[0] != ops->blend[0] ! 169: || ps->blend[1] != ops->blend[1] ! 170: || ps->blend[2] != ops->blend[2] ! 171: || ps->blend[3] != ops->blend[3] ) ! 172: pflags |= PS_BLEND; ! 173: ! 174: if (ps->fov != ops->fov) ! 175: pflags |= PS_FOV; ! 176: ! 177: if (ps->rdflags != ops->rdflags) ! 178: pflags |= PS_RDFLAGS; ! 179: ! 180: if (ps->gunframe != ops->gunframe) ! 181: pflags |= PS_WEAPONFRAME; ! 182: ! 183: pflags |= PS_WEAPONINDEX; ! 184: ! 185: // ! 186: // write it ! 187: // ! 188: MSG_WriteByte (msg, svc_playerinfo); ! 189: MSG_WriteShort (msg, pflags); ! 190: ! 191: // ! 192: // write the pmove_state_t ! 193: // ! 194: if (pflags & PS_M_TYPE) ! 195: MSG_WriteByte (msg, ps->pmove.pm_type); ! 196: ! 197: if (pflags & PS_M_ORIGIN) ! 198: { ! 199: MSG_WriteShort (msg, ps->pmove.origin[0]); ! 200: MSG_WriteShort (msg, ps->pmove.origin[1]); ! 201: MSG_WriteShort (msg, ps->pmove.origin[2]); ! 202: } ! 203: ! 204: if (pflags & PS_M_VELOCITY) ! 205: { ! 206: MSG_WriteShort (msg, ps->pmove.velocity[0]); ! 207: MSG_WriteShort (msg, ps->pmove.velocity[1]); ! 208: MSG_WriteShort (msg, ps->pmove.velocity[2]); ! 209: } ! 210: ! 211: if (pflags & PS_M_TIME) ! 212: MSG_WriteByte (msg, ps->pmove.pm_time); ! 213: ! 214: if (pflags & PS_M_FLAGS) ! 215: MSG_WriteByte (msg, ps->pmove.pm_flags); ! 216: ! 217: if (pflags & PS_M_GRAVITY) ! 218: MSG_WriteShort (msg, ps->pmove.gravity); ! 219: ! 220: if (pflags & PS_M_DELTA_ANGLES) ! 221: { ! 222: MSG_WriteShort (msg, ps->pmove.delta_angles[0]); ! 223: MSG_WriteShort (msg, ps->pmove.delta_angles[1]); ! 224: MSG_WriteShort (msg, ps->pmove.delta_angles[2]); ! 225: } ! 226: ! 227: // ! 228: // write the rest of the player_state_t ! 229: // ! 230: if (pflags & PS_VIEWOFFSET) ! 231: { ! 232: MSG_WriteChar (msg, ps->viewoffset[0]*4); ! 233: MSG_WriteChar (msg, ps->viewoffset[1]*4); ! 234: MSG_WriteChar (msg, ps->viewoffset[2]*4); ! 235: } ! 236: ! 237: if (pflags & PS_VIEWANGLES) ! 238: { ! 239: MSG_WriteAngle16 (msg, ps->viewangles[0]); ! 240: MSG_WriteAngle16 (msg, ps->viewangles[1]); ! 241: MSG_WriteAngle16 (msg, ps->viewangles[2]); ! 242: } ! 243: ! 244: if (pflags & PS_KICKANGLES) ! 245: { ! 246: MSG_WriteChar (msg, ps->kick_angles[0]*4); ! 247: MSG_WriteChar (msg, ps->kick_angles[1]*4); ! 248: MSG_WriteChar (msg, ps->kick_angles[2]*4); ! 249: } ! 250: ! 251: if (pflags & PS_WEAPONINDEX) ! 252: { ! 253: MSG_WriteByte (msg, ps->gunindex); ! 254: } ! 255: ! 256: if (pflags & PS_WEAPONFRAME) ! 257: { ! 258: MSG_WriteByte (msg, ps->gunframe); ! 259: MSG_WriteChar (msg, ps->gunoffset[0]*4); ! 260: MSG_WriteChar (msg, ps->gunoffset[1]*4); ! 261: MSG_WriteChar (msg, ps->gunoffset[2]*4); ! 262: MSG_WriteChar (msg, ps->gunangles[0]*4); ! 263: MSG_WriteChar (msg, ps->gunangles[1]*4); ! 264: MSG_WriteChar (msg, ps->gunangles[2]*4); ! 265: } ! 266: ! 267: if (pflags & PS_BLEND) ! 268: { ! 269: MSG_WriteByte (msg, ps->blend[0]*255); ! 270: MSG_WriteByte (msg, ps->blend[1]*255); ! 271: MSG_WriteByte (msg, ps->blend[2]*255); ! 272: MSG_WriteByte (msg, ps->blend[3]*255); ! 273: } ! 274: if (pflags & PS_FOV) ! 275: MSG_WriteByte (msg, ps->fov); ! 276: if (pflags & PS_RDFLAGS) ! 277: MSG_WriteByte (msg, ps->rdflags); ! 278: ! 279: // send stats ! 280: statbits = 0; ! 281: for (i=0 ; i<MAX_STATS ; i++) ! 282: if (ps->stats[i] != ops->stats[i]) ! 283: statbits |= 1<<i; ! 284: MSG_WriteLong (msg, statbits); ! 285: for (i=0 ; i<MAX_STATS ; i++) ! 286: if (statbits & (1<<i) ) ! 287: MSG_WriteShort (msg, ps->stats[i]); ! 288: } ! 289: ! 290: ! 291: /* ! 292: ================== ! 293: SV_WriteFrameToClient ! 294: ================== ! 295: */ ! 296: void SV_WriteFrameToClient (client_t *client, sizebuf_t *msg) ! 297: { ! 298: client_frame_t *frame, *oldframe; ! 299: int lastframe; ! 300: ! 301: //Com_Printf ("%i -> %i\n", client->lastframe, sv.framenum); ! 302: // this is the frame we are creating ! 303: frame = &client->frames[sv.framenum & UPDATE_MASK]; ! 304: ! 305: if (client->lastframe <= 0) ! 306: { // client is asking for a retransmit ! 307: oldframe = NULL; ! 308: lastframe = -1; ! 309: } ! 310: else if (sv.framenum - client->lastframe >= (UPDATE_BACKUP - 3) ) ! 311: { // client hasn't gotten a good message through in a long time ! 312: // Com_Printf ("%s: Delta request from out-of-date packet.\n", client->name); ! 313: oldframe = NULL; ! 314: lastframe = -1; ! 315: } ! 316: else ! 317: { // we have a valid message to delta from ! 318: oldframe = &client->frames[client->lastframe & UPDATE_MASK]; ! 319: lastframe = client->lastframe; ! 320: } ! 321: ! 322: MSG_WriteByte (msg, svc_frame); ! 323: MSG_WriteLong (msg, sv.framenum); ! 324: MSG_WriteLong (msg, lastframe); // what we are delta'ing from ! 325: MSG_WriteByte (msg, client->surpressCount); // rate dropped packets ! 326: client->surpressCount = 0; ! 327: ! 328: // send over the areabits ! 329: MSG_WriteByte (msg, frame->areabytes); ! 330: SZ_Write (msg, frame->areabits, frame->areabytes); ! 331: ! 332: // delta encode the playerstate ! 333: SV_WritePlayerstateToClient (oldframe, frame, msg); ! 334: ! 335: // delta encode the entities ! 336: SV_EmitPacketEntities (oldframe, frame, msg); ! 337: } ! 338: ! 339: ! 340: /* ! 341: ============================================================================= ! 342: ! 343: Build a client frame structure ! 344: ! 345: ============================================================================= ! 346: */ ! 347: ! 348: byte fatpvs[65536/8]; // 32767 is MAX_MAP_LEAFS ! 349: ! 350: /* ! 351: ============ ! 352: SV_FatPVS ! 353: ! 354: The client will interpolate the view position, ! 355: so we can't use a single PVS point ! 356: =========== ! 357: */ ! 358: void SV_FatPVS (vec3_t org) ! 359: { ! 360: int leafs[64]; ! 361: int i, j, count; ! 362: int longs; ! 363: byte *src; ! 364: vec3_t mins, maxs; ! 365: ! 366: for (i=0 ; i<3 ; i++) ! 367: { ! 368: mins[i] = org[i] - 8; ! 369: maxs[i] = org[i] + 8; ! 370: } ! 371: ! 372: count = CM_BoxLeafnums (mins, maxs, leafs, 64, NULL); ! 373: if (count < 1) ! 374: Com_Error (ERR_FATAL, "SV_FatPVS: count < 1"); ! 375: longs = (CM_NumClusters()+31)>>5; ! 376: ! 377: // convert leafs to clusters ! 378: for (i=0 ; i<count ; i++) ! 379: leafs[i] = CM_LeafCluster(leafs[i]); ! 380: ! 381: memcpy (fatpvs, CM_ClusterPVS(leafs[0]), longs<<2); ! 382: // or in all the other leaf bits ! 383: for (i=1 ; i<count ; i++) ! 384: { ! 385: for (j=0 ; j<i ; j++) ! 386: if (leafs[i] == leafs[j]) ! 387: break; ! 388: if (j != i) ! 389: continue; // already have the cluster we want ! 390: src = CM_ClusterPVS(leafs[i]); ! 391: for (j=0 ; j<longs ; j++) ! 392: ((long *)fatpvs)[j] |= ((long *)src)[j]; ! 393: } ! 394: } ! 395: ! 396: ! 397: /* ! 398: ============= ! 399: SV_BuildClientFrame ! 400: ! 401: Decides which entities are going to be visible to the client, and ! 402: copies off the playerstat and areabits. ! 403: ============= ! 404: */ ! 405: void SV_BuildClientFrame (client_t *client) ! 406: { ! 407: int e, i; ! 408: vec3_t org; ! 409: edict_t *ent; ! 410: edict_t *clent; ! 411: client_frame_t *frame; ! 412: entity_state_t *state; ! 413: int l; ! 414: int clientarea, clientcluster; ! 415: int leafnum; ! 416: int c_fullsend; ! 417: byte *clientphs; ! 418: byte *bitvector; ! 419: ! 420: clent = client->edict; ! 421: if (!clent->client) ! 422: return; // not in game yet ! 423: ! 424: // this is the frame we are creating ! 425: frame = &client->frames[sv.framenum & UPDATE_MASK]; ! 426: ! 427: // find the client's PVS ! 428: for (i=0 ; i<3 ; i++) ! 429: org[i] = clent->client->ps.pmove.origin[i]*0.125 + clent->client->ps.viewoffset[i]; ! 430: ! 431: leafnum = CM_PointLeafnum (org); ! 432: clientarea = CM_LeafArea (leafnum); ! 433: clientcluster = CM_LeafCluster (leafnum); ! 434: ! 435: // calculate the visible areas ! 436: frame->areabytes = CM_WriteAreaBits (frame->areabits, clientarea); ! 437: ! 438: // grab the current player_state_t ! 439: frame->ps = clent->client->ps; ! 440: ! 441: ! 442: SV_FatPVS (org); ! 443: clientphs = CM_ClusterPHS (clientcluster); ! 444: ! 445: // build up the list of visible entities ! 446: frame->num_entities = 0; ! 447: frame->first_entity = svs.next_client_entities; ! 448: ! 449: c_fullsend = 0; ! 450: ! 451: for (e=1 ; e<ge->num_edicts ; e++) ! 452: { ! 453: ent = EDICT_NUM(e); ! 454: ! 455: // ignore ents without visible models ! 456: if (ent->svflags & SVF_NOCLIENT) ! 457: continue; ! 458: ! 459: // ignore ents without visible models unless they have an effect ! 460: if (!ent->s.modelindex && !ent->s.effects && !ent->s.sound ! 461: && !ent->s.event) ! 462: continue; ! 463: ! 464: // ignore if not touching a PV leaf ! 465: if (ent != clent) ! 466: { ! 467: // check area ! 468: if (!CM_AreasConnected (clientarea, ent->areanum)) ! 469: { // doors can legally straddle two areas, so ! 470: // we may need to check another one ! 471: if (!ent->areanum2 ! 472: || !CM_AreasConnected (clientarea, ent->areanum2)) ! 473: continue; // blocked by a door ! 474: } ! 475: ! 476: // beams just check one point for PHS ! 477: if (ent->s.renderfx & RF_BEAM) ! 478: { ! 479: l = ent->clusternums[0]; ! 480: if ( !(clientphs[l >> 3] & (1 << (l&7) )) ) ! 481: continue; ! 482: } ! 483: else ! 484: { ! 485: // FIXME: if an ent has a model and a sound, but isn't ! 486: // in the PVS, only the PHS, clear the model ! 487: if (ent->s.sound) ! 488: { ! 489: bitvector = fatpvs; //clientphs; ! 490: } ! 491: else ! 492: bitvector = fatpvs; ! 493: ! 494: if (ent->num_clusters == -1) ! 495: { // too many leafs for individual check, go by headnode ! 496: if (!CM_HeadnodeVisible (ent->headnode, bitvector)) ! 497: continue; ! 498: c_fullsend++; ! 499: } ! 500: else ! 501: { // check individual leafs ! 502: for (i=0 ; i < ent->num_clusters ; i++) ! 503: { ! 504: l = ent->clusternums[i]; ! 505: if (bitvector[l >> 3] & (1 << (l&7) )) ! 506: break; ! 507: } ! 508: if (i == ent->num_clusters) ! 509: continue; // not visible ! 510: } ! 511: ! 512: if (!ent->s.modelindex) ! 513: { // don't send sounds if they will be attenuated away ! 514: vec3_t delta; ! 515: float len; ! 516: ! 517: VectorSubtract (org, ent->s.origin, delta); ! 518: len = VectorLength (delta); ! 519: if (len > 400) ! 520: continue; ! 521: } ! 522: } ! 523: } ! 524: ! 525: // add it to the circular client_entities array ! 526: state = &svs.client_entities[svs.next_client_entities%svs.num_client_entities]; ! 527: if (ent->s.number != e) ! 528: { ! 529: Com_DPrintf ("FIXING ENT->S.NUMBER!!!\n"); ! 530: ent->s.number = e; ! 531: } ! 532: *state = ent->s; ! 533: ! 534: // don't mark players missiles as solid ! 535: if (ent->owner == client->edict) ! 536: state->solid = 0; ! 537: ! 538: svs.next_client_entities++; ! 539: frame->num_entities++; ! 540: } ! 541: } ! 542: ! 543: ! 544: /* ! 545: ================== ! 546: SV_RecordDemoMessage ! 547: ! 548: Save everything in the world out without deltas. ! 549: Used for recording footage for merged or assembled demos ! 550: ================== ! 551: */ ! 552: void SV_RecordDemoMessage (void) ! 553: { ! 554: int e; ! 555: edict_t *ent; ! 556: entity_state_t nostate; ! 557: sizebuf_t buf; ! 558: byte buf_data[32768]; ! 559: int len; ! 560: ! 561: if (!svs.demofile) ! 562: return; ! 563: ! 564: memset (&nostate, 0, sizeof(nostate)); ! 565: SZ_Init (&buf, buf_data, sizeof(buf_data)); ! 566: ! 567: // write a frame message that doesn't contain a player_state_t ! 568: MSG_WriteByte (&buf, svc_frame); ! 569: MSG_WriteLong (&buf, sv.framenum); ! 570: ! 571: MSG_WriteByte (&buf, svc_packetentities); ! 572: ! 573: for (e=1, ent=EDICT_NUM(e) ; e<ge->num_edicts ; e++, ent++) ! 574: { ! 575: // invisible trigger ! 576: if (ent->svflags & SVF_NOCLIENT) ! 577: continue; ! 578: ! 579: // ignore ents without visible models unless they have an effect ! 580: if (!ent->s.modelindex && !ent->s.effects && !ent->s.sound ! 581: && !ent->s.event) ! 582: continue; ! 583: ! 584: MSG_WriteDeltaEntity (&nostate, &ent->s, &buf, false); ! 585: } ! 586: ! 587: MSG_WriteShort (&buf, 0); // end of packetentities ! 588: ! 589: // now add the accumulated multicast information ! 590: SZ_Write (&buf, svs.demo_multicast.data, svs.demo_multicast.cursize); ! 591: SZ_Clear (&svs.demo_multicast); ! 592: ! 593: // now write the entire message to the file, prefixed by the length ! 594: len = LittleLong (buf.cursize); ! 595: fwrite (&len, 4, 1, svs.demofile); ! 596: fwrite (buf.data, buf.cursize, 1, svs.demofile); ! 597: } ! 598:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.