📄 d_clisrv.c
字号:
textcmds[gametic%BACKUPTICS][playernum][0]+=MAXPLAYERNAME+1+1; } if(ex & 2) { size=textcmds[gametic%BACKUPTICS][playernum][0]; textcmds[gametic%BACKUPTICS][playernum][size+1]=XD_WEAPONPREF; memcpy(&textcmds[gametic%BACKUPTICS][playernum][size+2], p, NUMWEAPONS+2); p+=NUMWEAPONS+2; textcmds[gametic%BACKUPTICS][playernum][0]+=NUMWEAPONS+2+1; } nextra--; } else memcpy(textcmds[gametic%BACKUPTICS][playernum],*demo_pointer,nextra+1); // increment demo pointer *demo_pointer +=nextra+1;}// -----------------------------------------------------------------// end extra data function for lmps// -----------------------------------------------------------------static short Consistancy(void);typedef enum { cl_searching, cl_downloadfiles, cl_askjoin, cl_waitjoinresponce, cl_downloadsavegame, cl_connected} cl_mode_t;static void GetPackets(void);void SV_ResetServer( void );cl_mode_t cl_mode=cl_searching;//// SendClJoin//// send a special packet for declare how many player in local// used only in arbitratrenetstart()static boolean CL_SendJoin(){ CONS_Printf("Send join request...\n"); netbuffer->packettype=PT_CLIENTJOIN; if (drone) netbuffer->u.clientcfg.localplayers=0; else if (cv_splitscreen.value) netbuffer->u.clientcfg.localplayers=2; else netbuffer->u.clientcfg.localplayers=1; netbuffer->u.clientcfg.version = VERSION; netbuffer->u.clientcfg.subversion = SUBVERSION; return HSendPacket(servernode,true,0,sizeof(clientconfig_pak));}static void SV_SendServerInfo(int node, tic_t time){ byte *p; netbuffer->packettype=PT_SERVERINFO; netbuffer->u.serverinfo.version = VERSION; netbuffer->u.serverinfo.subversion = SUBVERSION; // return back the time value so client can compute there ping netbuffer->u.serverinfo.time = time; netbuffer->u.serverinfo.numberofplayer = SHORT(doomcom->numplayers); netbuffer->u.serverinfo.maxplayer = cv_maxplayers.value; netbuffer->u.serverinfo.load = 0; // unused for the moment netbuffer->u.serverinfo.deathmatch = cv_deathmatch.value; strncpy(netbuffer->u.serverinfo.servername, cv_servername.string, MAXSERVERNAME); if(gamemapname[0]) strcpy(netbuffer->u.serverinfo.mapname,gamemapname); else strcpy(netbuffer->u.serverinfo.mapname,G_BuildMapName(gameepisode,gamemap)); p=PutFileNeeded(); HSendPacket(node,false,0, p-((byte *)&netbuffer->u));}static boolean SV_SendServerConfig(int node){ int i,playermask=0; byte *p; netbuffer->packettype=PT_SERVERCFG; for(i=0;i<MAXPLAYERS;i++) if(playeringame[i]) playermask|=1<<i; netbuffer->u.servercfg.version = VERSION; netbuffer->u.servercfg.subversion = SUBVERSION; netbuffer->u.servercfg.serverplayer = serverplayer; netbuffer->u.servercfg.totalplayernum = SHORT(doomcom->numplayers); netbuffer->u.servercfg.playerdetected = playermask; netbuffer->u.servercfg.gametic = gametic; netbuffer->u.servercfg.clientnode = node; netbuffer->u.servercfg.gamestate = gamestate; p = netbuffer->u.servercfg.netcvarstates; CV_SaveNetVars((char**)&p); return HSendPacket(node,true,0,sizeof(serverconfig_pak)+(p-netbuffer->u.servercfg.netcvarstates));}#define JOININGAME#ifdef JOININGAME#define SAVEGAMESIZE (128*1024)static void SV_SendSaveGame(int node){ int length; byte* savebuffer; // first save it in a malloced buffer save_p = savebuffer = (byte *)malloc(SAVEGAMESIZE); if(!save_p) { CONS_Printf ("No More free memory for savegame\n"); return; } P_SaveGame(); length = save_p - savebuffer; if (length > SAVEGAMESIZE) I_Error ("Savegame buffer overrun"); // then send it ! SendRam(node, savebuffer, length, SF_RAM, 0);}static const char *tmpsave="$$$.sav";static void CL_LoadReceivedSavegame(void){ byte* savebuffer; int length = FIL_ReadFile(tmpsave,&savebuffer); CONS_Printf("loading savegame length %d\n",length); if (!length) { I_Error ("Can't read savegame sent"); return; } G_Downgrade (VERSION); save_p = savebuffer; paused = false; demoplayback = false; automapactive = false; // load a base level playerdeadview = false; if( !P_LoadGame() ) { CONS_Printf("Can't load the level !!!\n"); return; } // done Z_Free (savebuffer); unlink(tmpsave); consistancy[gametic%BACKUPTICS]=Consistancy(); CON_ToggleOff ();}#endifvoid SendAskInfo( int node ){ netbuffer->packettype = PT_ASKINFO; netbuffer->u.askinfo.version = VERSION; netbuffer->u.askinfo.time = LONG(I_GetTime()); HSendPacket(node,false,0,sizeof(askinfo_pak));}serverelem_t serverlist[MAXSERVERLIST];int serverlistcount=0;void SL_ClearServerList( int connectedserver ){ int i; for( i=0; i<serverlistcount; i++ ) if( connectedserver != serverlist[i].node ) { Net_CloseConnection(serverlist[i].node); serverlist[i].node = 0; } serverlistcount = 0;}int SL_SearchServer( int node ){ int i; for( i=0; i<serverlistcount; i++ ) if( serverlist[i].node == node ) return i; return -1;}void SL_InsertServer( serverinfo_pak *info, int node){ int i; boolean moved; // search if not allready on it i = SL_SearchServer( node ); if( i==-1 ) { // not found add it if( serverlistcount >= MAXSERVERLIST ) return; // list full i=serverlistcount++; } serverlist[i].info = *info; serverlist[i].node = node; // list is sorted by time (ping) // so move the entry until it is sorted do { moved = false; if( i>0 && serverlist[i].info.time < serverlist[i-1].info.time ) { serverelem_t s; s = serverlist[i]; serverlist[i] = serverlist[i-1]; serverlist[i-1] = s; i--; moved = true; } else if( i<serverlistcount-1 && serverlist[i].info.time > serverlist[i+1].info.time ) { serverelem_t s; s = serverlist[i]; serverlist[i] = serverlist[i+1]; serverlist[i+1] = s; i++; moved = true; } } while(moved);}void CL_UpdateServerList( boolean internetsearch ){ SL_ClearServerList(0); if( !netgame ) { I_NetOpenSocket(); netgame = true; multiplayer = true; } // search for local servers SendAskInfo( BROADCASTADDR ); if( internetsearch ) { msg_server_t *server_list; int i; if( (server_list = GetShortServersList()) ) { for (i=0; server_list[i].header[0]; i++) { int node; char addr_str[24]; // insert ip (and optionaly port) in node list sprintf(addr_str, "%s:%s", server_list[i].ip, server_list[i].port); node = I_NetMakeNode(addr_str); if( node == -1 ) break; // no more node free SendAskInfo( node ); } } }}// use addaptive send using net_bandwidth and stat.sendbytesstatic void CL_ConnectToServer(){ int numnodes,nodewaited=doomcom->numnodes,i; boolean waitmore; tic_t asksent; tic_t oldtic; cl_mode=cl_searching; CONS_Printf("Press ESC to abort\n"); if( servernode<0 || servernode>=MAXNETNODES ) CONS_Printf("Searching the server...\n"); else CONS_Printf("Contacting the server...\n"); DEBFILE(va("waiting %d nodes\n",doomcom->numnodes)); gamestate = wipegamestate = GS_WAITINGPLAYERS; numnodes=1; oldtic=I_GetTime()-1; asksent=-TICRATE/2; SL_ClearServerList(servernode); do { switch(cl_mode) { case cl_searching : // serverlist is updated by GetPacket function if( serverlistcount>0 ) { // this can be a responce to our broadcast request if( servernode==-1 || servernode>=MAXNETNODES) { i = 0; servernode = serverlist[i].node; CONS_Printf("Found, "); } else { i=SL_SearchServer(servernode); if (i<0) break; // the case } D_ParseFileneeded(notimecheck, serverlist[i].info.fileneedednum, serverlist[i].info.fileneeded ); CONS_Printf("Checking files...\n"); i = CL_CheckFiles(); if( i==2 ) // cannot join for some reason { CL_Reset(); D_StartTitle(); return; } else if( i==1 ) cl_mode=cl_askjoin; else { // must download something // no problem if can't send packet, we will retry later if( SendRequestFile() ) cl_mode=cl_downloadfiles; } break; } // ask the info to the server (askinfo packet) if(asksent+TICRATE/2<I_GetTime()) { SendAskInfo(servernode); asksent=I_GetTime(); } break; case cl_downloadfiles : waitmore=false; for(i=0;i<fileneedednum;i++) if(fileneeded[i].status==FS_DOWNLOADING || fileneeded[i].status==FS_REQUESTED) { waitmore=true; break; } if(waitmore==false) cl_mode=cl_askjoin; //don't break case continue to cljoin request now else break; // exit the case case cl_askjoin : CL_LoadServerFiles();#ifdef JOININGAME // prepare structures to save the file // WARNING: this can be useless in case of server not in GS_LEVEL // but since the network layer don't provide ordered packet ... CL_PrepareDownloadSaveGame(tmpsave);#endif if( CL_SendJoin() ) cl_mode=cl_waitjoinresponce; break;#ifdef JOININGAME case cl_downloadsavegame : if( fileneeded[0].status==FS_FOUND ) { CL_LoadReceivedSavegame(); gamestate = GS_LEVEL; cl_mode=cl_connected; } //don't break case continue to cl_connected else break;#endif case cl_waitjoinresponce : case cl_connected : break; } GetPackets(); // connection closed by cancel or timeout if( !server && !netgame ) { cl_mode = cl_searching; return; } Net_AckTicker(); // call it only one by tic if( oldtic!=I_GetTime() ) { int key; I_OsPolling(); key = I_GetKey(); if (key==KEY_ESCAPE) { M_StartMessage ("Network game synchronization aborted.\n\nPress ESC\n", NULL, MM_NOTHING); CL_Reset(); D_StartTitle(); return; } if( key=='s' && server) doomcom->numnodes=numnodes; FiletxTicker(); oldtic=I_GetTime(); CON_Drawer (); I_FinishUpdate (); // page flip or blit buffer }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -