Annotation of quake2/server/sv_send.c, revision 1.1.1.1

1.1       root        1: // sv_main.c -- server main program
                      2: 
                      3: #include "server.h"
                      4: 
                      5: /*
                      6: =============================================================================
                      7: 
                      8: Com_Printf redirection
                      9: 
                     10: =============================================================================
                     11: */
                     12: 
                     13: char sv_outputbuf[SV_OUTPUTBUF_LENGTH];
                     14: 
                     15: void SV_FlushRedirect (int sv_redirected, char *outputbuf)
                     16: {
                     17:        if (sv_redirected == RD_PACKET)
                     18:        {
                     19:                Netchan_OutOfBandPrint (NS_SERVER, net_from, "print\n%s", outputbuf);
                     20:        }
                     21:        else if (sv_redirected == RD_CLIENT)
                     22:        {
                     23:                MSG_WriteByte (&sv_client->netchan.message, svc_print);
                     24:                MSG_WriteByte (&sv_client->netchan.message, PRINT_HIGH);
                     25:                MSG_WriteString (&sv_client->netchan.message, outputbuf);
                     26:        }
                     27: }
                     28: 
                     29: 
                     30: /*
                     31: =============================================================================
                     32: 
                     33: EVENT MESSAGES
                     34: 
                     35: =============================================================================
                     36: */
                     37: 
                     38: 
                     39: /*
                     40: =================
                     41: SV_ClientPrintf
                     42: 
                     43: Sends text across to be displayed if the level passes
                     44: =================
                     45: */
                     46: void SV_ClientPrintf (client_t *cl, int level, char *fmt, ...)
                     47: {
                     48:        va_list         argptr;
                     49:        char            string[1024];
                     50:        
                     51:        if (level < cl->messagelevel)
                     52:                return;
                     53:        
                     54:        va_start (argptr,fmt);
                     55:        vsprintf (string, fmt,argptr);
                     56:        va_end (argptr);
                     57:        
                     58:        MSG_WriteByte (&cl->netchan.message, svc_print);
                     59:        MSG_WriteByte (&cl->netchan.message, level);
                     60:        MSG_WriteString (&cl->netchan.message, string);
                     61: }
                     62: 
                     63: /*
                     64: =================
                     65: SV_BroadcastPrintf
                     66: 
                     67: Sends text to all active clients
                     68: =================
                     69: */
                     70: void SV_BroadcastPrintf (int level, char *fmt, ...)
                     71: {
                     72:        va_list         argptr;
                     73:        char            string[2048];
                     74:        client_t        *cl;
                     75:        int                     i;
                     76: 
                     77:        va_start (argptr,fmt);
                     78:        vsprintf (string, fmt,argptr);
                     79:        va_end (argptr);
                     80:        
                     81:        // echo to console
                     82:        if (dedicated->value)
                     83:        {
                     84:                char    copy[1024];
                     85:                int             i;
                     86:                
                     87:                // mask off high bits
                     88:                for (i=0 ; i<1023 && string[i] ; i++)
                     89:                        copy[i] = string[i]&127;
                     90:                copy[i] = 0;
                     91:                Com_Printf ("%s", copy);
                     92:        }
                     93: 
                     94:        for (i=0, cl = svs.clients ; i<maxclients->value; i++, cl++)
                     95:        {
                     96:                if (level < cl->messagelevel)
                     97:                        continue;
                     98:                if (cl->state != cs_spawned)
                     99:                        continue;
                    100:                MSG_WriteByte (&cl->netchan.message, svc_print);
                    101:                MSG_WriteByte (&cl->netchan.message, level);
                    102:                MSG_WriteString (&cl->netchan.message, string);
                    103:        }
                    104: }
                    105: 
                    106: /*
                    107: =================
                    108: SV_BroadcastCommand
                    109: 
                    110: Sends text to all active clients
                    111: =================
                    112: */
                    113: void SV_BroadcastCommand (char *fmt, ...)
                    114: {
                    115:        va_list         argptr;
                    116:        char            string[1024];
                    117:        
                    118:        if (!sv.state)
                    119:                return;
                    120:        va_start (argptr,fmt);
                    121:        vsprintf (string, fmt,argptr);
                    122:        va_end (argptr);
                    123: 
                    124:        MSG_WriteByte (&sv.multicast, svc_stufftext);
                    125:        MSG_WriteString (&sv.multicast, string);
                    126:        SV_Multicast (NULL, MULTICAST_ALL_R);
                    127: }
                    128: 
                    129: 
                    130: /*
                    131: =================
                    132: SV_Multicast
                    133: 
                    134: Sends the contents of sv.multicast to a subset of the clients,
                    135: then clears sv.multicast.
                    136: 
                    137: MULTICAST_ALL  same as broadcast (origin can be NULL)
                    138: MULTICAST_PVS  send to clients potentially visible from org
                    139: MULTICAST_PHS  send to clients potentially hearable from org
                    140: =================
                    141: */
                    142: void SV_Multicast (vec3_t origin, multicast_t to)
                    143: {
                    144:        client_t        *client;
                    145:        byte            *mask;
                    146:        int                     leafnum, cluster;
                    147:        int                     j;
                    148:        qboolean        reliable;
                    149:        int                     area1, area2;
                    150: 
                    151:        reliable = false;
                    152: 
                    153:        if (to != MULTICAST_ALL_R && to != MULTICAST_ALL)
                    154:        {
                    155:                leafnum = CM_PointLeafnum (origin);
                    156:                area1 = CM_LeafArea (leafnum);
                    157:        }
                    158:        else
                    159:        {
                    160:                leafnum = 0;    // just to avoid compiler warnings
                    161:                area1 = 0;
                    162:        }
                    163: 
                    164:        // if doing a serverrecord, store everything
                    165:        if (svs.demofile)
                    166:                SZ_Write (&svs.demo_multicast, sv.multicast.data, sv.multicast.cursize);
                    167:        
                    168:        switch (to)
                    169:        {
                    170:        case MULTICAST_ALL_R:
                    171:                reliable = true;        // intentional fallthrough
                    172:        case MULTICAST_ALL:
                    173:                leafnum = 0;
                    174:                mask = NULL;
                    175:                break;
                    176: 
                    177:        case MULTICAST_PHS_R:
                    178:                reliable = true;        // intentional fallthrough
                    179:        case MULTICAST_PHS:
                    180:                leafnum = CM_PointLeafnum (origin);
                    181:                cluster = CM_LeafCluster (leafnum);
                    182:                mask = CM_ClusterPHS (cluster);
                    183:                break;
                    184: 
                    185:        case MULTICAST_PVS_R:
                    186:                reliable = true;        // intentional fallthrough
                    187:        case MULTICAST_PVS:
                    188:                leafnum = CM_PointLeafnum (origin);
                    189:                cluster = CM_LeafCluster (leafnum);
                    190:                mask = CM_ClusterPVS (cluster);
                    191:                break;
                    192: 
                    193:        default:
                    194:                mask = NULL;
                    195:                Com_Error (ERR_FATAL, "SV_Multicast: bad to:%i", to);
                    196:        }
                    197: 
                    198:        // send the data to all relevent clients
                    199:        for (j = 0, client = svs.clients; j < maxclients->value; j++, client++)
                    200:        {
                    201:                if (client->state == cs_free || client->state == cs_zombie)
                    202:                        continue;
                    203:                if (client->state != cs_spawned && !reliable)
                    204:                        continue;
                    205: 
                    206:                if (mask)
                    207:                {
                    208:                        leafnum = CM_PointLeafnum (client->edict->s.origin);
                    209:                        cluster = CM_LeafCluster (leafnum);
                    210:                        area2 = CM_LeafArea (leafnum);
                    211:                        if (!CM_AreasConnected (area1, area2))
                    212:                                continue;
                    213:                        if ( mask && (!(mask[cluster>>3] & (1<<(cluster&7)) ) ) )
                    214:                                continue;
                    215:                }
                    216: 
                    217:                if (reliable)
                    218:                        SZ_Write (&client->netchan.message, sv.multicast.data, sv.multicast.cursize);
                    219:                else
                    220:                        SZ_Write (&client->datagram, sv.multicast.data, sv.multicast.cursize);
                    221:        }
                    222: 
                    223:        SZ_Clear (&sv.multicast);
                    224: }
                    225: 
                    226: 
                    227: /*  
                    228: ==================
                    229: SV_StartSound
                    230: 
                    231: Each entity can have eight independant sound sources, like voice,
                    232: weapon, feet, etc.
                    233: 
                    234: If cahnnel & 8, the sound will be sent to everyone, not just
                    235: things in the PHS.
                    236: 
                    237: FIXME: if entity isn't in PHS, they must be forced to be sent or
                    238: have the origin explicitly sent.
                    239: 
                    240: Channel 0 is an auto-allocate channel, the others override anything
                    241: already running on that entity/channel pair.
                    242: 
                    243: An attenuation of 0 will play full volume everywhere in the level.
                    244: Larger attenuations will drop off.  (max 4 attenuation)
                    245: 
                    246: Timeofs can range from 0.0 to 0.1 to cause sounds to be started
                    247: later in the frame than they normally would.
                    248: 
                    249: If origin is NULL, the origin is determined from the entity origin
                    250: or the midpoint of the entity box for bmodels.
                    251: ==================
                    252: */  
                    253: void SV_StartSound (vec3_t origin, edict_t *entity, int channel,
                    254:                                        int soundindex, float volume,
                    255:                                        float attenuation, float timeofs)
                    256: {       
                    257:        int                     sendchan;
                    258:     int                        flags;
                    259:     int                        i;
                    260:        int                     ent;
                    261:        vec3_t          origin_v;
                    262:        qboolean        use_phs;
                    263: 
                    264:        if (volume < 0 || volume > 1.0)
                    265:                Com_Error (ERR_FATAL, "SV_StartSound: volume = %f", volume);
                    266: 
                    267:        if (attenuation < 0 || attenuation > 4)
                    268:                Com_Error (ERR_FATAL, "SV_StartSound: attenuation = %f", attenuation);
                    269: 
                    270: //     if (channel < 0 || channel > 15)
                    271: //             Com_Error (ERR_FATAL, "SV_StartSound: channel = %i", channel);
                    272: 
                    273:        if (timeofs < 0 || timeofs > 0.255)
                    274:                Com_Error (ERR_FATAL, "SV_StartSound: timeofs = %f", timeofs);
                    275: 
                    276:        ent = NUM_FOR_EDICT(entity);
                    277: 
                    278:        if (channel & 8)        // no PHS flag
                    279:        {
                    280:                use_phs = false;
                    281:                channel &= 7;
                    282:        }
                    283:        else
                    284:                use_phs = true;
                    285: 
                    286:        sendchan = (ent<<3) | (channel&7);
                    287: 
                    288:        flags = 0;
                    289:        if (volume != DEFAULT_SOUND_PACKET_VOLUME)
                    290:                flags |= SND_VOLUME;
                    291:        if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
                    292:                flags |= SND_ATTENUATION;
                    293: 
                    294:        // the client doesn't know that bmodels have weird origins
                    295:        // the origin can also be explicitly set
                    296:        if ( (entity->svflags & SVF_NOCLIENT)
                    297:                || (entity->solid == SOLID_BSP) 
                    298:                || origin )
                    299:                flags |= SND_POS;
                    300: 
                    301:        // always send the entity number for channel overrides
                    302:        flags |= SND_ENT;
                    303: 
                    304:        if (timeofs)
                    305:                flags |= SND_OFFSET;
                    306: 
                    307:        // use the entity origin unless it is a bmodel or explicitly specified
                    308:        if (!origin)
                    309:        {
                    310:                origin = origin_v;
                    311:                if (entity->solid == SOLID_BSP)
                    312:                {
                    313:                        for (i=0 ; i<3 ; i++)
                    314:                                origin_v[i] = entity->s.origin[i]+0.5*(entity->mins[i]+entity->maxs[i]);
                    315:                }
                    316:                else
                    317:                {
                    318:                        VectorCopy (entity->s.origin, origin_v);
                    319:                }
                    320:        }
                    321: 
                    322:        MSG_WriteByte (&sv.multicast, svc_sound);
                    323:        MSG_WriteByte (&sv.multicast, flags);
                    324:        MSG_WriteByte (&sv.multicast, soundindex);
                    325: 
                    326:        if (flags & SND_VOLUME)
                    327:                MSG_WriteByte (&sv.multicast, volume*255);
                    328:        if (flags & SND_ATTENUATION)
                    329:                MSG_WriteByte (&sv.multicast, attenuation*64);
                    330:        if (flags & SND_OFFSET)
                    331:                MSG_WriteByte (&sv.multicast, timeofs*1000);
                    332: 
                    333:        if (flags & SND_ENT)
                    334:                MSG_WriteShort (&sv.multicast, sendchan);
                    335: 
                    336:        if (flags & SND_POS)
                    337:                MSG_WritePos (&sv.multicast, origin);
                    338: 
                    339:        // if the sound doesn't attenuate,send it to everyone
                    340:        // (global radio chatter, voiceovers, etc)
                    341:        if (attenuation == ATTN_NONE)
                    342:                use_phs = false;
                    343: 
                    344:        if (channel & CHAN_RELIABLE)
                    345:        {
                    346:                if (use_phs)
                    347:                        SV_Multicast (origin, MULTICAST_PHS_R);
                    348:                else
                    349:                        SV_Multicast (origin, MULTICAST_ALL_R);
                    350:        }
                    351:        else
                    352:        {
                    353:                if (use_phs)
                    354:                        SV_Multicast (origin, MULTICAST_PHS);
                    355:                else
                    356:                        SV_Multicast (origin, MULTICAST_ALL);
                    357:        }
                    358: }           
                    359: 
                    360: 
                    361: /*
                    362: ===============================================================================
                    363: 
                    364: FRAME UPDATES
                    365: 
                    366: ===============================================================================
                    367: */
                    368: 
                    369: 
                    370: 
                    371: /*
                    372: =======================
                    373: SV_SendClientDatagram
                    374: =======================
                    375: */
                    376: qboolean SV_SendClientDatagram (client_t *client)
                    377: {
                    378:        byte            msg_buf[MAX_MSGLEN];
                    379:        sizebuf_t       msg;
                    380: 
                    381:        SV_BuildClientFrame (client);
                    382: 
                    383:        SZ_Init (&msg, msg_buf, sizeof(msg_buf));
                    384:        msg.allowoverflow = true;
                    385: 
                    386:        // send over all the relevant entity_state_t
                    387:        // and the player_state_t
                    388:        SV_WriteFrameToClient (client, &msg);
                    389: 
                    390:        // copy the accumulated multicast datagram
                    391:        // for this client out to the message
                    392:        // it is necessary for this to be after the WriteEntities
                    393:        // so that entity references will be current
                    394:        if (client->datagram.overflowed)
                    395:                Com_Printf ("WARNING: datagram overflowed for %s\n", client->name);
                    396:        else
                    397:                SZ_Write (&msg, client->datagram.data, client->datagram.cursize);
                    398:        SZ_Clear (&client->datagram);
                    399: 
                    400:        if (msg.overflowed)
                    401:        {       // must have room left for the packet header
                    402:                Com_Printf ("WARNING: msg overflowed for %s\n", client->name);
                    403:                SZ_Clear (&msg);
                    404:        }
                    405: 
                    406:        // send the datagram
                    407:        Netchan_Transmit (&client->netchan, msg.cursize, msg.data);
                    408: 
                    409:        // record the size for rate estimation
                    410:        client->message_size[sv.framenum % RATE_MESSAGES] = msg.cursize;
                    411: 
                    412:        return true;
                    413: }
                    414: 
                    415: 
                    416: /*
                    417: ==================
                    418: SV_DemoCompleted
                    419: ==================
                    420: */
                    421: void SV_DemoCompleted (void)
                    422: {
                    423:        if (sv.demofile)
                    424:        {
                    425:                fclose (sv.demofile);
                    426:                sv.demofile = NULL;
                    427:        }
                    428:        SV_Nextserver ();
                    429: }
                    430: 
                    431: 
                    432: /*
                    433: =======================
                    434: SV_RateDrop
                    435: 
                    436: Returns true if the client is over its current
                    437: bandwidth estimation and should not be sent another packet
                    438: =======================
                    439: */
                    440: qboolean SV_RateDrop (client_t *c)
                    441: {
                    442:        int             total;
                    443:        int             i;
                    444: 
                    445:        // never drop over the loopback
                    446:        if (c->netchan.remote_address.type == NA_LOOPBACK)
                    447:                return false;
                    448: 
                    449:        total = 0;
                    450: 
                    451:        for (i = 0 ; i < RATE_MESSAGES ; i++)
                    452:        {
                    453:                total += c->message_size[i];
                    454:        }
                    455: 
                    456:        if (total > c->rate)
                    457:        {
                    458:                c->surpressCount++;
                    459:                c->message_size[sv.framenum % RATE_MESSAGES] = 0;
                    460:                return true;
                    461:        }
                    462: 
                    463:        return false;
                    464: }
                    465: 
                    466: /*
                    467: =======================
                    468: SV_SendClientMessages
                    469: =======================
                    470: */
                    471: void SV_SendClientMessages (void)
                    472: {
                    473:        int                     i;
                    474:        client_t        *c;
                    475:        int                     msglen;
                    476:        byte            msgbuf[MAX_MSGLEN];
                    477:        int                     r;
                    478: 
                    479:        msglen = 0;
                    480: 
                    481:        // read the next demo message if needed
                    482:        if (sv.state == ss_demo && sv.demofile)
                    483:        {
                    484:                if (sv_paused->value)
                    485:                        msglen = 0;
                    486:                else
                    487:                {
                    488:                        // get the next message
                    489:                        r = fread (&msglen, 4, 1, sv.demofile);
                    490:                        if (r != 1)
                    491:                        {
                    492:                                SV_DemoCompleted ();
                    493:                                return;
                    494:                        }
                    495:                        msglen = LittleLong (msglen);
                    496:                        if (msglen == -1)
                    497:                        {
                    498:                                SV_DemoCompleted ();
                    499:                                return;
                    500:                        }
                    501:                        if (msglen > MAX_MSGLEN)
                    502:                                Com_Error (ERR_DROP, "SV_SendClientMessages: msglen > MAX_MSGLEN");
                    503:                        r = fread (msgbuf, msglen, 1, sv.demofile);
                    504:                        if (r != 1)
                    505:                        {
                    506:                                SV_DemoCompleted ();
                    507:                                return;
                    508:                        }
                    509:                }
                    510:        }
                    511: 
                    512:        // send a message to each connected client
                    513:        for (i=0, c = svs.clients ; i<maxclients->value; i++, c++)
                    514:        {
                    515:                if (!c->state)
                    516:                        continue;
                    517:                // if the reliable message overflowed,
                    518:                // drop the client
                    519:                if (c->netchan.message.overflowed)
                    520:                {
                    521:                        SZ_Clear (&c->netchan.message);
                    522:                        SZ_Clear (&c->datagram);
                    523:                        SV_BroadcastPrintf (PRINT_HIGH, "%s overflowed\n", c->name);
                    524:                        SV_DropClient (c);
                    525:                }
                    526: 
                    527:                if (sv.state == ss_cinematic 
                    528:                        || sv.state == ss_demo 
                    529:                        || sv.state == ss_pic
                    530:                        )
                    531:                        Netchan_Transmit (&c->netchan, msglen, msgbuf);
                    532:                else if (c->state == cs_spawned)
                    533:                {
                    534:                        // don't overrun bandwidth
                    535:                        if (SV_RateDrop (c))
                    536:                                continue;
                    537: 
                    538:                        SV_SendClientDatagram (c);
                    539:                }
                    540:                else
                    541:                {
                    542:        // just update reliable if needed
                    543:                        if (c->netchan.message.cursize  || curtime - c->netchan.last_sent > 1000 )
                    544:                                Netchan_Transmit (&c->netchan, 0, NULL);
                    545:                }
                    546:        }
                    547: }
                    548: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.