Annotation of quake2/server/sv_init.c, revision 1.1

1.1     ! root        1: 
        !             2: #include "server.h"
        !             3: 
        !             4: server_static_t        svs;                            // persistant server info
        !             5: server_t               sv;                                     // local server
        !             6: 
        !             7: /*
        !             8: ================
        !             9: SV_FindIndex
        !            10: 
        !            11: ================
        !            12: */
        !            13: int SV_FindIndex (char *name, int start, int max, qboolean create)
        !            14: {
        !            15:        int             i;
        !            16:        
        !            17:        if (!name || !name[0])
        !            18:                return 0;
        !            19: 
        !            20:        for (i=1 ; i<max && sv.configstrings[start+i][0] ; i++)
        !            21:                if (!strcmp(sv.configstrings[start+i], name))
        !            22:                        return i;
        !            23: 
        !            24:        if (!create)
        !            25:                return 0;
        !            26: 
        !            27:        if (i == max)
        !            28:                Com_Error (ERR_DROP, "*Index: overflow");
        !            29: 
        !            30:        strncpy (sv.configstrings[start+i], name, sizeof(sv.configstrings[i]));
        !            31: 
        !            32:        if (sv.state != ss_loading)
        !            33:        {       // send the update to everyone
        !            34:                SZ_Clear (&sv.multicast);
        !            35:                MSG_WriteChar (&sv.multicast, svc_configstring);
        !            36:                MSG_WriteShort (&sv.multicast, start+i);
        !            37:                MSG_WriteString (&sv.multicast, name);
        !            38:                SV_Multicast (vec3_origin, MULTICAST_ALL_R);
        !            39:        }
        !            40: 
        !            41:        return i;
        !            42: }
        !            43: 
        !            44: 
        !            45: int SV_ModelIndex (char *name)
        !            46: {
        !            47:        return SV_FindIndex (name, CS_MODELS, MAX_MODELS, true);
        !            48: }
        !            49: 
        !            50: int SV_SoundIndex (char *name)
        !            51: {
        !            52:        return SV_FindIndex (name, CS_SOUNDS, MAX_SOUNDS, true);
        !            53: }
        !            54: 
        !            55: int SV_ImageIndex (char *name)
        !            56: {
        !            57:        return SV_FindIndex (name, CS_IMAGES, MAX_IMAGES, true);
        !            58: }
        !            59: 
        !            60: 
        !            61: /*
        !            62: ================
        !            63: SV_CreateBaseline
        !            64: 
        !            65: Entity baselines are used to compress the update messages
        !            66: to the clients -- only the fields that differ from the
        !            67: baseline will be transmitted
        !            68: ================
        !            69: */
        !            70: void SV_CreateBaseline (void)
        !            71: {
        !            72:        edict_t                 *svent;
        !            73:        int                             entnum; 
        !            74: 
        !            75:        for (entnum = 1; entnum < ge->num_edicts ; entnum++)
        !            76:        {
        !            77:                svent = EDICT_NUM(entnum);
        !            78:                if (!svent->inuse)
        !            79:                        continue;
        !            80:                if (!svent->s.modelindex && !svent->s.sound && !svent->s.effects)
        !            81:                        continue;
        !            82:                svent->s.number = entnum;
        !            83: 
        !            84:                //
        !            85:                // take current state as baseline
        !            86:                //
        !            87:                VectorCopy (svent->s.origin, svent->s.old_origin);
        !            88:                sv.baselines[entnum] = svent->s;
        !            89:        }
        !            90: }
        !            91: 
        !            92: 
        !            93: /*
        !            94: =================
        !            95: SV_CheckForSavegame
        !            96: =================
        !            97: */
        !            98: void SV_CheckForSavegame (void)
        !            99: {
        !           100:        char            name[MAX_OSPATH];
        !           101:        FILE            *f;
        !           102:        int                     i;
        !           103: 
        !           104:        if (sv_noreload->value)
        !           105:                return;
        !           106: 
        !           107:        if (Cvar_VariableValue ("deathmatch"))
        !           108:                return;
        !           109: 
        !           110:        Com_sprintf (name, sizeof(name), "%s/save/current/%s.sav", FS_Gamedir(), sv.name);
        !           111:        f = fopen (name, "rb");
        !           112:        if (!f)
        !           113:                return;         // no savegame
        !           114: 
        !           115:        fclose (f);
        !           116: 
        !           117:        SV_ClearWorld ();
        !           118: 
        !           119:        // get configstrings and areaportals
        !           120:        SV_ReadLevelFile ();
        !           121: 
        !           122:        if (!sv.loadgame)
        !           123:        {       // coming back to a level after being in a different
        !           124:                // level, so run it for ten seconds
        !           125:                for (i=0 ; i<100 ; i++)
        !           126:                        ge->RunFrame ();
        !           127:        }
        !           128: }
        !           129: 
        !           130: 
        !           131: /*
        !           132: ================
        !           133: SV_SpawnServer
        !           134: 
        !           135: Change the server to a new map, taking all connected
        !           136: clients along with it.
        !           137: 
        !           138: ================
        !           139: */
        !           140: void SV_SpawnServer (char *server, char *spawnpoint, server_state_t serverstate, qboolean attractloop, qboolean loadgame)
        !           141: {
        !           142:        int                     i;
        !           143:        unsigned        checksum;
        !           144: 
        !           145:        if (attractloop)
        !           146:                Cvar_Set ("paused", "0");
        !           147: 
        !           148:        Com_Printf ("------- Server Initialization -------\n");
        !           149: 
        !           150:        Com_DPrintf ("SpawnServer: %s\n",server);
        !           151:        if (sv.demofile)
        !           152:                fclose (sv.demofile);
        !           153: 
        !           154:        svs.spawncount++;               // any partially connected client will be
        !           155:                                                        // restarted
        !           156:        sv.state = ss_dead;
        !           157:        Com_SetServerState (sv.state);
        !           158: 
        !           159:        // wipe the entire per-level structure
        !           160:        memset (&sv, 0, sizeof(sv));
        !           161:        svs.realtime = 0;
        !           162:        sv.loadgame = loadgame;
        !           163:        sv.attractloop = attractloop;
        !           164: 
        !           165:        // save name for levels that don't set message
        !           166:        strcpy (sv.configstrings[CS_NAME], server);
        !           167: 
        !           168:        SZ_Init (&sv.multicast, sv.multicast_buf, sizeof(sv.multicast_buf));
        !           169: 
        !           170:        strcpy (sv.name, server);
        !           171: 
        !           172:        // leave slots at start for clients only
        !           173:        for (i=0 ; i<maxclients->value ; i++)
        !           174:        {
        !           175:                // needs to reconnect
        !           176:                if (svs.clients[i].state > cs_connected)
        !           177:                        svs.clients[i].state = cs_connected;
        !           178:                svs.clients[i].lastframe = -1;
        !           179:        }
        !           180: 
        !           181:        sv.time = 1000;
        !           182:        
        !           183:        strcpy (sv.name, server);
        !           184:        strcpy (sv.configstrings[CS_NAME], server);
        !           185: 
        !           186:        if (serverstate != ss_game)
        !           187:        {
        !           188:                sv.models[1] = CM_LoadMap ("", false, &checksum);       // no real map
        !           189:        }
        !           190:        else
        !           191:        {
        !           192:                Com_sprintf (sv.configstrings[CS_MODELS+1],sizeof(sv.configstrings[CS_MODELS+1]),
        !           193:                        "maps/%s.bsp", server);
        !           194:                sv.models[1] = CM_LoadMap (sv.configstrings[CS_MODELS+1], false, &checksum);
        !           195:        }
        !           196:        Com_sprintf (sv.configstrings[CS_MAPCHECKSUM],sizeof(sv.configstrings[CS_MAPCHECKSUM]),
        !           197:                "%i", checksum);
        !           198: 
        !           199:        //
        !           200:        // clear physics interaction links
        !           201:        //
        !           202:        SV_ClearWorld ();
        !           203:        
        !           204:        for (i=1 ; i< CM_NumInlineModels() ; i++)
        !           205:        {
        !           206:                Com_sprintf (sv.configstrings[CS_MODELS+1+i], sizeof(sv.configstrings[CS_MODELS+1+i]),
        !           207:                        "*%i", i);
        !           208:                sv.models[i+1] = CM_InlineModel (sv.configstrings[CS_MODELS+1+i]);
        !           209:        }
        !           210: 
        !           211:        //
        !           212:        // spawn the rest of the entities on the map
        !           213:        //      
        !           214: 
        !           215:        // precache and static commands can be issued during
        !           216:        // map initialization
        !           217:        sv.state = ss_loading;
        !           218:        Com_SetServerState (sv.state);
        !           219: 
        !           220:        // load and spawn all other entities
        !           221:        ge->SpawnEntities ( sv.name, CM_EntityString(), spawnpoint );
        !           222: 
        !           223:        // run two frames to allow everything to settle
        !           224:        ge->RunFrame ();
        !           225:        ge->RunFrame ();
        !           226: 
        !           227:        // all precaches are complete
        !           228:        sv.state = serverstate;
        !           229:        Com_SetServerState (sv.state);
        !           230:        
        !           231:        // create a baseline for more efficient communications
        !           232:        SV_CreateBaseline ();
        !           233: 
        !           234:        // check for a savegame
        !           235:        SV_CheckForSavegame ();
        !           236: 
        !           237:        // set serverinfo variable
        !           238:        Cvar_FullSet ("mapname", sv.name, CVAR_SERVERINFO | CVAR_NOSET);
        !           239: 
        !           240:        Com_Printf ("-------------------------------------\n");
        !           241: }
        !           242: 
        !           243: /*
        !           244: ==============
        !           245: SV_InitGame
        !           246: 
        !           247: A brand new game has been started
        !           248: ==============
        !           249: */
        !           250: void SV_InitGame (void)
        !           251: {
        !           252:        int             i;
        !           253:        edict_t *ent;
        !           254:        char    idmaster[32];
        !           255: 
        !           256:        if (svs.initialized)
        !           257:        {
        !           258:                // cause any connected clients to reconnect
        !           259:                SV_Shutdown ("Server restarted\n", true);
        !           260:        }
        !           261:        else
        !           262:        {
        !           263:                // make sure the client is down
        !           264:                CL_Drop ();
        !           265:                SCR_BeginLoadingPlaque ();
        !           266:        }
        !           267: 
        !           268:        // get any latched variable changes (maxclients, etc)
        !           269:        Cvar_GetLatchedVars ();
        !           270: 
        !           271:        svs.initialized = true;
        !           272: 
        !           273:        if (Cvar_VariableValue ("coop") && Cvar_VariableValue ("deathmatch"))
        !           274:        {
        !           275:                Com_Printf("Deathmatch and Coop both set, disabling Coop\n");
        !           276:                Cvar_FullSet ("coop", "0",  CVAR_SERVERINFO | CVAR_LATCH);
        !           277:        }
        !           278: 
        !           279:        // dedicated servers are can't be single player and are usually DM
        !           280:        // so unless they explicity set coop, force it to deathmatch
        !           281:        if (dedicated->value)
        !           282:        {
        !           283:                if (!Cvar_VariableValue ("coop"))
        !           284:                        Cvar_FullSet ("deathmatch", "1",  CVAR_SERVERINFO | CVAR_LATCH);
        !           285:        }
        !           286: 
        !           287:        // init clients
        !           288:        if (Cvar_VariableValue ("deathmatch"))
        !           289:        {
        !           290:                if (maxclients->value <= 1)
        !           291:                        Cvar_FullSet ("maxclients", "8", CVAR_SERVERINFO | CVAR_LATCH);
        !           292:                else if (maxclients->value > MAX_CLIENTS)
        !           293:                        Cvar_FullSet ("maxclients", va("%i", MAX_CLIENTS), CVAR_SERVERINFO | CVAR_LATCH);
        !           294:        }
        !           295:        else if (Cvar_VariableValue ("coop"))
        !           296:        {
        !           297:                if (maxclients->value <= 1 || maxclients->value > 4)
        !           298:                        Cvar_FullSet ("maxclients", "4", CVAR_SERVERINFO | CVAR_LATCH);
        !           299:                if (!sv.attractloop && !dedicated->value)
        !           300:                        Sys_CopyProtect ();
        !           301:        }
        !           302:        else    // non-deathmatch, non-coop is one player
        !           303:        {
        !           304:                Cvar_FullSet ("maxclients", "1", CVAR_SERVERINFO | CVAR_LATCH);
        !           305:                if (!sv.attractloop)
        !           306:                        Sys_CopyProtect ();
        !           307:        }
        !           308: 
        !           309:        svs.spawncount = rand();
        !           310:        svs.clients = Z_Malloc (sizeof(client_t)*maxclients->value);
        !           311:        svs.num_client_entities = maxclients->value*UPDATE_BACKUP*64;
        !           312:        svs.client_entities = Z_Malloc (sizeof(entity_state_t)*svs.num_client_entities);
        !           313: 
        !           314:        // init network stuff
        !           315:        NET_Config ( (maxclients->value > 1) );
        !           316: 
        !           317:        // heartbeats will always be sent to the id master
        !           318:        svs.last_heartbeat = -99999;            // send immediately
        !           319:        Com_sprintf(idmaster, sizeof(idmaster), "192.246.40.37:%i", PORT_MASTER);
        !           320:        NET_StringToAdr (idmaster, &master_adr[0]);
        !           321: 
        !           322:        // init game
        !           323:        SV_InitGameProgs ();
        !           324:        for (i=0 ; i<maxclients->value ; i++)
        !           325:        {
        !           326:                ent = EDICT_NUM(i+1);
        !           327:                ent->s.number = i+1;
        !           328:                svs.clients[i].edict = ent;
        !           329:                memset (&svs.clients[i].lastcmd, 0, sizeof(svs.clients[i].lastcmd));
        !           330:        }
        !           331: }
        !           332: 
        !           333: 
        !           334: /*
        !           335: ======================
        !           336: SV_Map
        !           337: 
        !           338:   the full syntax is:
        !           339: 
        !           340:   map [*]<map>$<startspot>+<nextserver>
        !           341: 
        !           342: command from the console or progs.
        !           343: Map can also be a.cin, .pcx, or .dm2 file
        !           344: Nextserver is used to allow a cinematic to play, then proceed to
        !           345: another level:
        !           346: 
        !           347:        map tram.cin+jail_e3
        !           348: ======================
        !           349: */
        !           350: void SV_Map (qboolean attractloop, char *levelstring, qboolean loadgame)
        !           351: {
        !           352:        char    level[MAX_QPATH];
        !           353:        char    *ch;
        !           354:        int             l;
        !           355:        char    spawnpoint[MAX_QPATH];
        !           356: 
        !           357:        sv.loadgame = loadgame;
        !           358:        sv.attractloop = attractloop;
        !           359: 
        !           360:        if (sv.state == ss_dead && !sv.loadgame)
        !           361:                SV_InitGame (); // the game is just starting
        !           362: 
        !           363:        strcpy (level, levelstring);
        !           364: 
        !           365:        // if there is a + in the map, set nextserver to the remainder
        !           366:        ch = strstr(level, "+");
        !           367:        if (ch)
        !           368:        {
        !           369:                *ch = 0;
        !           370:                Cvar_Set ("nextserver", va("gamemap \"%s\"", ch+1));
        !           371:        }
        !           372:        else
        !           373:                Cvar_Set ("nextserver", "");
        !           374: 
        !           375: 
        !           376:        // if there is a $, use the remainder as a spawnpoint
        !           377:        ch = strstr(level, "$");
        !           378:        if (ch)
        !           379:        {
        !           380:                *ch = 0;
        !           381:                strcpy (spawnpoint, ch+1);
        !           382:        }
        !           383:        else
        !           384:                spawnpoint[0] = 0;
        !           385: 
        !           386:        // skip the end-of-unit flag if necessary
        !           387:        if (level[0] == '*')
        !           388:                strcpy (level, level+1);
        !           389: 
        !           390:        l = strlen(level);
        !           391:        if (l > 4 && !strcmp (level+l-4, ".cin") )
        !           392:        {
        !           393:                SCR_BeginLoadingPlaque ();                      // for local system
        !           394:                SV_SpawnServer (level, spawnpoint, ss_cinematic, attractloop, loadgame);
        !           395:        }
        !           396:        else if (l > 4 && !strcmp (level+l-4, ".dm2") )
        !           397:        {
        !           398:                SCR_BeginLoadingPlaque ();                      // for local system
        !           399:                SV_SpawnServer (level, spawnpoint, ss_demo, attractloop, loadgame);
        !           400:        }
        !           401:        else if (l > 4 && !strcmp (level+l-4, ".pcx") )
        !           402:        {
        !           403:                SCR_BeginLoadingPlaque ();                      // for local system
        !           404:                SV_SpawnServer (level, spawnpoint, ss_pic, attractloop, loadgame);
        !           405:        }
        !           406:        else
        !           407:        {
        !           408:                SCR_BeginLoadingPlaque ();                      // for local system
        !           409:                SV_BroadcastCommand ("changing\n");
        !           410:                SV_SendClientMessages ();
        !           411:                SV_SpawnServer (level, spawnpoint, ss_game, attractloop, loadgame);
        !           412:                Cbuf_CopyToDefer ();
        !           413:        }
        !           414: 
        !           415:        SV_BroadcastCommand ("reconnect\n");
        !           416: }

unix.superglobalmegacorp.com

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