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

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

unix.superglobalmegacorp.com

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