static void init(void) { /* Enable all the interrupts */ IRQ_ENABLE; /* Initialize debugging module (allow kprintf(), etc.) */ kdbg_init(); /* Initialize system timer */ timer_init(); /* Initialize LED driver */ LED_INIT(); ser_init(&ser_port, SER_UART2); ser_setbaudrate(&ser_port, 115200L); afsk_init(&afsk, 0, 0); // timer period = 24000000 hz /100/25 = 9600hz AD_Init(&afsk); AD_SetTimer(100, 25); AD_Start(); DA_Init(&afsk); DA_SetTimer(100, 25); kiss_init(&ser_port, &ax25, &afsk); ax25_init(&ax25, &afsk.fd, 1, ax25_message_callback); }
/* ================ SV_CreateBaseline Entity baselines are used to compress non-delta messages to the clients -- only the fields that differ from the baseline will be transmitted ================ */ static void SV_CreateBaseline( void ) { sharedEntity_t *svent; int entnum; DA_Init( &sv.svEntitiesBaseline, MAX_GENTITIES, sv.gameEntityStateSize, qfalse ); for ( entnum = 1; entnum < sv.num_entities ; entnum++ ) { svent = SV_GentityNum(entnum); if (!svent->r.linked) { continue; } svent->s.number = entnum; // // take current state as baseline // DA_SetElement( &sv.svEntitiesBaseline, entnum, SV_GameEntityStateNum(entnum) ); } }
/* ================ SV_SpawnServer Change the server to a new map, taking all connected clients along with it. This is NOT called for map_restart ================ */ void SV_SpawnServer( char *server, qboolean killBots ) { int i; int checksum; qboolean isBot; char systemInfo[16384]; const char *p; // shut down the existing game if it is running SV_ShutdownGameProgs(); Com_Printf ("Loading level %s...\n", server); Com_DPrintf ("------ Server Initialization ------\n"); Com_DPrintf ("Server: %s\n",server); // if not running a dedicated server CL_MapLoading will connect the client to the server // also print some status stuff CL_MapLoading(); // make sure all the client stuff is unloaded CL_ShutdownAll(qfalse); // clear the whole hunk because we're (re)loading the server Hunk_Clear(); #ifdef DEDICATED // Restart renderer SV_InitDedicatedRef(); #else // Restart renderer, and if dedicated start cgame CL_StartHunkUsers( !com_dedicated->integer ); #endif // clear collision map data CM_ClearMap(); // init client structures and svs.numSnapshotEntities if ( !Cvar_VariableValue("sv_running") ) { SV_Startup(); } else { // check for maxclients change if ( sv_maxclients->modified ) { SV_ChangeMaxClients(); } } // toggle the server bit so clients can detect that a // server has changed svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT; // set nextmap to the same map, but it may be overriden // by the game startup or another console command Cvar_Set( "nextmap", "map_restart 0"); // Cvar_Set( "nextmap", va("map %s", server) ); for (i=0 ; i<sv_maxclients->integer ; i++) { // save when the server started for each client already connected if (svs.clients[i].state >= CS_CONNECTED) { svs.clients[i].oldServerTime = sv.time; } } // wipe the entire per-level structure SV_ClearServer(); for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) { sv.configstrings[i].s = CopyString(""); sv.configstrings[i].restricted = qfalse; Com_Memset(&sv.configstrings[i].clientList, 0, sizeof(clientList_t)); } // make sure we are not paused Cvar_Set("cl_paused", "0"); // restart the file system FS_Restart(qfalse); CM_LoadMap( va("maps/%s.bsp", server), qfalse, &checksum ); // set serverinfo visible name Cvar_Set( "mapname", server ); Cvar_Set( "sv_mapChecksum", va("%i",checksum) ); // serverid should be different each time sv.serverId = com_frameTime; sv.restartedServerId = sv.serverId; // I suppose the init here is just to be safe Cvar_Set( "sv_serverid", va("%i", sv.serverId ) ); // clear physics interaction links SV_ClearWorld (); // media configstring setting should be done during // the loading stage, so connected clients don't have // to load during actual gameplay sv.state = SS_LOADING; // load and spawn all other entities SV_InitGameProgs(); // allocate the snapshot entities on the hunk DA_Init( &svs.snapshotEntities, svs.numSnapshotEntities, sv.gameEntityStateSize, qfalse ); svs.nextSnapshotEntities = 0; // run a few frames to allow everything to settle for (i = 0;i < 3; i++) { VM_Call (gvm, GAME_RUN_FRAME, sv.time); SV_BotFrame (sv.time); sv.time += 100; svs.time += 100; } // create a baseline for more efficient communications SV_CreateBaseline (); for (i=0 ; i<sv_maxclients->integer ; i++) { // send the new gamestate to all connected clients if (svs.clients[i].state >= CS_CONNECTED) { char *denied; player_t *player; int j; if ( svs.clients[i].netchan.remoteAddress.type == NA_BOT ) { if ( killBots ) { SV_DropClient( &svs.clients[i], "" ); continue; } isBot = qtrue; } else { isBot = qfalse; } for ( j = 0; j < MAX_SPLITVIEW; j++ ) { player = svs.clients[i].localPlayers[j]; if ( !player ) continue; // setup entity before connecting SV_SetupPlayerEntity( player ); // connect the client again denied = VM_ExplicitArgPtr( gvm, VM_Call( gvm, GAME_CLIENT_CONNECT, player - svs.players, qfalse, isBot, i, j ) ); // firstTime = qfalse player = svs.clients[i].localPlayers[j]; // may be NULL if game dropped player if ( denied && player != NULL ) { // this generally shouldn't happen, because the client // was connected before the level change SV_DropPlayer( player, denied ); } } // check if client was dropped if ( svs.clients[i].state < CS_CONNECTED ) { continue; } if( !isBot ) { // when we get the next packet from a connected client, // the new gamestate will be sent svs.clients[i].state = CS_CONNECTED; } else { client_t *client; client = &svs.clients[i]; client->state = CS_ACTIVE; client->deltaMessage = -1; client->lastSnapshotTime = 0; // generate a snapshot immediately VM_Call( gvm, GAME_CLIENT_BEGIN, i ); } } } // run another frame to allow things to look at all the players VM_Call (gvm, GAME_RUN_FRAME, sv.time); SV_BotFrame (sv.time); sv.time += 100; svs.time += 100; // Force sv_pure to off if invalid default pk3s if (sv_pure->integer && !com_fs_pure->integer) { Cvar_Set( "sv_pure", "0" ); } if ( sv_pure->integer ) { // the server sends these to the clients so they will only // load pk3s also loaded at the server p = FS_LoadedPakChecksums(); Cvar_Set( "sv_paks", p ); if (strlen(p) == 0) { Com_Printf( "WARNING: sv_pure set but no PK3 files loaded\n" ); } p = FS_LoadedPakNames(); Cvar_Set( "sv_pakNames", p ); // if a dedicated pure server we need to touch the cgame because it could be in a // seperate pk3 file and the client will need to load the latest cgame.qvm if ( com_dedicated->integer ) { SV_TouchCGame(); } } else { Cvar_Set( "sv_paks", "" ); Cvar_Set( "sv_pakNames", "" ); } // the server sends these to the clients so they can figure // out which pk3s should be auto-downloaded p = FS_ReferencedPakChecksums(); Cvar_Set( "sv_referencedPaks", p ); p = FS_ReferencedPakNames(); Cvar_Set( "sv_referencedPakNames", p ); // save systeminfo and serverinfo strings Q_strncpyz( systemInfo, Cvar_InfoString_Big( CVAR_SYSTEMINFO ), sizeof( systemInfo ) ); cvar_modifiedFlags &= ~CVAR_SYSTEMINFO; SV_SetConfigstring( CS_SYSTEMINFO, systemInfo ); SV_SetConfigstring( CS_SERVERINFO, Cvar_InfoString( CVAR_SERVERINFO ) ); cvar_modifiedFlags &= ~CVAR_SERVERINFO; // any media configstring setting now should issue a warning // and any configstring changes should be reliably transmitted // to all clients sv.state = SS_GAME; // send a heartbeat now so the master will get up to date info SV_Heartbeat_f(); Hunk_SetMark(); Com_DPrintf ("-----------------------------------\n"); }