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

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

unix.superglobalmegacorp.com

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