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

1.1       root        1: 
                      2: #include "server.h"
                      3: 
                      4: /*
                      5: ===============================================================================
                      6: 
                      7: OPERATOR CONSOLE ONLY COMMANDS
                      8: 
                      9: These commands can only be entered from stdin or by a remote operator datagram
                     10: ===============================================================================
                     11: */
                     12: 
                     13: /*
                     14: ====================
                     15: SV_SetMaster_f
                     16: 
                     17: Specify a list of master servers
                     18: ====================
                     19: */
                     20: void SV_SetMaster_f (void)
                     21: {
                     22:        int             i, slot;
                     23: 
                     24:        // only dedicated servers send heartbeats
                     25:        if (!dedicated->value)
                     26:        {
                     27:                Com_Printf ("Only dedicated servers use masters.\n");
                     28:                return;
                     29:        }
                     30: 
                     31:        // make sure the server is listed public
                     32:        Cvar_Set ("public", "1");
                     33: 
                     34:        for (i=1 ; i<MAX_MASTERS ; i++)
                     35:                memset (&master_adr[i], 0, sizeof(master_adr[i]));
                     36: 
                     37:        slot = 1;               // slot 0 will always contain the id master
                     38:        for (i=1 ; i<Cmd_Argc() ; i++)
                     39:        {
                     40:                if (slot == MAX_MASTERS)
                     41:                        break;
                     42: 
                     43:                if (!NET_StringToAdr (Cmd_Argv(i), &master_adr[i]))
                     44:                {
                     45:                        Com_Printf ("Bad address: %s\n", Cmd_Argv(i));
                     46:                        continue;
                     47:                }
                     48:                if (master_adr[slot].port == 0)
                     49:                        master_adr[slot].port = BigShort (PORT_MASTER);
                     50: 
                     51:                Com_Printf ("Master server at %s\n", NET_AdrToString (master_adr[slot]));
                     52: 
                     53:                Com_Printf ("Sending a ping.\n");
                     54: 
                     55:                Netchan_OutOfBandPrint (NS_SERVER, master_adr[slot], "ping");
                     56: 
                     57:                slot++;
                     58:        }
                     59: 
                     60:        svs.last_heartbeat = -9999999;
                     61: }
                     62: 
                     63: 
                     64: 
                     65: /*
                     66: ==================
                     67: SV_SetPlayer
                     68: 
                     69: Sets sv_client and sv_player to the player with idnum Cmd_Argv(1)
                     70: ==================
                     71: */
                     72: qboolean SV_SetPlayer (void)
                     73: {
                     74:        client_t        *cl;
                     75:        int                     i;
                     76:        int                     idnum;
                     77:        char            *s;
                     78: 
                     79:        if (Cmd_Argc() < 2)
                     80:                return false;
                     81: 
                     82:        s = Cmd_Argv(1);
                     83: 
                     84:        // numeric values are just slot numbers
                     85:        if (s[0] >= '0' && s[0] <= '9')
                     86:        {
                     87:                idnum = atoi(Cmd_Argv(1));
                     88:                if (idnum < 0 || idnum >= maxclients->value)
                     89:                {
                     90:                        Com_Printf ("Bad client slot: %i\n", idnum);
                     91:                        return false;
                     92:                }
                     93: 
                     94:                sv_client = &svs.clients[idnum];
                     95:                sv_player = sv_client->edict;
                     96:                if (!sv_client->state)
                     97:                {
                     98:                        Com_Printf ("Clinet %i is not active\n", idnum);
                     99:                        return false;
                    100:                }
                    101:                return true;
                    102:        }
                    103: 
                    104:        // check for a name match
                    105:        for (i=0,cl=svs.clients ; i<maxclients->value; i++,cl++)
                    106:        {
                    107:                if (!cl->state)
                    108:                        continue;
                    109:                if (!strcmp(cl->name, s))
                    110:                {
                    111:                        sv_client = cl;
                    112:                        sv_player = sv_client->edict;
                    113:                        return true;
                    114:                }
                    115:        }
                    116: 
                    117:        Com_Printf ("Userid %s is not on the server\n", s);
                    118:        return false;
                    119: }
                    120: 
                    121: 
                    122: /*
                    123: ===============================================================================
                    124: 
                    125: SAVEGAME FILES
                    126: 
                    127: ===============================================================================
                    128: */
                    129: 
                    130: /*
                    131: =====================
                    132: SV_WipeSavegame
                    133: 
                    134: Delete save/<XXX>/
                    135: =====================
                    136: */
                    137: void SV_WipeSavegame (char *savename)
                    138: {
                    139:        char    name[MAX_OSPATH];
                    140:        char    *s;
                    141: 
                    142:        Com_sprintf (name, sizeof(name), "%s/save/%s/server.ssv", FS_Gamedir (), savename);
                    143:        remove (name);
                    144:        Com_sprintf (name, sizeof(name), "%s/save/%s/game.ssv", FS_Gamedir (), savename);
                    145:        remove (name);
                    146: 
                    147:        Com_sprintf (name, sizeof(name), "%s/save/%s/*.sav", FS_Gamedir (), savename);
                    148:        s = Sys_FindFirst( name, 0, 0 );
                    149:        while (s)
                    150:        {
                    151:                remove (s);
                    152:                s = Sys_FindNext( 0, 0 );
                    153:        }
                    154:        Sys_FindClose ();
                    155:        Com_sprintf (name, sizeof(name), "%s/save/%s/*.sv2", FS_Gamedir (), savename);
                    156:        s = Sys_FindFirst(name, 0, 0 );
                    157:        while (s)
                    158:        {
                    159:                remove (s);
                    160:                s = Sys_FindNext( 0, 0 );
                    161:        }
                    162:        Sys_FindClose ();
                    163: }
                    164: 
                    165: 
                    166: /*
                    167: ================
                    168: CopyFile
                    169: ================
                    170: */
                    171: void CopyFile (char *src, char *dst)
                    172: {
                    173:        FILE    *f1, *f2;
                    174:        int             l;
                    175:        byte    buffer[65536];
                    176: 
                    177:        Com_DPrintf ("CopyFile (%s, %s)\n", src, dst);
                    178: 
                    179:        f1 = fopen (src, "rb");
                    180:        if (!f1)
                    181:                return;
                    182:        f2 = fopen (dst, "wb");
                    183:        if (!f2)
                    184:        {
                    185:                fclose (f1);
                    186:                return;
                    187:        }
                    188: 
                    189:        while (1)
                    190:        {
                    191:                l = fread (buffer, 1, sizeof(buffer), f1);
                    192:                if (!l)
                    193:                        break;
                    194:                fwrite (buffer, 1, l, f2);
                    195:        }
                    196: 
                    197:        fclose (f1);
                    198:        fclose (f2);
                    199: }
                    200: 
                    201: 
                    202: /*
                    203: ================
                    204: SV_CopySaveGame
                    205: ================
                    206: */
                    207: void SV_CopySaveGame (char *src, char *dst)
                    208: {
                    209:        char    name[MAX_OSPATH], name2[MAX_OSPATH];
                    210:        int             l, len;
                    211:        char    *found;
                    212: 
                    213:        SV_WipeSavegame (dst);
                    214: 
                    215:        // copy the savegame over
                    216:        Com_sprintf (name, sizeof(name), "%s/save/%s/server.ssv", FS_Gamedir(), src);
                    217:        Com_sprintf (name2, sizeof(name2), "%s/save/%s/server.ssv", FS_Gamedir(), dst);
                    218:        FS_CreatePath (name2);
                    219:        CopyFile (name, name2);
                    220: 
                    221:        Com_sprintf (name, sizeof(name), "%s/save/%s/game.ssv", FS_Gamedir(), src);
                    222:        Com_sprintf (name2, sizeof(name2), "%s/save/%s/game.ssv", FS_Gamedir(), dst);
                    223:        CopyFile (name, name2);
                    224: 
                    225:        Com_sprintf (name, sizeof(name), "%s/save/%s/", FS_Gamedir(), src);
                    226:        len = strlen(name);
                    227:        Com_sprintf (name, sizeof(name), "%s/save/%s/*.sav", FS_Gamedir(), src);
                    228:        found = Sys_FindFirst(name, 0, 0 );
                    229:        while (found)
                    230:        {
                    231:                strcpy (name+len, found+len);
                    232: 
                    233:                Com_sprintf (name2, sizeof(name2), "%s/save/%s/%s", FS_Gamedir(), dst, found+len);
                    234:                CopyFile (name, name2);
                    235: 
                    236:                // change sav to sv2
                    237:                l = strlen(name);
                    238:                strcpy (name+l-3, "sv2");
                    239:                l = strlen(name2);
                    240:                strcpy (name2+l-3, "sv2");
                    241:                CopyFile (name, name2);
                    242: 
                    243:                found = Sys_FindNext( 0, 0 );
                    244:        }
                    245:        Sys_FindClose ();
                    246: }
                    247: 
                    248: 
                    249: /*
                    250: ==============
                    251: SV_WriteLevelFile
                    252: 
                    253: ==============
                    254: */
                    255: void SV_WriteLevelFile (void)
                    256: {
                    257:        char    name[MAX_OSPATH];
                    258:        FILE    *f;
                    259: 
                    260:        Com_sprintf (name, sizeof(name), "%s/save/current/%s.sv2", FS_Gamedir(), sv.name);
                    261:        f = fopen(name, "wb");
                    262:        if (!f)
                    263:        {
                    264:                Com_Printf ("Failed to open %s\n", name);
                    265:                return;
                    266:        }
                    267:        fwrite (sv.configstrings, sizeof(sv.configstrings), 1, f);
                    268:        CM_WritePortalState (f);
                    269:        fclose (f);
                    270: 
                    271:        Com_sprintf (name, sizeof(name), "%s/save/current/%s.sav", FS_Gamedir(), sv.name);
                    272:        ge->WriteLevel (name);
                    273: }
                    274: 
                    275: /*
                    276: ==============
                    277: SV_ReadLevelFile
                    278: 
                    279: ==============
                    280: */
                    281: void SV_ReadLevelFile (void)
                    282: {
                    283:        char    name[MAX_OSPATH];
                    284:        FILE    *f;
                    285: 
                    286:        Com_sprintf (name, sizeof(name), "%s/save/current/%s.sv2", FS_Gamedir(), sv.name);
                    287:        f = fopen(name, "rb");
                    288:        if (!f)
                    289:        {
                    290:                Com_Printf ("Failed to open %s\n", name);
                    291:                return;
                    292:        }
                    293:        FS_Read (sv.configstrings, sizeof(sv.configstrings), f);
                    294:        CM_ReadPortalState (f);
                    295:        fclose (f);
                    296: 
                    297:        Com_sprintf (name, sizeof(name), "%s/save/current/%s.sav", FS_Gamedir(), sv.name);
                    298:        ge->ReadLevel (name);
                    299: }
                    300: 
                    301: /*
                    302: ==============
                    303: SV_WriteServerFile
                    304: 
                    305: ==============
                    306: */
                    307: void SV_WriteServerFile (qboolean autosave)
                    308: {
                    309:        FILE    *f;
                    310:        cvar_t  *var;
                    311:        char    name[MAX_OSPATH], string[128];
                    312:        char    comment[32];
                    313:        time_t  aclock;
                    314:        struct tm       *newtime;
                    315: 
                    316:        Com_sprintf (name, sizeof(name), "%s/save/current/server.ssv", FS_Gamedir());
                    317:        f = fopen (name, "wb");
                    318:        if (!f)
                    319:        {
                    320:                Com_Printf ("Couldn't write %s\n", name);
                    321:                return;
                    322:        }
                    323:        // write the comment field
                    324:        memset (comment, 0, sizeof(comment));
                    325: 
                    326:        if (!autosave)
                    327:        {
                    328:                time (&aclock);
                    329:                newtime = localtime (&aclock);
                    330:                Com_sprintf (comment,sizeof(comment), "%2i:%i%i %2i/%2i  ", newtime->tm_hour
                    331:                        , newtime->tm_min/10, newtime->tm_min%10,
                    332:                        newtime->tm_mon+1, newtime->tm_mday);
                    333:                strncat (comment, sv.configstrings[CS_NAME], sizeof(comment)-1-strlen(comment) );
                    334:        }
                    335:        else
                    336:        {       // autosaved
                    337:                Com_sprintf (comment, sizeof(comment), "ENTERING %s", sv.configstrings[CS_NAME]);
                    338:        }
                    339: 
                    340:        fwrite (comment, 1, sizeof(comment), f);
                    341: 
                    342:        // write the mapcmd
                    343:        fwrite (svs.mapcmd, 1, sizeof(svs.mapcmd), f);
                    344: 
                    345:        // write all CVAR_LATCH cvars
                    346:        // these will be things like coop, skill, deathmatch, etc
                    347:        for (var = cvar_vars ; var ; var=var->next)
                    348:        {
                    349:                if (!(var->flags & CVAR_LATCH))
                    350:                        continue;
                    351:                if (strlen(var->name) >= sizeof(name)-1
                    352:                        || strlen(var->string) >= sizeof(string)-1)
                    353:                {
                    354:                        Com_Printf ("Cvar too long: %s = %s\n", var->name, var->string);
                    355:                        continue;
                    356:                }
                    357:                memset (name, 0, sizeof(name));
                    358:                memset (string, 0, sizeof(string));
                    359:                strcpy (name, var->name);
                    360:                strcpy (string, var->string);
                    361:                fwrite (name, 1, sizeof(name), f);
                    362:                fwrite (string, 1, sizeof(string), f);
                    363:        }
                    364: 
                    365:        fclose (f);
                    366: 
                    367:        // write game state
                    368:        Com_sprintf (name, sizeof(name), "%s/save/current/game.ssv", FS_Gamedir());
                    369:        ge->WriteGame (name, autosave);
                    370: }
                    371: 
                    372: /*
                    373: ==============
                    374: SV_ReadServerFile
                    375: 
                    376: ==============
                    377: */
                    378: void SV_ReadServerFile (void)
                    379: {
                    380:        FILE    *f;
                    381:        char    name[MAX_OSPATH], string[128];
                    382:        char    comment[32];
                    383:        char    mapcmd[MAX_TOKEN_CHARS];
                    384: 
                    385:        Com_sprintf (name, sizeof(name), "%s/save/current/server.ssv", FS_Gamedir());
                    386:        f = fopen (name, "rb");
                    387:        if (!f)
                    388:        {
                    389:                Com_Printf ("Couldn't read %s\n", name);
                    390:                return;
                    391:        }
                    392:        // read the comment field
                    393:        FS_Read (comment, sizeof(comment), f);
                    394: 
                    395:        // read the mapcmd
                    396:        FS_Read (mapcmd, sizeof(mapcmd), f);
                    397: 
                    398:        // read all CVAR_LATCH cvars
                    399:        // these will be things like coop, skill, deathmatch, etc
                    400:        while (1)
                    401:        {
                    402:                if (!fread (name, 1, sizeof(name), f))
                    403:                        break;
                    404:                FS_Read (string, sizeof(string), f);
                    405:                Com_DPrintf ("Set %s = %s\n", name, string);
                    406:                Cvar_ForceSet (name, string);
                    407:        }
                    408: 
                    409:        fclose (f);
                    410: 
                    411:        // start a new game fresh with new cvars
                    412:        SV_InitGame ();
                    413: 
                    414:        strcpy (svs.mapcmd, mapcmd);
                    415: 
                    416:        // read game state
                    417:        Com_sprintf (name, sizeof(name), "%s/save/current/game.ssv", FS_Gamedir());
                    418:        ge->ReadGame (name);
                    419: }
                    420: 
                    421: 
                    422: //=========================================================
                    423: 
                    424: 
                    425: 
                    426: 
                    427: /*
                    428: ==================
                    429: SV_DemoMap_f
                    430: 
                    431: Puts the server in demo mode on a specific map/cinematic
                    432: ==================
                    433: */
                    434: void SV_DemoMap_f (void)
                    435: {
                    436:        SV_Map (true, Cmd_Argv(1), false );
                    437: }
                    438: 
                    439: /*
                    440: ==================
                    441: SV_GameMap_f
                    442: 
                    443: Saves the state of the map just being exited and goes to a new map.
                    444: 
                    445: If the initial character of the map string is '*', the next map is
                    446: in a new unit, so the current savegame directory is cleared of
                    447: map files.
                    448: 
                    449: Example:
                    450: 
                    451: *inter.cin+jail
                    452: 
                    453: Clears the archived maps, plays the inter.cin cinematic, then
                    454: goes to map jail.bsp.
                    455: ==================
                    456: */
                    457: void SV_GameMap_f (void)
                    458: {
                    459:        char            *map;
                    460:        int                     i;
                    461:        client_t        *cl;
                    462:        qboolean        *savedInuse;
                    463: 
                    464:        if (Cmd_Argc() != 2)
                    465:        {
                    466:                Com_Printf ("USAGE: gamemap <map>\n");
                    467:                return;
                    468:        }
                    469: 
                    470:        FS_CreatePath (va("%s/save/current/", FS_Gamedir()));
                    471: 
                    472:        // check for clearing the current savegame
                    473:        map = Cmd_Argv(1);
                    474:        if (map[0] == '*')
                    475:        {
                    476:                // wipe all the *.sav files
                    477:                SV_WipeSavegame ("current");
                    478:        }
                    479:        else
                    480:        {       // save the map just exited
                    481:                if (sv.state == ss_game)
                    482:                {
                    483:                        // clear all the client inuse flags before saving so that
                    484:                        // when the level is re-entered, the clients will spawn
                    485:                        // at spawn points instead of occupying body shells
                    486:                        savedInuse = malloc(maxclients->value * sizeof(qboolean));
                    487:                        for (i=0,cl=svs.clients ; i<maxclients->value; i++,cl++)
                    488:                        {
                    489:                                savedInuse[i] = cl->edict->inuse;
                    490:                                cl->edict->inuse = false;
                    491:                        }
                    492: 
                    493:                        SV_WriteLevelFile ();
                    494: 
                    495:                        // we must restore these for clients to transfer over correctly
                    496:                        for (i=0,cl=svs.clients ; i<maxclients->value; i++,cl++)
                    497:                                cl->edict->inuse = savedInuse[i];
                    498:                        free (savedInuse);
                    499:                }
                    500:        }
                    501: 
                    502:        // start up the next map
                    503:        SV_Map (false, Cmd_Argv(1), false );
                    504: 
                    505:        // archive server state
                    506:        strncpy (svs.mapcmd, Cmd_Argv(1), sizeof(svs.mapcmd)-1);
                    507: 
                    508:        // copy off the level to the autosave slot
                    509:        if (!dedicated->value)
                    510:        {
                    511:                SV_WriteServerFile (true);
                    512:                SV_CopySaveGame ("current", "save0");
                    513:        }
                    514: }
                    515: 
                    516: /*
                    517: ==================
                    518: SV_Map_f
                    519: 
                    520: Goes directly to a given map without any savegame archiving.
                    521: For development work
                    522: ==================
                    523: */
                    524: void SV_Map_f (void)
                    525: {
                    526:        char    *map;
                    527:        char    expanded[MAX_QPATH];
                    528: 
                    529:        // if not a pcx, demo, or cinematic, check to make sure the level exists
                    530:        map = Cmd_Argv(1);
                    531:        if (!strstr (map, "."))
                    532:        {
                    533:                Com_sprintf (expanded, sizeof(expanded), "maps/%s.bsp", map);
                    534:                if (FS_LoadFile (expanded, NULL) == -1)
                    535:                {
                    536:                        Com_Printf ("Can't find %s\n", expanded);
                    537:                        return;
                    538:                }
                    539:        }
                    540: 
                    541:        sv.state = ss_dead;             // don't save current level when changing
                    542:        SV_WipeSavegame("current");
                    543:        SV_GameMap_f ();
                    544: }
                    545: 
                    546: /*
                    547: =====================================================================
                    548: 
                    549:   SAVEGAMES
                    550: 
                    551: =====================================================================
                    552: */
                    553: 
                    554: 
                    555: /*
                    556: ==============
                    557: SV_Loadgame_f
                    558: 
                    559: ==============
                    560: */
                    561: void SV_Loadgame_f (void)
                    562: {
                    563:        char    name[MAX_OSPATH];
                    564:        FILE    *f;
                    565:        char    *dir;
                    566: 
                    567:        if (Cmd_Argc() != 2)
                    568:        {
                    569:                Com_Printf ("USAGE: loadgame <directory>\n");
                    570:                return;
                    571:        }
                    572: 
                    573:        Com_Printf ("Loading game...\n");
                    574: 
                    575:        dir = Cmd_Argv(1);
                    576:        if (strstr (dir, "..") || strstr (dir, "/") || strstr (dir, "\\") )
                    577:        {
                    578:                Com_Printf ("Bad savedir.\n");
                    579:        }
                    580: 
                    581:        // make sure the server.ssv file exists
                    582:        Com_sprintf (name, sizeof(name), "%s/save/%s/server.ssv", FS_Gamedir(), Cmd_Argv(1));
                    583:        f = fopen (name, "rb");
                    584:        if (!f)
                    585:        {
                    586:                Com_Printf ("No such savegame: %s\n", name);
                    587:                return;
                    588:        }
                    589:        fclose (f);
                    590: 
                    591:        SV_CopySaveGame (Cmd_Argv(1), "current");
                    592: 
                    593:        SV_ReadServerFile ();
                    594: 
                    595:        // go to the map
                    596:        sv.state = ss_dead;             // don't save current level when changing
                    597:        SV_Map (false, svs.mapcmd, true);
                    598: }
                    599: 
                    600: 
                    601: 
                    602: /*
                    603: ==============
                    604: SV_Savegame_f
                    605: 
                    606: ==============
                    607: */
                    608: void SV_Savegame_f (void)
                    609: {
                    610:        char    *dir;
                    611: 
                    612:        if (sv.state != ss_game)
                    613:        {
                    614:                Com_Printf ("You must be in a game to save.\n");
                    615:                return;
                    616:        }
                    617: 
                    618:        if (Cmd_Argc() != 2)
                    619:        {
                    620:                Com_Printf ("USAGE: savegame <directory>\n");
                    621:                return;
                    622:        }
                    623: 
                    624:        if (Cvar_VariableValue("deathmatch"))
                    625:        {
                    626:                Com_Printf ("Can't savegame in a deathmatch\n");
                    627:                return;
                    628:        }
                    629: 
                    630:        if (!strcmp (Cmd_Argv(1), "current"))
                    631:        {
                    632:                Com_Printf ("Can't save to 'current'\n");
                    633:                return;
                    634:        }
                    635: 
                    636:        if (maxclients->value == 1 && svs.clients[0].edict->client->ps.stats[STAT_HEALTH] <= 0)
                    637:        {
                    638:                Com_Printf ("\nCan't savegame while dead!\n");
                    639:                return;
                    640:        }
                    641: 
                    642:        dir = Cmd_Argv(1);
                    643:        if (strstr (dir, "..") || strstr (dir, "/") || strstr (dir, "\\") )
                    644:        {
                    645:                Com_Printf ("Bad savedir.\n");
                    646:        }
                    647: 
                    648:        Com_Printf ("Saving game...\n");
                    649: 
                    650:        // archive current level, including all client edicts.
                    651:        // when the level is reloaded, they will be shells awaiting
                    652:        // a connecting client
                    653:        SV_WriteLevelFile ();
                    654: 
                    655:        // save server state
                    656:        SV_WriteServerFile (false);
                    657: 
                    658:        // copy it off
                    659:        SV_CopySaveGame ("current", dir);
                    660: 
                    661:        Com_Printf ("Done.\n");
                    662: }
                    663: 
                    664: //===============================================================
                    665: 
                    666: /*
                    667: ==================
                    668: SV_Kick_f
                    669: 
                    670: Kick a user off of the server
                    671: ==================
                    672: */
                    673: void SV_Kick_f (void)
                    674: {
                    675:        if (!svs.initialized)
                    676:        {
                    677:                Com_Printf ("No server running.\n");
                    678:                return;
                    679:        }
                    680: 
                    681:        if (Cmd_Argc() != 2)
                    682:        {
                    683:                Com_Printf ("Usage: kick <userid>\n");
                    684:                return;
                    685:        }
                    686: 
                    687:        if (!SV_SetPlayer ())
                    688:                return;
                    689: 
                    690:        SV_BroadcastPrintf (PRINT_HIGH, "%s was kicked\n", sv_client->name);
                    691:        // print directly, because the dropped client won't get the
                    692:        // SV_BroadcastPrintf message
                    693:        SV_ClientPrintf (sv_client, PRINT_HIGH, "You were kicked from the game\n");
                    694:        SV_DropClient (sv_client);
                    695:        sv_client->lastmessage = svs.realtime;  // min case there is a funny zombie
                    696: }
                    697: 
                    698: 
                    699: /*
                    700: ================
                    701: SV_Status_f
                    702: ================
                    703: */
                    704: void SV_Status_f (void)
                    705: {
                    706:        int                     i, j, l;
                    707:        client_t        *cl;
                    708:        char            *s;
                    709:        int                     ping;
                    710:        if (!svs.clients)
                    711:        {
                    712:                Com_Printf ("No server running.\n");
                    713:                return;
                    714:        }
                    715:        Com_Printf ("map              : %s\n", sv.name);
                    716: 
                    717:        Com_Printf ("num score ping name            lastmsg address               qport \n");
                    718:        Com_Printf ("--- ----- ---- --------------- ------- --------------------- ------\n");
                    719:        for (i=0,cl=svs.clients ; i<maxclients->value; i++,cl++)
                    720:        {
                    721:                if (!cl->state)
                    722:                        continue;
                    723:                Com_Printf ("%3i ", i);
                    724:                Com_Printf ("%5i ", cl->edict->client->ps.stats[STAT_FRAGS]);
                    725: 
                    726:                if (cl->state == cs_connected)
                    727:                        Com_Printf ("CNCT ");
                    728:                else if (cl->state == cs_zombie)
                    729:                        Com_Printf ("ZMBI ");
                    730:                else
                    731:                {
                    732:                        ping = cl->ping < 9999 ? cl->ping : 9999;
                    733:                        Com_Printf ("%4i ", ping);
                    734:                }
                    735: 
                    736:                Com_Printf ("%s", cl->name);
                    737:                l = 16 - strlen(cl->name);
                    738:                for (j=0 ; j<l ; j++)
                    739:                        Com_Printf (" ");
                    740: 
                    741:                Com_Printf ("%7i ", svs.realtime - cl->lastmessage );
                    742: 
                    743:                s = NET_AdrToString ( cl->netchan.remote_address);
                    744:                Com_Printf ("%s", s);
                    745:                l = 22 - strlen(s);
                    746:                for (j=0 ; j<l ; j++)
                    747:                        Com_Printf (" ");
                    748:                
                    749:                Com_Printf ("%5i", cl->netchan.qport);
                    750: 
                    751:                Com_Printf ("\n");
                    752:        }
                    753:        Com_Printf ("\n");
                    754: }
                    755: 
                    756: /*
                    757: ==================
                    758: SV_ConSay_f
                    759: ==================
                    760: */
                    761: void SV_ConSay_f(void)
                    762: {
                    763:        client_t *client;
                    764:        int             j;
                    765:        char    *p;
                    766:        char    text[1024];
                    767: 
                    768:        if (Cmd_Argc () < 2)
                    769:                return;
                    770: 
                    771:        strcpy (text, "console: ");
                    772:        p = Cmd_Args();
                    773: 
                    774:        if (*p == '"')
                    775:        {
                    776:                p++;
                    777:                p[strlen(p)-1] = 0;
                    778:        }
                    779: 
                    780:        strcat(text, p);
                    781: 
                    782:        for (j = 0, client = svs.clients; j < maxclients->value; j++, client++)
                    783:        {
                    784:                if (client->state != cs_spawned)
                    785:                        continue;
                    786:                SV_ClientPrintf(client, PRINT_CHAT, "%s\n", text);
                    787:        }
                    788: }
                    789: 
                    790: 
                    791: /*
                    792: ==================
                    793: SV_Heartbeat_f
                    794: ==================
                    795: */
                    796: void SV_Heartbeat_f (void)
                    797: {
                    798:        svs.last_heartbeat = -9999999;
                    799: }
                    800: 
                    801: 
                    802: /*
                    803: ===========
                    804: SV_Serverinfo_f
                    805: 
                    806:   Examine or change the serverinfo string
                    807: ===========
                    808: */
                    809: void SV_Serverinfo_f (void)
                    810: {
                    811:        Com_Printf ("Server info settings:\n");
                    812:        Info_Print (Cvar_Serverinfo());
                    813: }
                    814: 
                    815: 
                    816: /*
                    817: ===========
                    818: SV_DumpUser_f
                    819: 
                    820: Examine all a users info strings
                    821: ===========
                    822: */
                    823: void SV_DumpUser_f (void)
                    824: {
                    825:        if (Cmd_Argc() != 2)
                    826:        {
                    827:                Com_Printf ("Usage: info <userid>\n");
                    828:                return;
                    829:        }
                    830: 
                    831:        if (!SV_SetPlayer ())
                    832:                return;
                    833: 
                    834:        Com_Printf ("userinfo\n");
                    835:        Com_Printf ("--------\n");
                    836:        Info_Print (sv_client->userinfo);
                    837: 
                    838: }
                    839: 
                    840: 
                    841: /*
                    842: ==============
                    843: SV_ServerRecord_f
                    844: 
                    845: Begins server demo recording.  Every entity and every message will be
                    846: recorded, but no playerinfo will be stored.  Primarily for demo merging.
                    847: ==============
                    848: */
                    849: void SV_ServerRecord_f (void)
                    850: {
                    851:        char    name[MAX_OSPATH];
                    852:        char    buf_data[MAX_MSGLEN];
                    853:        sizebuf_t       buf;
                    854:        int             len;
                    855:        int             i;
                    856: 
                    857:        if (Cmd_Argc() != 2)
                    858:        {
                    859:                Com_Printf ("serverrecord <demoname>\n");
                    860:                return;
                    861:        }
                    862: 
                    863:        if (svs.demofile)
                    864:        {
                    865:                Com_Printf ("Already recording.\n");
                    866:                return;
                    867:        }
                    868: 
                    869:        if (sv.state != ss_game)
                    870:        {
                    871:                Com_Printf ("You must be in a level to record.\n");
                    872:                return;
                    873:        }
                    874: 
                    875:        //
                    876:        // open the demo file
                    877:        //
                    878:        Com_sprintf (name, sizeof(name), "%s/demos/%s.dm2", FS_Gamedir(), Cmd_Argv(1));
                    879: 
                    880:        Com_Printf ("recording to %s.\n", name);
                    881:        FS_CreatePath (name);
                    882:        svs.demofile = fopen (name, "wb");
                    883:        if (!svs.demofile)
                    884:        {
                    885:                Com_Printf ("ERROR: couldn't open.\n");
                    886:                return;
                    887:        }
                    888: 
                    889:        // setup a buffer to catch all multicasts
                    890:        SZ_Init (&svs.demo_multicast, svs.demo_multicast_buf, sizeof(svs.demo_multicast_buf));
                    891: 
                    892:        //
                    893:        // write a single giant fake message with all the startup info
                    894:        //
                    895:        SZ_Init (&buf, buf_data, sizeof(buf_data));
                    896: 
                    897:        for (i=0 ; i<MAX_CONFIGSTRINGS ; i++)
                    898:                if (sv.configstrings[i][0])
                    899:                {
                    900:                        MSG_WriteByte (&buf, svc_configstring);
                    901:                        MSG_WriteShort (&buf, i);
                    902:                        MSG_WriteString (&buf, sv.configstrings[i]);
                    903:                }
                    904: 
                    905:        // write it to the demo file
                    906:        Com_DPrintf ("signon message length: %i\n", buf.cursize);
                    907:        len = LittleLong (buf.cursize);
                    908:        fwrite (&len, 4, 1, svs.demofile);
                    909:        fwrite (buf.data, buf.cursize, 1, svs.demofile);
                    910: 
                    911:        // the rest of the demo file will be individual frames
                    912: }
                    913: 
                    914: 
                    915: /*
                    916: ==============
                    917: SV_ServerStop_f
                    918: 
                    919: Ends server demo recording
                    920: ==============
                    921: */
                    922: void SV_ServerStop_f (void)
                    923: {
                    924:        if (!svs.demofile)
                    925:        {
                    926:                Com_Printf ("Not doing a serverrecord.\n");
                    927:                return;
                    928:        }
                    929:        fclose (svs.demofile);
                    930:        svs.demofile = NULL;
                    931:        Com_Printf ("Recording completed.\n");
                    932: }
                    933: 
                    934: 
                    935: /*
                    936: ===============
                    937: SV_KillServer_f
                    938: 
                    939: Kick everyone off, possibly in preparation for a new game
                    940: 
                    941: ===============
                    942: */
                    943: void SV_KillServer_f (void)
                    944: {
                    945:        if (!svs.initialized)
                    946:                return;
                    947:        SV_Shutdown ("Server was killed.\n", false);
                    948:        NET_Config ( false );   // close network sockets
                    949: }
                    950: 
                    951: /*
                    952: ===============
                    953: SV_ServerCommand_f
                    954: 
                    955: Let the game dll handle a command
                    956: ===============
                    957: */
                    958: void SV_ServerCommand_f (void)
                    959: {
                    960:        if (!ge)
                    961:        {
                    962:                Com_Printf ("No game loaded.\n");
                    963:                return;
                    964:        }
                    965: 
                    966:        ge->ServerCommand();
                    967: }
                    968: 
                    969: //===========================================================
                    970: 
                    971: /*
                    972: ==================
                    973: SV_InitOperatorCommands
                    974: ==================
                    975: */
                    976: void SV_InitOperatorCommands (void)
                    977: {
                    978:        Cmd_AddCommand ("heartbeat", SV_Heartbeat_f);
                    979:        Cmd_AddCommand ("kick", SV_Kick_f);
                    980:        Cmd_AddCommand ("status", SV_Status_f);
                    981:        Cmd_AddCommand ("serverinfo", SV_Serverinfo_f);
                    982:        Cmd_AddCommand ("dumpuser", SV_DumpUser_f);
                    983: 
                    984:        Cmd_AddCommand ("map", SV_Map_f);
                    985:        Cmd_AddCommand ("demomap", SV_DemoMap_f);
                    986:        Cmd_AddCommand ("gamemap", SV_GameMap_f);
                    987:        Cmd_AddCommand ("setmaster", SV_SetMaster_f);
                    988: 
                    989:        if ( dedicated->value )
                    990:                Cmd_AddCommand ("say", SV_ConSay_f);
                    991: 
                    992:        Cmd_AddCommand ("serverrecord", SV_ServerRecord_f);
                    993:        Cmd_AddCommand ("serverstop", SV_ServerStop_f);
                    994: 
                    995:        Cmd_AddCommand ("save", SV_Savegame_f);
                    996:        Cmd_AddCommand ("load", SV_Loadgame_f);
                    997: 
                    998:        Cmd_AddCommand ("killserver", SV_KillServer_f);
                    999: 
                   1000:        Cmd_AddCommand ("sv", SV_ServerCommand_f);
                   1001: }
                   1002: 

unix.superglobalmegacorp.com

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