Annotation of quakeworld/server/sv_user.c, revision 1.1.1.1

1.1       root        1: /*
                      2: Copyright (C) 1996-1997 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: */
                     20: // sv_user.c -- server code for moving users
                     21: 
                     22: #include "qwsvdef.h"
                     23: 
                     24: edict_t        *sv_player;
                     25: 
                     26: usercmd_t      cmd;
                     27: 
                     28: cvar_t cl_rollspeed = {"cl_rollspeed", "200"};
                     29: cvar_t cl_rollangle = {"cl_rollangle", "2.0"};
                     30: cvar_t sv_spectalk = {"sv_spectalk", "1"};
                     31: 
                     32: cvar_t sv_mapcheck     = {"sv_mapcheck", "1"};
                     33: 
                     34: extern vec3_t  player_mins;
                     35: 
                     36: extern int fp_messages, fp_persecond, fp_secondsdead;
                     37: extern char fp_msg[];
                     38: extern cvar_t pausable;
                     39: 
                     40: /*
                     41: ============================================================
                     42: 
                     43: USER STRINGCMD EXECUTION
                     44: 
                     45: host_client and sv_player will be valid.
                     46: ============================================================
                     47: */
                     48: 
                     49: /*
                     50: ================
                     51: SV_New_f
                     52: 
                     53: Sends the first message from the server to a connected client.
                     54: This will be sent on the initial connection and upon each server load.
                     55: ================
                     56: */
                     57: void SV_New_f (void)
                     58: {
                     59:        char            *gamedir;
                     60:        int                     playernum;
                     61: 
                     62:        if (host_client->state == cs_spawned)
                     63:                return;
                     64: 
                     65:        host_client->state = cs_connected;
                     66:        host_client->connection_started = realtime;
                     67: 
                     68:        // send the info about the new client to all connected clients
                     69: //     SV_FullClientUpdate (host_client, &sv.reliable_datagram);
                     70: //     host_client->sendinfo = true;
                     71: 
                     72:        gamedir = Info_ValueForKey (svs.info, "*gamedir");
                     73:        if (!gamedir[0])
                     74:                gamedir = "qw";
                     75: 
                     76: //NOTE:  This doesn't go through ClientReliableWrite since it's before the user
                     77: //spawns.  These functions are written to not overflow
                     78:        if (host_client->num_backbuf) {
                     79:                Con_Printf("WARNING %s: [SV_New] Back buffered (%d0, clearing", host_client->name, host_client->netchan.message.cursize); 
                     80:                host_client->num_backbuf = 0;
                     81:                SZ_Clear(&host_client->netchan.message);
                     82:        }
                     83: 
                     84:        // send the serverdata
                     85:        MSG_WriteByte (&host_client->netchan.message, svc_serverdata);
                     86:        MSG_WriteLong (&host_client->netchan.message, PROTOCOL_VERSION);
                     87:        MSG_WriteLong (&host_client->netchan.message, svs.spawncount);
                     88:        MSG_WriteString (&host_client->netchan.message, gamedir);
                     89: 
                     90:        playernum = NUM_FOR_EDICT(host_client->edict)-1;
                     91:        if (host_client->spectator)
                     92:                playernum |= 128;
                     93:        MSG_WriteByte (&host_client->netchan.message, playernum);
                     94: 
                     95:        // send full levelname
                     96:        MSG_WriteString (&host_client->netchan.message, PR_GetString(sv.edicts->v.message));
                     97: 
                     98:        // send the movevars
                     99:        MSG_WriteFloat(&host_client->netchan.message, movevars.gravity);
                    100:        MSG_WriteFloat(&host_client->netchan.message, movevars.stopspeed);
                    101:        MSG_WriteFloat(&host_client->netchan.message, movevars.maxspeed);
                    102:        MSG_WriteFloat(&host_client->netchan.message, movevars.spectatormaxspeed);
                    103:        MSG_WriteFloat(&host_client->netchan.message, movevars.accelerate);
                    104:        MSG_WriteFloat(&host_client->netchan.message, movevars.airaccelerate);
                    105:        MSG_WriteFloat(&host_client->netchan.message, movevars.wateraccelerate);
                    106:        MSG_WriteFloat(&host_client->netchan.message, movevars.friction);
                    107:        MSG_WriteFloat(&host_client->netchan.message, movevars.waterfriction);
                    108:        MSG_WriteFloat(&host_client->netchan.message, movevars.entgravity);
                    109: 
                    110:        // send music
                    111:        MSG_WriteByte (&host_client->netchan.message, svc_cdtrack);
                    112:        MSG_WriteByte (&host_client->netchan.message, sv.edicts->v.sounds);
                    113: 
                    114:        // send server info string
                    115:        MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
                    116:        MSG_WriteString (&host_client->netchan.message, va("fullserverinfo \"%s\"\n", svs.info) );
                    117: }
                    118: 
                    119: /*
                    120: ==================
                    121: SV_Soundlist_f
                    122: ==================
                    123: */
                    124: void SV_Soundlist_f (void)
                    125: {
                    126:        char            **s;
                    127:        int                     n;
                    128: 
                    129:        if (host_client->state != cs_connected)
                    130:        {
                    131:                Con_Printf ("soundlist not valid -- allready spawned\n");
                    132:                return;
                    133:        }
                    134: 
                    135:        // handle the case of a level changing while a client was connecting
                    136:        if ( atoi(Cmd_Argv(1)) != svs.spawncount )
                    137:        {
                    138:                Con_Printf ("SV_Soundlist_f from different level\n");
                    139:                SV_New_f ();
                    140:                return;
                    141:        }
                    142: 
                    143:        n = atoi(Cmd_Argv(2));
                    144:        
                    145: //NOTE:  This doesn't go through ClientReliableWrite since it's before the user
                    146: //spawns.  These functions are written to not overflow
                    147:        if (host_client->num_backbuf) {
                    148:                Con_Printf("WARNING %s: [SV_Soundlist] Back buffered (%d0, clearing", host_client->name, host_client->netchan.message.cursize); 
                    149:                host_client->num_backbuf = 0;
                    150:                SZ_Clear(&host_client->netchan.message);
                    151:        }
                    152: 
                    153:        MSG_WriteByte (&host_client->netchan.message, svc_soundlist);
                    154:        MSG_WriteByte (&host_client->netchan.message, n);
                    155:        for (s = sv.sound_precache+1 + n ; 
                    156:                *s && host_client->netchan.message.cursize < (MAX_MSGLEN/2); 
                    157:                s++, n++)
                    158:                MSG_WriteString (&host_client->netchan.message, *s);
                    159: 
                    160:        MSG_WriteByte (&host_client->netchan.message, 0);
                    161: 
                    162:        // next msg
                    163:        if (*s)
                    164:                MSG_WriteByte (&host_client->netchan.message, n);
                    165:        else
                    166:                MSG_WriteByte (&host_client->netchan.message, 0);
                    167: }
                    168: 
                    169: /*
                    170: ==================
                    171: SV_Modellist_f
                    172: ==================
                    173: */
                    174: void SV_Modellist_f (void)
                    175: {
                    176:        char            **s;
                    177:        int                     n;
                    178: 
                    179:        if (host_client->state != cs_connected)
                    180:        {
                    181:                Con_Printf ("modellist not valid -- allready spawned\n");
                    182:                return;
                    183:        }
                    184:        
                    185:        // handle the case of a level changing while a client was connecting
                    186:        if ( atoi(Cmd_Argv(1)) != svs.spawncount )
                    187:        {
                    188:                Con_Printf ("SV_Modellist_f from different level\n");
                    189:                SV_New_f ();
                    190:                return;
                    191:        }
                    192: 
                    193:        n = atoi(Cmd_Argv(2));
                    194: 
                    195: //NOTE:  This doesn't go through ClientReliableWrite since it's before the user
                    196: //spawns.  These functions are written to not overflow
                    197:        if (host_client->num_backbuf) {
                    198:                Con_Printf("WARNING %s: [SV_Modellist] Back buffered (%d0, clearing", host_client->name, host_client->netchan.message.cursize); 
                    199:                host_client->num_backbuf = 0;
                    200:                SZ_Clear(&host_client->netchan.message);
                    201:        }
                    202: 
                    203:        MSG_WriteByte (&host_client->netchan.message, svc_modellist);
                    204:        MSG_WriteByte (&host_client->netchan.message, n);
                    205:        for (s = sv.model_precache+1+n ; 
                    206:                *s && host_client->netchan.message.cursize < (MAX_MSGLEN/2); 
                    207:                s++, n++)
                    208:                MSG_WriteString (&host_client->netchan.message, *s);
                    209:        MSG_WriteByte (&host_client->netchan.message, 0);
                    210: 
                    211:        // next msg
                    212:        if (*s)
                    213:                MSG_WriteByte (&host_client->netchan.message, n);
                    214:        else
                    215:                MSG_WriteByte (&host_client->netchan.message, 0);
                    216: }
                    217: 
                    218: /*
                    219: ==================
                    220: SV_PreSpawn_f
                    221: ==================
                    222: */
                    223: void SV_PreSpawn_f (void)
                    224: {
                    225:        unsigned        buf;
                    226:        unsigned        check;
                    227: 
                    228:        if (host_client->state != cs_connected)
                    229:        {
                    230:                Con_Printf ("prespawn not valid -- allready spawned\n");
                    231:                return;
                    232:        }
                    233:        
                    234:        // handle the case of a level changing while a client was connecting
                    235:        if ( atoi(Cmd_Argv(1)) != svs.spawncount )
                    236:        {
                    237:                Con_Printf ("SV_PreSpawn_f from different level\n");
                    238:                SV_New_f ();
                    239:                return;
                    240:        }
                    241:        
                    242:        buf = atoi(Cmd_Argv(2));
                    243:        if (buf >= sv.num_signon_buffers)
                    244:                buf = 0;
                    245: 
                    246:        if (!buf) {
                    247:                // should be three numbers following containing checksums
                    248:                check = atoi(Cmd_Argv(3));
                    249: 
                    250: //             Con_DPrintf("Client check = %d\n", check);
                    251: 
                    252:                if (sv_mapcheck.value && check != sv.worldmodel->checksum &&
                    253:                        check != sv.worldmodel->checksum2) {
                    254:                        SV_ClientPrintf (host_client, PRINT_HIGH, 
                    255:                                "Map model file does not match (%s), %i != %i/%i.\n"
                    256:                                "You may need a new version of the map, or the proper install files.\n",
                    257:                                sv.modelname, check, sv.worldmodel->checksum, sv.worldmodel->checksum2);
                    258:                        SV_DropClient (host_client); 
                    259:                        return;
                    260:                }
                    261:                host_client->checksum = check;
                    262:        }
                    263: 
                    264: //NOTE:  This doesn't go through ClientReliableWrite since it's before the user
                    265: //spawns.  These functions are written to not overflow
                    266:        if (host_client->num_backbuf) {
                    267:                Con_Printf("WARNING %s: [SV_PreSpawn] Back buffered (%d0, clearing", host_client->name, host_client->netchan.message.cursize); 
                    268:                host_client->num_backbuf = 0;
                    269:                SZ_Clear(&host_client->netchan.message);
                    270:        }
                    271: 
                    272:        SZ_Write (&host_client->netchan.message, 
                    273:                sv.signon_buffers[buf],
                    274:                sv.signon_buffer_size[buf]);
                    275: 
                    276:        buf++;
                    277:        if (buf == sv.num_signon_buffers)
                    278:        {       // all done prespawning
                    279:                MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
                    280:                MSG_WriteString (&host_client->netchan.message, va("cmd spawn %i 0\n",svs.spawncount) );
                    281:        }
                    282:        else
                    283:        {       // need to prespawn more
                    284:                MSG_WriteByte (&host_client->netchan.message, svc_stufftext);
                    285:                MSG_WriteString (&host_client->netchan.message, 
                    286:                        va("cmd prespawn %i %i\n", svs.spawncount, buf) );
                    287:        }
                    288: }
                    289: 
                    290: /*
                    291: ==================
                    292: SV_Spawn_f
                    293: ==================
                    294: */
                    295: void SV_Spawn_f (void)
                    296: {
                    297:        int             i;
                    298:        client_t        *client;
                    299:        edict_t *ent;
                    300:        eval_t *val;
                    301:        int n;
                    302: 
                    303:        if (host_client->state != cs_connected)
                    304:        {
                    305:                Con_Printf ("Spawn not valid -- allready spawned\n");
                    306:                return;
                    307:        }
                    308: 
                    309: // handle the case of a level changing while a client was connecting
                    310:        if ( atoi(Cmd_Argv(1)) != svs.spawncount )
                    311:        {
                    312:                Con_Printf ("SV_Spawn_f from different level\n");
                    313:                SV_New_f ();
                    314:                return;
                    315:        }
                    316: 
                    317:        n = atoi(Cmd_Argv(2));
                    318: 
                    319:        // make sure n is valid
                    320:        if ( n < 0 || n > MAX_CLIENTS )
                    321:        {
                    322:                Con_Printf ("SV_Spawn_f invalid client start\n");
                    323:                SV_New_f ();
                    324:                return;
                    325:        }
                    326: 
                    327: 
                    328:        
                    329: // send all current names, colors, and frag counts
                    330:        // FIXME: is this a good thing?
                    331:        SZ_Clear (&host_client->netchan.message);
                    332: 
                    333: // send current status of all other players
                    334: 
                    335:        // normally this could overflow, but no need to check due to backbuf
                    336:        for (i=n, client = svs.clients + n ; i<MAX_CLIENTS ; i++, client++)
                    337:                SV_FullClientUpdateToClient (client, host_client);
                    338:        
                    339: // send all current light styles
                    340:        for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
                    341:        {
                    342:                ClientReliableWrite_Begin (host_client, svc_lightstyle, 
                    343:                        3 + (sv.lightstyles[i] ? strlen(sv.lightstyles[i]) : 1));
                    344:                ClientReliableWrite_Byte (host_client, (char)i);
                    345:                ClientReliableWrite_String (host_client, sv.lightstyles[i]);
                    346:        }
                    347: 
                    348:        // set up the edict
                    349:        ent = host_client->edict;
                    350: 
                    351:        memset (&ent->v, 0, progs->entityfields * 4);
                    352:        ent->v.colormap = NUM_FOR_EDICT(ent);
                    353:        ent->v.team = 0;        // FIXME
                    354:        ent->v.netname = PR_SetString(host_client->name);
                    355: 
                    356:        host_client->entgravity = 1.0;
                    357:        val = GetEdictFieldValue(ent, "gravity");
                    358:        if (val)
                    359:                val->_float = 1.0;
                    360:        host_client->maxspeed = sv_maxspeed.value;
                    361:        val = GetEdictFieldValue(ent, "maxspeed");
                    362:        if (val)
                    363:                val->_float = sv_maxspeed.value;
                    364: 
                    365: //
                    366: // force stats to be updated
                    367: //
                    368:        memset (host_client->stats, 0, sizeof(host_client->stats));
                    369: 
                    370:        ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6);
                    371:        ClientReliableWrite_Byte (host_client, STAT_TOTALSECRETS);
                    372:        ClientReliableWrite_Long (host_client, pr_global_struct->total_secrets);
                    373: 
                    374:        ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6);
                    375:        ClientReliableWrite_Byte (host_client, STAT_TOTALMONSTERS);
                    376:        ClientReliableWrite_Long (host_client, pr_global_struct->total_monsters);
                    377: 
                    378:        ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6);
                    379:        ClientReliableWrite_Byte (host_client, STAT_SECRETS);
                    380:        ClientReliableWrite_Long (host_client, pr_global_struct->found_secrets);
                    381: 
                    382:        ClientReliableWrite_Begin (host_client, svc_updatestatlong, 6);
                    383:        ClientReliableWrite_Byte (host_client, STAT_MONSTERS);
                    384:        ClientReliableWrite_Long (host_client, pr_global_struct->killed_monsters);
                    385: 
                    386:        // get the client to check and download skins
                    387:        // when that is completed, a begin command will be issued
                    388:        ClientReliableWrite_Begin (host_client, svc_stufftext, 8);
                    389:        ClientReliableWrite_String (host_client, "skins\n" );
                    390: 
                    391: }
                    392: 
                    393: /*
                    394: ==================
                    395: SV_SpawnSpectator
                    396: ==================
                    397: */
                    398: void SV_SpawnSpectator (void)
                    399: {
                    400:        int             i;
                    401:        edict_t *e;
                    402: 
                    403:        VectorCopy (vec3_origin, sv_player->v.origin);
                    404:        VectorCopy (vec3_origin, sv_player->v.view_ofs);
                    405:        sv_player->v.view_ofs[2] = 22;
                    406: 
                    407:        // search for an info_playerstart to spawn the spectator at
                    408:        for (i=MAX_CLIENTS-1 ; i<sv.num_edicts ; i++)
                    409:        {
                    410:                e = EDICT_NUM(i);
                    411:                if (!strcmp(PR_GetString(e->v.classname), "info_player_start"))
                    412:                {
                    413:                        VectorCopy (e->v.origin, sv_player->v.origin);
                    414:                        return;
                    415:                }
                    416:        }
                    417: 
                    418: }
                    419: 
                    420: /*
                    421: ==================
                    422: SV_Begin_f
                    423: ==================
                    424: */
                    425: void SV_Begin_f (void)
                    426: {
                    427:        unsigned pmodel = 0, emodel = 0;
                    428:        int             i;
                    429: 
                    430:        if (host_client->state == cs_spawned)
                    431:                return; // don't begin again
                    432: 
                    433:        host_client->state = cs_spawned;
                    434:        
                    435:        // handle the case of a level changing while a client was connecting
                    436:        if ( atoi(Cmd_Argv(1)) != svs.spawncount )
                    437:        {
                    438:                Con_Printf ("SV_Begin_f from different level\n");
                    439:                SV_New_f ();
                    440:                return;
                    441:        }
                    442: 
                    443:        if (host_client->spectator)
                    444:        {
                    445:                SV_SpawnSpectator ();
                    446: 
                    447:                if (SpectatorConnect) {
                    448:                        // copy spawn parms out of the client_t
                    449:                        for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
                    450:                                (&pr_global_struct->parm1)[i] = host_client->spawn_parms[i];
                    451:        
                    452:                        // call the spawn function
                    453:                        pr_global_struct->time = sv.time;
                    454:                        pr_global_struct->self = EDICT_TO_PROG(sv_player);
                    455:                        PR_ExecuteProgram (SpectatorConnect);
                    456:                }
                    457:        }
                    458:        else
                    459:        {
                    460:                // copy spawn parms out of the client_t
                    461:                for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
                    462:                        (&pr_global_struct->parm1)[i] = host_client->spawn_parms[i];
                    463: 
                    464:                // call the spawn function
                    465:                pr_global_struct->time = sv.time;
                    466:                pr_global_struct->self = EDICT_TO_PROG(sv_player);
                    467:                PR_ExecuteProgram (pr_global_struct->ClientConnect);
                    468: 
                    469:                // actually spawn the player
                    470:                pr_global_struct->time = sv.time;
                    471:                pr_global_struct->self = EDICT_TO_PROG(sv_player);
                    472:                PR_ExecuteProgram (pr_global_struct->PutClientInServer);        
                    473:        }
                    474: 
                    475:        // clear the net statistics, because connecting gives a bogus picture
                    476:        host_client->netchan.frame_latency = 0;
                    477:        host_client->netchan.frame_rate = 0;
                    478:        host_client->netchan.drop_count = 0;
                    479:        host_client->netchan.good_count = 0;
                    480: 
                    481:        //check he's not cheating
                    482: 
                    483:        pmodel = atoi(Info_ValueForKey (host_client->userinfo, "pmodel"));
                    484:        emodel = atoi(Info_ValueForKey (host_client->userinfo, "emodel"));
                    485: 
                    486:        if (pmodel != sv.model_player_checksum ||
                    487:                emodel != sv.eyes_player_checksum)
                    488:                SV_BroadcastPrintf (PRINT_HIGH, "%s WARNING: non standard player/eyes model detected\n", host_client->name);
                    489: 
                    490:        // if we are paused, tell the client
                    491:        if (sv.paused) {
                    492:                ClientReliableWrite_Begin (host_client, svc_setpause, 2);
                    493:                ClientReliableWrite_Byte (host_client, sv.paused);
                    494:                SV_ClientPrintf(host_client, PRINT_HIGH, "Server is paused.\n");
                    495:        }
                    496: 
                    497: #if 0
                    498: //
                    499: // send a fixangle over the reliable channel to make sure it gets there
                    500: // Never send a roll angle, because savegames can catch the server
                    501: // in a state where it is expecting the client to correct the angle
                    502: // and it won't happen if the game was just loaded, so you wind up
                    503: // with a permanent head tilt
                    504:        ent = EDICT_NUM( 1 + (host_client - svs.clients) );
                    505:        MSG_WriteByte (&host_client->netchan.message, svc_setangle);
                    506:        for (i=0 ; i < 2 ; i++)
                    507:                MSG_WriteAngle (&host_client->netchan.message, ent->v.angles[i] );
                    508:        MSG_WriteAngle (&host_client->netchan.message, 0 );
                    509: #endif
                    510: }
                    511: 
                    512: //=============================================================================
                    513: 
                    514: /*
                    515: ==================
                    516: SV_NextDownload_f
                    517: ==================
                    518: */
                    519: void SV_NextDownload_f (void)
                    520: {
                    521:        byte    buffer[1024];
                    522:        int             r;
                    523:        int             percent;
                    524:        int             size;
                    525: 
                    526:        if (!host_client->download)
                    527:                return;
                    528: 
                    529:        r = host_client->downloadsize - host_client->downloadcount;
                    530:        if (r > 768)
                    531:                r = 768;
                    532:        r = fread (buffer, 1, r, host_client->download);
                    533:        ClientReliableWrite_Begin (host_client, svc_download, 6+r);
                    534:        ClientReliableWrite_Short (host_client, r);
                    535: 
                    536:        host_client->downloadcount += r;
                    537:        size = host_client->downloadsize;
                    538:        if (!size)
                    539:                size = 1;
                    540:        percent = host_client->downloadcount*100/size;
                    541:        ClientReliableWrite_Byte (host_client, percent);
                    542:        ClientReliableWrite_SZ (host_client, buffer, r);
                    543: 
                    544:        if (host_client->downloadcount != host_client->downloadsize)
                    545:                return;
                    546: 
                    547:        fclose (host_client->download);
                    548:        host_client->download = NULL;
                    549: 
                    550: }
                    551: 
                    552: void OutofBandPrintf(netadr_t where, char *fmt, ...)
                    553: {
                    554:        va_list         argptr;
                    555:        char    send[1024];
                    556:        
                    557:        send[0] = 0xff;
                    558:        send[1] = 0xff;
                    559:        send[2] = 0xff;
                    560:        send[3] = 0xff;
                    561:        send[4] = A2C_PRINT;
                    562:        va_start (argptr, fmt);
                    563:        vsprintf (send+5, fmt, argptr);
                    564:        va_end (argptr);
                    565: 
                    566:        NET_SendPacket (strlen(send)+1, send, where);
                    567: }
                    568: 
                    569: /*
                    570: ==================
                    571: SV_NextUpload
                    572: ==================
                    573: */
                    574: void SV_NextUpload (void)
                    575: {
                    576:        byte    buffer[1024];
                    577:        int             r;
                    578:        int             percent;
                    579:        int             size;
                    580:        client_t *client;
                    581: 
                    582:        if (!*host_client->uploadfn) {
                    583:                SV_ClientPrintf(host_client, PRINT_HIGH, "Upload denied\n");
                    584:                ClientReliableWrite_Begin (host_client, svc_stufftext, 8);
                    585:                ClientReliableWrite_String (host_client, "stopul");
                    586: 
                    587:                // suck out rest of packet
                    588:                size = MSG_ReadShort ();        MSG_ReadByte ();
                    589:                msg_readcount += size;
                    590:                return;
                    591:        }
                    592: 
                    593:        size = MSG_ReadShort ();
                    594:        percent = MSG_ReadByte ();
                    595: 
                    596:        if (!host_client->upload)
                    597:        {
                    598:                host_client->upload = fopen(host_client->uploadfn, "wb");
                    599:                if (!host_client->upload) {
                    600:                        Sys_Printf("Can't create %s\n", host_client->uploadfn);
                    601:                        ClientReliableWrite_Begin (host_client, svc_stufftext, 8);
                    602:                        ClientReliableWrite_String (host_client, "stopul");
                    603:                        *host_client->uploadfn = 0;
                    604:                        return;
                    605:                }
                    606:                Sys_Printf("Receiving %s from %d...\n", host_client->uploadfn, host_client->userid);
                    607:                if (host_client->remote_snap)
                    608:                        OutofBandPrintf(host_client->snap_from, "Server receiving %s from %d...\n", host_client->uploadfn, host_client->userid);
                    609:        }
                    610: 
                    611:        fwrite (net_message.data + msg_readcount, 1, size, host_client->upload);
                    612:        msg_readcount += size;
                    613: 
                    614: Con_DPrintf ("UPLOAD: %d received\n", size);
                    615: 
                    616:        if (percent != 100) {
                    617:                ClientReliableWrite_Begin (host_client, svc_stufftext, 8);
                    618:                ClientReliableWrite_String (host_client, "nextul\n");
                    619:        } else {
                    620:                fclose (host_client->upload);
                    621:                host_client->upload = NULL;
                    622: 
                    623:                Sys_Printf("%s upload completed.\n", host_client->uploadfn);
                    624: 
                    625:                if (host_client->remote_snap) {
                    626:                        char *p;
                    627: 
                    628:                        if ((p = strchr(host_client->uploadfn, '/')) != NULL)
                    629:                                p++;
                    630:                        else
                    631:                                p = host_client->uploadfn;
                    632:                        OutofBandPrintf(host_client->snap_from, "%s upload completed.\nTo download, enter:\ndownload %s\n", 
                    633:                                host_client->uploadfn, p);
                    634:                }
                    635:        }
                    636: 
                    637: }
                    638: 
                    639: /*
                    640: ==================
                    641: SV_BeginDownload_f
                    642: ==================
                    643: */
                    644: void SV_BeginDownload_f(void)
                    645: {
                    646:        char    *name;
                    647:        extern  cvar_t  allow_download;
                    648:        extern  cvar_t  allow_download_skins;
                    649:        extern  cvar_t  allow_download_models;
                    650:        extern  cvar_t  allow_download_sounds;
                    651:        extern  cvar_t  allow_download_maps;
                    652:        extern  int             file_from_pak; // ZOID did file come from pak?
                    653: 
                    654:        name = Cmd_Argv(1);
                    655: // hacked by zoid to allow more conrol over download
                    656:                // first off, no .. or global allow check
                    657:        if (strstr (name, "..") || !allow_download.value
                    658:                // leading dot is no good
                    659:                || *name == '.' 
                    660:                // leading slash bad as well, must be in subdir
                    661:                || *name == '/'
                    662:                // next up, skin check
                    663:                || (strncmp(name, "skins/", 6) == 0 && !allow_download_skins.value)
                    664:                // now models
                    665:                || (strncmp(name, "progs/", 6) == 0 && !allow_download_models.value)
                    666:                // now sounds
                    667:                || (strncmp(name, "sound/", 6) == 0 && !allow_download_sounds.value)
                    668:                // now maps (note special case for maps, must not be in pak)
                    669:                || (strncmp(name, "maps/", 6) == 0 && !allow_download_maps.value)
                    670:                // MUST be in a subdirectory    
                    671:                || !strstr (name, "/") )        
                    672:        {       // don't allow anything with .. path
                    673:                ClientReliableWrite_Begin (host_client, svc_download, 4);
                    674:                ClientReliableWrite_Short (host_client, -1);
                    675:                ClientReliableWrite_Byte (host_client, 0);
                    676:                return;
                    677:        }
                    678: 
                    679:        if (host_client->download) {
                    680:                fclose (host_client->download);
                    681:                host_client->download = NULL;
                    682:        }
                    683: 
                    684:        // lowercase name (needed for casesen file systems)
                    685:        {
                    686:                char *p;
                    687: 
                    688:                for (p = name; *p; p++)
                    689:                        *p = (char)tolower(*p);
                    690:        }
                    691: 
                    692: 
                    693:        host_client->downloadsize = COM_FOpenFile (name, &host_client->download);
                    694:        host_client->downloadcount = 0;
                    695: 
                    696:        if (!host_client->download
                    697:                // special check for maps, if it came from a pak file, don't allow
                    698:                // download  ZOID
                    699:                || (strncmp(name, "maps/", 5) == 0 && file_from_pak))
                    700:        {
                    701:                if (host_client->download) {
                    702:                        fclose(host_client->download);
                    703:                        host_client->download = NULL;
                    704:                }
                    705: 
                    706:                Sys_Printf ("Couldn't download %s to %s\n", name, host_client->name);
                    707:                ClientReliableWrite_Begin (host_client, svc_download, 4);
                    708:                ClientReliableWrite_Short (host_client, -1);
                    709:                ClientReliableWrite_Byte (host_client, 0);
                    710:                return;
                    711:        }
                    712: 
                    713:        SV_NextDownload_f ();
                    714:        Sys_Printf ("Downloading %s to %s\n", name, host_client->name);
                    715: }
                    716: 
                    717: //=============================================================================
                    718: 
                    719: /*
                    720: ==================
                    721: SV_Say
                    722: ==================
                    723: */
                    724: void SV_Say (qboolean team)
                    725: {
                    726:        client_t *client;
                    727:        int             j, tmp;
                    728:        char    *p;
                    729:        char    text[2048];
                    730:        char    t1[32], *t2;
                    731: 
                    732:        if (Cmd_Argc () < 2)
                    733:                return;
                    734: 
                    735:        if (team)
                    736:        {
                    737:                strncpy (t1, Info_ValueForKey (host_client->userinfo, "team"), 31);
                    738:                t1[31] = 0;
                    739:        }
                    740: 
                    741:        if (host_client->spectator && (!sv_spectalk.value || team))
                    742:                sprintf (text, "[SPEC] %s: ", host_client->name);
                    743:        else if (team)
                    744:                sprintf (text, "(%s): ", host_client->name);
                    745:        else {
                    746:                sprintf (text, "%s: ", host_client->name);
                    747:        }
                    748: 
                    749:        if (fp_messages) {
                    750:                if (!sv.paused && realtime<host_client->lockedtill) {
                    751:                        SV_ClientPrintf(host_client, PRINT_CHAT,
                    752:                                "You can't talk for %d more seconds\n", 
                    753:                                        (int) (host_client->lockedtill - realtime));
                    754:                        return;
                    755:                }
                    756:                tmp = host_client->whensaidhead - fp_messages + 1;
                    757:                if (tmp < 0)
                    758:                        tmp = 10+tmp;
                    759:                if (!sv.paused &&
                    760:                        host_client->whensaid[tmp] && (realtime-host_client->whensaid[tmp] < fp_persecond)) {
                    761:                        host_client->lockedtill = realtime + fp_secondsdead;
                    762:                        if (fp_msg[0])
                    763:                                SV_ClientPrintf(host_client, PRINT_CHAT,
                    764:                                        "FloodProt: %s\n", fp_msg);
                    765:                        else
                    766:                                SV_ClientPrintf(host_client, PRINT_CHAT,
                    767:                                        "FloodProt: You can't talk for %d seconds.\n", fp_secondsdead);
                    768:                        return;
                    769:                }
                    770:                host_client->whensaidhead++;
                    771:                if (host_client->whensaidhead > 9)
                    772:                        host_client->whensaidhead = 0;
                    773:                host_client->whensaid[host_client->whensaidhead] = realtime;
                    774:        }
                    775: 
                    776:        p = Cmd_Args();
                    777: 
                    778:        if (*p == '"')
                    779:        {
                    780:                p++;
                    781:                p[Q_strlen(p)-1] = 0;
                    782:        }
                    783: 
                    784:        Q_strcat(text, p);
                    785:        Q_strcat(text, "\n");
                    786: 
                    787:        Sys_Printf ("%s", text);
                    788: 
                    789:        for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++)
                    790:        {
                    791:                if (client->state != cs_spawned)
                    792:                        continue;
                    793:                if (host_client->spectator && !sv_spectalk.value)
                    794:                        if (!client->spectator)
                    795:                                continue;
                    796: 
                    797:                if (team)
                    798:                {
                    799:                        // the spectator team
                    800:                        if (host_client->spectator) {
                    801:                                if (!client->spectator)
                    802:                                        continue;
                    803:                        } else {
                    804:                                t2 = Info_ValueForKey (client->userinfo, "team");
                    805:                                if (strcmp(t1, t2) || client->spectator)
                    806:                                        continue;       // on different teams
                    807:                        }
                    808:                }
                    809:                SV_ClientPrintf(client, PRINT_CHAT, "%s", text);
                    810:        }
                    811: }
                    812: 
                    813: 
                    814: /*
                    815: ==================
                    816: SV_Say_f
                    817: ==================
                    818: */
                    819: void SV_Say_f(void)
                    820: {
                    821:        SV_Say (false);
                    822: }
                    823: /*
                    824: ==================
                    825: SV_Say_Team_f
                    826: ==================
                    827: */
                    828: void SV_Say_Team_f(void)
                    829: {
                    830:        SV_Say (true);
                    831: }
                    832: 
                    833: 
                    834: 
                    835: //============================================================================
                    836: 
                    837: /*
                    838: =================
                    839: SV_Pings_f
                    840: 
                    841: The client is showing the scoreboard, so send new ping times for all
                    842: clients
                    843: =================
                    844: */
                    845: void SV_Pings_f (void)
                    846: {
                    847:        client_t *client;
                    848:        int             j;
                    849: 
                    850:        for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++)
                    851:        {
                    852:                if (client->state != cs_spawned)
                    853:                        continue;
                    854: 
                    855:                ClientReliableWrite_Begin (host_client, svc_updateping, 4);
                    856:                ClientReliableWrite_Byte (host_client, j);
                    857:                ClientReliableWrite_Short (host_client, SV_CalcPing(client));
                    858:                ClientReliableWrite_Begin (host_client, svc_updatepl, 4);
                    859:                ClientReliableWrite_Byte (host_client, j);
                    860:                ClientReliableWrite_Byte (host_client, client->lossage);
                    861:        }
                    862: }
                    863: 
                    864: 
                    865: 
                    866: /*
                    867: ==================
                    868: SV_Kill_f
                    869: ==================
                    870: */
                    871: void SV_Kill_f (void)
                    872: {
                    873:        if (sv_player->v.health <= 0)
                    874:        {
                    875:                SV_ClientPrintf (host_client, PRINT_HIGH, "Can't suicide -- allready dead!\n");
                    876:                return;
                    877:        }
                    878:        
                    879:        pr_global_struct->time = sv.time;
                    880:        pr_global_struct->self = EDICT_TO_PROG(sv_player);
                    881:        PR_ExecuteProgram (pr_global_struct->ClientKill);
                    882: }
                    883: 
                    884: /*
                    885: ==================
                    886: SV_TogglePause
                    887: ==================
                    888: */
                    889: void SV_TogglePause (const char *msg)
                    890: {
                    891:        int i;
                    892:        client_t *cl;
                    893: 
                    894:        sv.paused ^= 1;
                    895: 
                    896:        if (msg)
                    897:                SV_BroadcastPrintf (PRINT_HIGH, "%s", msg);
                    898: 
                    899:        // send notification to all clients
                    900:        for (i=0, cl = svs.clients ; i<MAX_CLIENTS ; i++, cl++)
                    901:        {
                    902:                if (!cl->state)
                    903:                        continue;
                    904:                ClientReliableWrite_Begin (cl, svc_setpause, 2);
                    905:                ClientReliableWrite_Byte (cl, sv.paused);
                    906:        }
                    907: }
                    908: 
                    909: 
                    910: /*
                    911: ==================
                    912: SV_Pause_f
                    913: ==================
                    914: */
                    915: void SV_Pause_f (void)
                    916: {
                    917:        int i;
                    918:        client_t *cl;
                    919:        char st[sizeof(host_client->name) + 32];
                    920: 
                    921:        if (!pausable.value) {
                    922:                SV_ClientPrintf (host_client, PRINT_HIGH, "Pause not allowed.\n");
                    923:                return;
                    924:        }
                    925: 
                    926:        if (host_client->spectator) {
                    927:                SV_ClientPrintf (host_client, PRINT_HIGH, "Spectators can not pause.\n");
                    928:                return;
                    929:        }
                    930: 
                    931:        if (sv.paused)
                    932:                sprintf (st, "%s paused the game\n", host_client->name);
                    933:        else
                    934:                sprintf (st, "%s unpaused the game\n", host_client->name);
                    935: 
                    936:        SV_TogglePause(st);
                    937: }
                    938: 
                    939: 
                    940: /*
                    941: =================
                    942: SV_Drop_f
                    943: 
                    944: The client is going to disconnect, so remove the connection immediately
                    945: =================
                    946: */
                    947: void SV_Drop_f (void)
                    948: {
                    949:        SV_EndRedirect ();
                    950:        if (!host_client->spectator)
                    951:                SV_BroadcastPrintf (PRINT_HIGH, "%s dropped\n", host_client->name);
                    952:        SV_DropClient (host_client);    
                    953: }
                    954: 
                    955: /*
                    956: =================
                    957: SV_PTrack_f
                    958: 
                    959: Change the bandwidth estimate for a client
                    960: =================
                    961: */
                    962: void SV_PTrack_f (void)
                    963: {
                    964:        int             i;
                    965:        edict_t *ent, *tent;
                    966:        
                    967:        if (!host_client->spectator)
                    968:                return;
                    969: 
                    970:        if (Cmd_Argc() != 2)
                    971:        {
                    972:                // turn off tracking
                    973:                host_client->spec_track = 0;
                    974:                ent = EDICT_NUM(host_client - svs.clients + 1);
                    975:                tent = EDICT_NUM(0);
                    976:                ent->v.goalentity = EDICT_TO_PROG(tent);
                    977:                return;
                    978:        }
                    979:        
                    980:        i = atoi(Cmd_Argv(1));
                    981:        if (i < 0 || i >= MAX_CLIENTS || svs.clients[i].state != cs_spawned ||
                    982:                svs.clients[i].spectator) {
                    983:                SV_ClientPrintf (host_client, PRINT_HIGH, "Invalid client to track\n");
                    984:                host_client->spec_track = 0;
                    985:                ent = EDICT_NUM(host_client - svs.clients + 1);
                    986:                tent = EDICT_NUM(0);
                    987:                ent->v.goalentity = EDICT_TO_PROG(tent);
                    988:                return;
                    989:        }
                    990:        host_client->spec_track = i + 1; // now tracking
                    991: 
                    992:        ent = EDICT_NUM(host_client - svs.clients + 1);
                    993:        tent = EDICT_NUM(i + 1);
                    994:        ent->v.goalentity = EDICT_TO_PROG(tent);
                    995: }
                    996: 
                    997: 
                    998: /*
                    999: =================
                   1000: SV_Rate_f
                   1001: 
                   1002: Change the bandwidth estimate for a client
                   1003: =================
                   1004: */
                   1005: void SV_Rate_f (void)
                   1006: {
                   1007:        int             rate;
                   1008:        
                   1009:        if (Cmd_Argc() != 2)
                   1010:        {
                   1011:                SV_ClientPrintf (host_client, PRINT_HIGH, "Current rate is %i\n",
                   1012:                        (int)(1.0/host_client->netchan.rate + 0.5));
                   1013:                return;
                   1014:        }
                   1015:        
                   1016:        rate = atoi(Cmd_Argv(1));
                   1017:        if (rate < 500)
                   1018:                rate = 500;
                   1019:        if (rate > 10000)
                   1020:                rate = 10000;
                   1021: 
                   1022:        SV_ClientPrintf (host_client, PRINT_HIGH, "Net rate set to %i\n", rate);
                   1023:        host_client->netchan.rate = 1.0/rate;
                   1024: }
                   1025: 
                   1026: 
                   1027: /*
                   1028: =================
                   1029: SV_Msg_f
                   1030: 
                   1031: Change the message level for a client
                   1032: =================
                   1033: */
                   1034: void SV_Msg_f (void)
                   1035: {      
                   1036:        if (Cmd_Argc() != 2)
                   1037:        {
                   1038:                SV_ClientPrintf (host_client, PRINT_HIGH, "Current msg level is %i\n",
                   1039:                        host_client->messagelevel);
                   1040:                return;
                   1041:        }
                   1042:        
                   1043:        host_client->messagelevel = atoi(Cmd_Argv(1));
                   1044: 
                   1045:        SV_ClientPrintf (host_client, PRINT_HIGH, "Msg level set to %i\n", host_client->messagelevel);
                   1046: }
                   1047: 
                   1048: /*
                   1049: ==================
                   1050: SV_SetInfo_f
                   1051: 
                   1052: Allow clients to change userinfo
                   1053: ==================
                   1054: */
                   1055: void SV_SetInfo_f (void)
                   1056: {
                   1057:        int i;
                   1058:        char oldval[MAX_INFO_STRING];
                   1059: 
                   1060: 
                   1061:        if (Cmd_Argc() == 1)
                   1062:        {
                   1063:                Con_Printf ("User info settings:\n");
                   1064:                Info_Print (host_client->userinfo);
                   1065:                return;
                   1066:        }
                   1067: 
                   1068:        if (Cmd_Argc() != 3)
                   1069:        {
                   1070:                Con_Printf ("usage: setinfo [ <key> <value> ]\n");
                   1071:                return;
                   1072:        }
                   1073: 
                   1074:        if (Cmd_Argv(1)[0] == '*')
                   1075:                return;         // don't set priveledged values
                   1076: 
                   1077:        strcpy(oldval, Info_ValueForKey(host_client->userinfo, Cmd_Argv(1)));
                   1078: 
                   1079:        Info_SetValueForKey (host_client->userinfo, Cmd_Argv(1), Cmd_Argv(2), MAX_INFO_STRING);
                   1080: // name is extracted below in ExtractFromUserInfo
                   1081: //     strncpy (host_client->name, Info_ValueForKey (host_client->userinfo, "name")
                   1082: //             , sizeof(host_client->name)-1); 
                   1083: //     SV_FullClientUpdate (host_client, &sv.reliable_datagram);
                   1084: //     host_client->sendinfo = true;
                   1085: 
                   1086:        if (!strcmp(Info_ValueForKey(host_client->userinfo, Cmd_Argv(1)), oldval))
                   1087:                return; // key hasn't changed
                   1088: 
                   1089:        // process any changed values
                   1090:        SV_ExtractFromUserinfo (host_client);
                   1091: 
                   1092:        i = host_client - svs.clients;
                   1093:        MSG_WriteByte (&sv.reliable_datagram, svc_setinfo);
                   1094:        MSG_WriteByte (&sv.reliable_datagram, i);
                   1095:        MSG_WriteString (&sv.reliable_datagram, Cmd_Argv(1));
                   1096:        MSG_WriteString (&sv.reliable_datagram, Info_ValueForKey(host_client->userinfo, Cmd_Argv(1)));
                   1097: }
                   1098: 
                   1099: /*
                   1100: ==================
                   1101: SV_ShowServerinfo_f
                   1102: 
                   1103: Dumps the serverinfo info string
                   1104: ==================
                   1105: */
                   1106: void SV_ShowServerinfo_f (void)
                   1107: {
                   1108:        Info_Print (svs.info);
                   1109: }
                   1110: 
                   1111: void SV_NoSnap_f(void)
                   1112: {
                   1113:        if (*host_client->uploadfn) {
                   1114:                *host_client->uploadfn = 0;
                   1115:                SV_BroadcastPrintf (PRINT_HIGH, "%s refused remote screenshot\n", host_client->name);
                   1116:        }
                   1117: }
                   1118: 
                   1119: typedef struct
                   1120: {
                   1121:        char    *name;
                   1122:        void    (*func) (void);
                   1123: } ucmd_t;
                   1124: 
                   1125: ucmd_t ucmds[] =
                   1126: {
                   1127:        {"new", SV_New_f},
                   1128:        {"modellist", SV_Modellist_f},
                   1129:        {"soundlist", SV_Soundlist_f},
                   1130:        {"prespawn", SV_PreSpawn_f},
                   1131:        {"spawn", SV_Spawn_f},
                   1132:        {"begin", SV_Begin_f},
                   1133: 
                   1134:        {"drop", SV_Drop_f},
                   1135:        {"pings", SV_Pings_f},
                   1136: 
                   1137: // issued by hand at client consoles   
                   1138:        {"rate", SV_Rate_f},
                   1139:        {"kill", SV_Kill_f},
                   1140:        {"pause", SV_Pause_f},
                   1141:        {"msg", SV_Msg_f},
                   1142: 
                   1143:        {"say", SV_Say_f},
                   1144:        {"say_team", SV_Say_Team_f},
                   1145: 
                   1146:        {"setinfo", SV_SetInfo_f},
                   1147: 
                   1148:        {"serverinfo", SV_ShowServerinfo_f},
                   1149: 
                   1150:        {"download", SV_BeginDownload_f},
                   1151:        {"nextdl", SV_NextDownload_f},
                   1152: 
                   1153:        {"ptrack", SV_PTrack_f}, //ZOID - used with autocam
                   1154: 
                   1155:        {"snap", SV_NoSnap_f},
                   1156:        
                   1157:        {NULL, NULL}
                   1158: };
                   1159: 
                   1160: /*
                   1161: ==================
                   1162: SV_ExecuteUserCommand
                   1163: ==================
                   1164: */
                   1165: void SV_ExecuteUserCommand (char *s)
                   1166: {
                   1167:        ucmd_t  *u;
                   1168:        
                   1169:        Cmd_TokenizeString (s);
                   1170:        sv_player = host_client->edict;
                   1171: 
                   1172:        SV_BeginRedirect (RD_CLIENT);
                   1173: 
                   1174:        for (u=ucmds ; u->name ; u++)
                   1175:                if (!strcmp (Cmd_Argv(0), u->name) )
                   1176:                {
                   1177:                        u->func ();
                   1178:                        break;
                   1179:                }
                   1180: 
                   1181:        if (!u->name)
                   1182:                Con_Printf ("Bad user command: %s\n", Cmd_Argv(0));
                   1183: 
                   1184:        SV_EndRedirect ();
                   1185: }
                   1186: 
                   1187: /*
                   1188: ===========================================================================
                   1189: 
                   1190: USER CMD EXECUTION
                   1191: 
                   1192: ===========================================================================
                   1193: */
                   1194: 
                   1195: /*
                   1196: ===============
                   1197: V_CalcRoll
                   1198: 
                   1199: Used by view and sv_user
                   1200: ===============
                   1201: */
                   1202: float V_CalcRoll (vec3_t angles, vec3_t velocity)
                   1203: {
                   1204:        vec3_t  forward, right, up;
                   1205:        float   sign;
                   1206:        float   side;
                   1207:        float   value;
                   1208:        
                   1209:        AngleVectors (angles, forward, right, up);
                   1210:        side = DotProduct (velocity, right);
                   1211:        sign = side < 0 ? -1 : 1;
                   1212:        side = fabs(side);
                   1213:        
                   1214:        value = cl_rollangle.value;
                   1215: 
                   1216:        if (side < cl_rollspeed.value)
                   1217:                side = side * value / cl_rollspeed.value;
                   1218:        else
                   1219:                side = value;
                   1220:        
                   1221:        return side*sign;
                   1222:        
                   1223: }
                   1224: 
                   1225: 
                   1226: 
                   1227: 
                   1228: //============================================================================
                   1229: 
                   1230: vec3_t pmove_mins, pmove_maxs;
                   1231: 
                   1232: /*
                   1233: ====================
                   1234: AddLinksToPmove
                   1235: 
                   1236: ====================
                   1237: */
                   1238: void AddLinksToPmove ( areanode_t *node )
                   1239: {
                   1240:        link_t          *l, *next;
                   1241:        edict_t         *check;
                   1242:        int                     pl;
                   1243:        int                     i;
                   1244:        physent_t       *pe;
                   1245: 
                   1246:        pl = EDICT_TO_PROG(sv_player);
                   1247: 
                   1248:        // touch linked edicts
                   1249:        for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next)
                   1250:        {
                   1251:                next = l->next;
                   1252:                check = EDICT_FROM_AREA(l);
                   1253: 
                   1254:                if (check->v.owner == pl)
                   1255:                        continue;               // player's own missile
                   1256:                if (check->v.solid == SOLID_BSP 
                   1257:                        || check->v.solid == SOLID_BBOX 
                   1258:                        || check->v.solid == SOLID_SLIDEBOX)
                   1259:                {
                   1260:                        if (check == sv_player)
                   1261:                                continue;
                   1262: 
                   1263:                        for (i=0 ; i<3 ; i++)
                   1264:                                if (check->v.absmin[i] > pmove_maxs[i]
                   1265:                                || check->v.absmax[i] < pmove_mins[i])
                   1266:                                        break;
                   1267:                        if (i != 3)
                   1268:                                continue;
                   1269:                        if (pmove.numphysent == MAX_PHYSENTS)
                   1270:                                return;
                   1271:                        pe = &pmove.physents[pmove.numphysent];
                   1272:                        pmove.numphysent++;
                   1273: 
                   1274:                        VectorCopy (check->v.origin, pe->origin);
                   1275:                        pe->info = NUM_FOR_EDICT(check);
                   1276:                        if (check->v.solid == SOLID_BSP)
                   1277:                                pe->model = sv.models[(int)(check->v.modelindex)];
                   1278:                        else
                   1279:                        {
                   1280:                                pe->model = NULL;
                   1281:                                VectorCopy (check->v.mins, pe->mins);
                   1282:                                VectorCopy (check->v.maxs, pe->maxs);
                   1283:                        }
                   1284:                }
                   1285:        }
                   1286:        
                   1287: // recurse down both sides
                   1288:        if (node->axis == -1)
                   1289:                return;
                   1290: 
                   1291:        if ( pmove_maxs[node->axis] > node->dist )
                   1292:                AddLinksToPmove ( node->children[0] );
                   1293:        if ( pmove_mins[node->axis] < node->dist )
                   1294:                AddLinksToPmove ( node->children[1] );
                   1295: }
                   1296: 
                   1297: 
                   1298: /*
                   1299: ================
                   1300: AddAllEntsToPmove
                   1301: 
                   1302: For debugging
                   1303: ================
                   1304: */
                   1305: void AddAllEntsToPmove (void)
                   1306: {
                   1307:        int                     e;
                   1308:        edict_t         *check;
                   1309:        int                     i;
                   1310:        physent_t       *pe;
                   1311:        int                     pl;
                   1312: 
                   1313:        pl = EDICT_TO_PROG(sv_player);
                   1314:        check = NEXT_EDICT(sv.edicts);
                   1315:        for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
                   1316:        {
                   1317:                if (check->free)
                   1318:                        continue;
                   1319:                if (check->v.owner == pl)
                   1320:                        continue;
                   1321:                if (check->v.solid == SOLID_BSP 
                   1322:                        || check->v.solid == SOLID_BBOX 
                   1323:                        || check->v.solid == SOLID_SLIDEBOX)
                   1324:                {
                   1325:                        if (check == sv_player)
                   1326:                                continue;
                   1327: 
                   1328:                        for (i=0 ; i<3 ; i++)
                   1329:                                if (check->v.absmin[i] > pmove_maxs[i]
                   1330:                                || check->v.absmax[i] < pmove_mins[i])
                   1331:                                        break;
                   1332:                        if (i != 3)
                   1333:                                continue;
                   1334:                        pe = &pmove.physents[pmove.numphysent];
                   1335: 
                   1336:                        VectorCopy (check->v.origin, pe->origin);
                   1337:                        pmove.physents[pmove.numphysent].info = e;
                   1338:                        if (check->v.solid == SOLID_BSP)
                   1339:                                pe->model = sv.models[(int)(check->v.modelindex)];
                   1340:                        else
                   1341:                        {
                   1342:                                pe->model = NULL;
                   1343:                                VectorCopy (check->v.mins, pe->mins);
                   1344:                                VectorCopy (check->v.maxs, pe->maxs);
                   1345:                        }
                   1346: 
                   1347:                        if (++pmove.numphysent == MAX_PHYSENTS)
                   1348:                                break;
                   1349:                }
                   1350:        }
                   1351: }
                   1352: 
                   1353: /*
                   1354: ===========
                   1355: SV_PreRunCmd
                   1356: ===========
                   1357: Done before running a player command.  Clears the touch array
                   1358: */
                   1359: byte playertouch[(MAX_EDICTS+7)/8];
                   1360: 
                   1361: void SV_PreRunCmd(void)
                   1362: {
                   1363:        memset(playertouch, 0, sizeof(playertouch));
                   1364: }
                   1365: 
                   1366: /*
                   1367: ===========
                   1368: SV_RunCmd
                   1369: ===========
                   1370: */
                   1371: void SV_RunCmd (usercmd_t *ucmd)
                   1372: {
                   1373:        edict_t         *ent;
                   1374:        int                     i, n;
                   1375:        int                     oldmsec;
                   1376: 
                   1377:        cmd = *ucmd;
                   1378: 
                   1379:        // chop up very long commands
                   1380:        if (cmd.msec > 50)
                   1381:        {
                   1382:                oldmsec = ucmd->msec;
                   1383:                cmd.msec = oldmsec/2;
                   1384:                SV_RunCmd (&cmd);
                   1385:                cmd.msec = oldmsec/2;
                   1386:                cmd.impulse = 0;
                   1387:                SV_RunCmd (&cmd);
                   1388:                return;
                   1389:        }
                   1390: 
                   1391:        if (!sv_player->v.fixangle)
                   1392:                VectorCopy (ucmd->angles, sv_player->v.v_angle);
                   1393: 
                   1394:        sv_player->v.button0 = ucmd->buttons & 1;
                   1395:        sv_player->v.button2 = (ucmd->buttons & 2)>>1;
                   1396:        if (ucmd->impulse)
                   1397:                sv_player->v.impulse = ucmd->impulse;
                   1398: 
                   1399: //
                   1400: // angles
                   1401: // show 1/3 the pitch angle and all the roll angle     
                   1402:        if (sv_player->v.health > 0)
                   1403:        {
                   1404:                if (!sv_player->v.fixangle)
                   1405:                {
                   1406:                        sv_player->v.angles[PITCH] = -sv_player->v.v_angle[PITCH]/3;
                   1407:                        sv_player->v.angles[YAW] = sv_player->v.v_angle[YAW];
                   1408:                }
                   1409:                sv_player->v.angles[ROLL] = 
                   1410:                        V_CalcRoll (sv_player->v.angles, sv_player->v.velocity)*4;
                   1411:        }
                   1412: 
                   1413:        host_frametime = ucmd->msec * 0.001;
                   1414:        if (host_frametime > 0.1)
                   1415:                host_frametime = 0.1;
                   1416: 
                   1417:        if (!host_client->spectator)
                   1418:        {
                   1419:                pr_global_struct->frametime = host_frametime;
                   1420: 
                   1421:                pr_global_struct->time = sv.time;
                   1422:                pr_global_struct->self = EDICT_TO_PROG(sv_player);
                   1423:                PR_ExecuteProgram (pr_global_struct->PlayerPreThink);
                   1424: 
                   1425:                SV_RunThink (sv_player);
                   1426:        }
                   1427: 
                   1428:        for (i=0 ; i<3 ; i++)
                   1429:                pmove.origin[i] = sv_player->v.origin[i] + (sv_player->v.mins[i] - player_mins[i]);
                   1430:        VectorCopy (sv_player->v.velocity, pmove.velocity);
                   1431:        VectorCopy (sv_player->v.v_angle, pmove.angles);
                   1432: 
                   1433:        pmove.spectator = host_client->spectator;
                   1434:        pmove.waterjumptime = sv_player->v.teleport_time;
                   1435:        pmove.numphysent = 1;
                   1436:        pmove.physents[0].model = sv.worldmodel;
                   1437:        pmove.cmd = *ucmd;
                   1438:        pmove.dead = sv_player->v.health <= 0;
                   1439:        pmove.oldbuttons = host_client->oldbuttons;
                   1440: 
                   1441:        movevars.entgravity = host_client->entgravity;
                   1442:        movevars.maxspeed = host_client->maxspeed;
                   1443: 
                   1444:        for (i=0 ; i<3 ; i++)
                   1445:        {
                   1446:                pmove_mins[i] = pmove.origin[i] - 256;
                   1447:                pmove_maxs[i] = pmove.origin[i] + 256;
                   1448:        }
                   1449: #if 1
                   1450:        AddLinksToPmove ( sv_areanodes );
                   1451: #else
                   1452:        AddAllEntsToPmove ();
                   1453: #endif
                   1454: 
                   1455: #if 0
                   1456: {
                   1457:        int before, after;
                   1458: 
                   1459: before = PM_TestPlayerPosition (pmove.origin);
                   1460:        PlayerMove ();
                   1461: after = PM_TestPlayerPosition (pmove.origin);
                   1462: 
                   1463: if (sv_player->v.health > 0 && before && !after )
                   1464:        Con_Printf ("player %s got stuck in playermove!!!!\n", host_client->name);
                   1465: }
                   1466: #else
                   1467:        PlayerMove ();
                   1468: #endif
                   1469: 
                   1470:        host_client->oldbuttons = pmove.oldbuttons;
                   1471:        sv_player->v.teleport_time = pmove.waterjumptime;
                   1472:        sv_player->v.waterlevel = waterlevel;
                   1473:        sv_player->v.watertype = watertype;
                   1474:        if (onground != -1)
                   1475:        {
                   1476:                sv_player->v.flags = (int)sv_player->v.flags | FL_ONGROUND;
                   1477:                sv_player->v.groundentity = EDICT_TO_PROG(EDICT_NUM(pmove.physents[onground].info));
                   1478:        }
                   1479:        else
                   1480:                sv_player->v.flags = (int)sv_player->v.flags & ~FL_ONGROUND;
                   1481:        for (i=0 ; i<3 ; i++)
                   1482:                sv_player->v.origin[i] = pmove.origin[i] - (sv_player->v.mins[i] - player_mins[i]);
                   1483: 
                   1484: #if 0
                   1485:        // truncate velocity the same way the net protocol will
                   1486:        for (i=0 ; i<3 ; i++)
                   1487:                sv_player->v.velocity[i] = (int)pmove.velocity[i];
                   1488: #else
                   1489:        VectorCopy (pmove.velocity, sv_player->v.velocity);
                   1490: #endif
                   1491: 
                   1492:        VectorCopy (pmove.angles, sv_player->v.v_angle);
                   1493: 
                   1494:        if (!host_client->spectator)
                   1495:        {
                   1496:                // link into place and touch triggers
                   1497:                SV_LinkEdict (sv_player, true);
                   1498: 
                   1499:                // touch other objects
                   1500:                for (i=0 ; i<pmove.numtouch ; i++)
                   1501:                {
                   1502:                        n = pmove.physents[pmove.touchindex[i]].info;
                   1503:                        ent = EDICT_NUM(n);
                   1504:                        if (!ent->v.touch || (playertouch[n/8]&(1<<(n%8))))
                   1505:                                continue;
                   1506:                        pr_global_struct->self = EDICT_TO_PROG(ent);
                   1507:                        pr_global_struct->other = EDICT_TO_PROG(sv_player);
                   1508:                        PR_ExecuteProgram (ent->v.touch);
                   1509:                        playertouch[n/8] |= 1 << (n%8);
                   1510:                }
                   1511:        }
                   1512: }
                   1513: 
                   1514: /*
                   1515: ===========
                   1516: SV_PostRunCmd
                   1517: ===========
                   1518: Done after running a player command.
                   1519: */
                   1520: void SV_PostRunCmd(void)
                   1521: {
                   1522:        // run post-think
                   1523: 
                   1524:        if (!host_client->spectator) {
                   1525:                pr_global_struct->time = sv.time;
                   1526:                pr_global_struct->self = EDICT_TO_PROG(sv_player);
                   1527:                PR_ExecuteProgram (pr_global_struct->PlayerPostThink);
                   1528:                SV_RunNewmis ();
                   1529:        } else if (SpectatorThink) {
                   1530:                pr_global_struct->time = sv.time;
                   1531:                pr_global_struct->self = EDICT_TO_PROG(sv_player);
                   1532:                PR_ExecuteProgram (SpectatorThink);
                   1533:        }
                   1534: }
                   1535: 
                   1536: 
                   1537: /*
                   1538: ===================
                   1539: SV_ExecuteClientMessage
                   1540: 
                   1541: The current net_message is parsed for the given client
                   1542: ===================
                   1543: */
                   1544: void SV_ExecuteClientMessage (client_t *cl)
                   1545: {
                   1546:        int             c;
                   1547:        char    *s;
                   1548:        usercmd_t       oldest, oldcmd, newcmd;
                   1549:        client_frame_t  *frame;
                   1550:        vec3_t o;
                   1551:        qboolean        move_issued = false; //only allow one move command
                   1552:        int             checksumIndex;
                   1553:        byte    checksum, calculatedChecksum;
                   1554:        int             seq_hash;
                   1555: 
                   1556:        // calc ping time
                   1557:        frame = &cl->frames[cl->netchan.incoming_acknowledged & UPDATE_MASK];
                   1558:        frame->ping_time = realtime - frame->senttime;
                   1559: 
                   1560:        // make sure the reply sequence number matches the incoming
                   1561:        // sequence number 
                   1562:        if (cl->netchan.incoming_sequence >= cl->netchan.outgoing_sequence)
                   1563:                cl->netchan.outgoing_sequence = cl->netchan.incoming_sequence;
                   1564:        else
                   1565:                cl->send_message = false;       // don't reply, sequences have slipped          
                   1566: 
                   1567:        // save time for ping calculations
                   1568:        cl->frames[cl->netchan.outgoing_sequence & UPDATE_MASK].senttime = realtime;
                   1569:        cl->frames[cl->netchan.outgoing_sequence & UPDATE_MASK].ping_time = -1;
                   1570: 
                   1571:        host_client = cl;
                   1572:        sv_player = host_client->edict;
                   1573: 
                   1574: //     seq_hash = (cl->netchan.incoming_sequence & 0xffff) ; // ^ QW_CHECK_HASH;
                   1575:        seq_hash = cl->netchan.incoming_sequence;
                   1576:        
                   1577:        // mark time so clients will know how much to predict
                   1578:        // other players
                   1579:        cl->localtime = sv.time;
                   1580:        cl->delta_sequence = -1;        // no delta unless requested
                   1581:        while (1)
                   1582:        {
                   1583:                if (msg_badread)
                   1584:                {
                   1585:                        Con_Printf ("SV_ReadClientMessage: badread\n");
                   1586:                        SV_DropClient (cl);
                   1587:                        return;
                   1588:                }       
                   1589: 
                   1590:                c = MSG_ReadByte ();
                   1591:                if (c == -1)
                   1592:                        break;
                   1593:                                
                   1594:                switch (c)
                   1595:                {
                   1596:                default:
                   1597:                        Con_Printf ("SV_ReadClientMessage: unknown command char\n");
                   1598:                        SV_DropClient (cl);
                   1599:                        return;
                   1600:                                                
                   1601:                case clc_nop:
                   1602:                        break;
                   1603: 
                   1604:                case clc_delta:
                   1605:                        cl->delta_sequence = MSG_ReadByte ();
                   1606:                        break;
                   1607: 
                   1608:                case clc_move:
                   1609:                        if (move_issued)
                   1610:                                return;         // someone is trying to cheat...
                   1611: 
                   1612:                        move_issued = true;
                   1613: 
                   1614:                        checksumIndex = MSG_GetReadCount();
                   1615:                        checksum = (byte)MSG_ReadByte ();
                   1616: 
                   1617:                        // read loss percentage
                   1618:                        cl->lossage = MSG_ReadByte();
                   1619: 
                   1620:                        MSG_ReadDeltaUsercmd (&nullcmd, &oldest);
                   1621:                        MSG_ReadDeltaUsercmd (&oldest, &oldcmd);
                   1622:                        MSG_ReadDeltaUsercmd (&oldcmd, &newcmd);
                   1623: 
                   1624:                        if ( cl->state != cs_spawned )
                   1625:                                break;
                   1626: 
                   1627:                        // if the checksum fails, ignore the rest of the packet
                   1628:                        calculatedChecksum = COM_BlockSequenceCRCByte(
                   1629:                                net_message.data + checksumIndex + 1,
                   1630:                                MSG_GetReadCount() - checksumIndex - 1,
                   1631:                                seq_hash);
                   1632: 
                   1633:                        if (calculatedChecksum != checksum)
                   1634:                        {
                   1635:                                Con_DPrintf ("Failed command checksum for %s(%d) (%d != %d)\n", 
                   1636:                                        cl->name, cl->netchan.incoming_sequence, checksum, calculatedChecksum);
                   1637:                                return;
                   1638:                        }
                   1639: 
                   1640:                        if (!sv.paused) {
                   1641:                                SV_PreRunCmd();
                   1642: 
                   1643:                                if (net_drop < 20)
                   1644:                                {
                   1645:                                        while (net_drop > 2)
                   1646:                                        {
                   1647:                                                SV_RunCmd (&cl->lastcmd);
                   1648:                                                net_drop--;
                   1649:                                        }
                   1650:                                        if (net_drop > 1)
                   1651:                                                SV_RunCmd (&oldest);
                   1652:                                        if (net_drop > 0)
                   1653:                                                SV_RunCmd (&oldcmd);
                   1654:                                }
                   1655:                                SV_RunCmd (&newcmd);
                   1656: 
                   1657:                                SV_PostRunCmd();
                   1658:                        }
                   1659: 
                   1660:                        cl->lastcmd = newcmd;
                   1661:                        cl->lastcmd.buttons = 0; // avoid multiple fires on lag
                   1662:                        break;
                   1663: 
                   1664: 
                   1665:                case clc_stringcmd:     
                   1666:                        s = MSG_ReadString ();
                   1667:                        SV_ExecuteUserCommand (s);
                   1668:                        break;
                   1669: 
                   1670:                case clc_tmove:
                   1671:                        o[0] = MSG_ReadCoord();
                   1672:                        o[1] = MSG_ReadCoord();
                   1673:                        o[2] = MSG_ReadCoord();
                   1674:                        // only allowed by spectators
                   1675:                        if (host_client->spectator) {
                   1676:                                VectorCopy(o, sv_player->v.origin);
                   1677:                                SV_LinkEdict(sv_player, false);
                   1678:                        }
                   1679:                        break;
                   1680: 
                   1681:                case clc_upload:
                   1682:                        SV_NextUpload();
                   1683:                        break;
                   1684: 
                   1685:                }
                   1686:        }
                   1687: }
                   1688: 
                   1689: /*
                   1690: ==============
                   1691: SV_UserInit
                   1692: ==============
                   1693: */
                   1694: void SV_UserInit (void)
                   1695: {
                   1696:        Cvar_RegisterVariable (&cl_rollspeed);
                   1697:        Cvar_RegisterVariable (&cl_rollangle);
                   1698:        Cvar_RegisterVariable (&sv_spectalk);
                   1699:        Cvar_RegisterVariable (&sv_mapcheck);
                   1700: }
                   1701: 
                   1702: 

unix.superglobalmegacorp.com

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