📄 d_clisrv.c
字号:
// TODO : fixthis // don't send more than once the config par tic (more than one player join) if( sendconfigtic!=gametic ) { sendconfigtic=gametic; D_SendPlayerConfig(); }}boolean SV_AddWaitingPlayers(void){ int node,n; int newplayer=false; byte buf[2],newplayernum; newplayernum=0; for(node=0;node<MAXNETNODES;node++) { // splitscreen can allow 2 player in one node for(;nodewaiting[node]>0;nodewaiting[node]--) { newplayer=true; // search for a free playernum // we can't use playeringame since it is not updated here //while(newplayernum<MAXPLAYERS && playeringame[newplayernum]) // newplayernum++; for ( ;newplayernum<MAXPLAYERS;newplayernum++) { for(n=0;n<MAXNETNODES;n++) if( nodetoplayer[n] == newplayernum || nodetoplayer2[n] == newplayernum ) break; if( n == MAXNETNODES ) break; } #ifdef PARANOIA // should never happens since we check the playernum before accept // the join if(newplayernum==MAXPLAYERS) I_Error("SV_AddWaitingPlayers : j=MAXPLAYERS\n");#endif playernode[newplayernum]=node; buf[0]=node; buf[1]=newplayernum; if( playerpernode[node]<1 ) nodetoplayer[node] = newplayernum; else { nodetoplayer2[node] = newplayernum; buf[1]|=0x80; } playerpernode[node]++; SendNetXCmd(XD_ADDPLAYER,&buf,2); if( doomcom->numplayers==0 ) doomcom->numplayers++; //we must send the change to other players DEBFILE(va("Server added player %d node %d\n", newplayernum, node)); // use the next free slote (we can't put playeringame[j]=true here) newplayernum++; } } return newplayer;}void CL_AddSplitscreenPlayer( void ){ if( cl_mode == cl_connected ) CL_SendJoin();}void CL_RemoveSplitscreenPlayer( void ){ char buf[2]; if( cl_mode != cl_connected ) return; buf[0]=secondarydisplayplayer; buf[1]=KICK_MSG_PLAYER_QUIT; SendNetXCmd(XD_KICK,&buf,2);}// is there a game runningboolean Playing( void ){ return (server && serverrunning) || (!server && cl_mode==cl_connected);}boolean SV_SpawnServer( void ){ if( demoplayback ) G_StopDemo(); // reset engine parameter if( serverrunning == false ) { CONS_Printf("Starting Server....\n"); serverrunning = true; SV_ResetServer(); if( netgame ) { I_NetOpenSocket(); if( cv_internetserver.value ) RegisterServer(0, 0); } // server just connect to itself if( !dedicated ) CL_ConnectToServer(); } return SV_AddWaitingPlayers();}void SV_StopServer( void ){ int i; gamestate = wipegamestate = GS_NULL; localtextcmd[0]=0; localtextcmd2[0]=0; for(i=0;i<BACKUPTICS;i++) D_Clearticcmd(i); consoleplayer=0; cl_mode = cl_searching; maketic=gametic+1; neededtic=maketic; serverrunning = false;}// called at singleplayer start and stopdemovoid SV_StartSinglePlayerServer(void){ server = true; netgame = false; multiplayer = false; // no more tic the game with this settings ! SV_StopServer(); if( cv_splitscreen.value ) multiplayer = true;}static void SV_SendRefuse(int node,char *reason){ strcpy(netbuffer->u.serverrefuse.reason, reason); netbuffer->packettype=PT_SERVERREFUSE; HSendPacket(node,true,0,strlen(netbuffer->u.serverrefuse.reason)+1); Net_CloseConnection(node);}// used at txtcmds received to check packetsize boundstatic int TotalTextCmdPerTic(int tic){ int i,total=1; // num of textcmds in the tic (ntextcmd byte) tic %= BACKUPTICS; for(i=0;i<MAXPLAYERS;i++) if( ((i==0) || playeringame[i]) && textcmds[tic][i][0] ) total += 2 + textcmds[tic][i][0]; // "+2" for size and playernum return total;}//// GetPackets//// TODO : break this 300 line function to mutliple functionsstatic void GetPackets (void){ int netconsole; tic_t realend,realstart; int p=maketic%BACKUPTICS; byte *pak,*txtpak,numtxtpak; int node; while ( HGetPacket() ) { node = doomcom->remotenode; if( netbuffer->packettype == PT_CLIENTJOIN && server ) { if( netbuffer->u.clientcfg.version!=VERSION || netbuffer->u.clientcfg.subversion!=SUBVERSION) SV_SendRefuse(node,va("Different DOOM versions cannot play a net game! (server version %d.%d.%d)",VERSION/100,VERSION%100,SUBVERSION)); else if(!cv_allownewplayer.value && node!=0 ) SV_SendRefuse(node,"The server is not accepting people for the moment"); else // TODO; compute it using nodewaiting and playeringame if(doomcom->numplayers+1>cv_maxplayers.value) SV_SendRefuse(node,va("Maximum of player reached (max:%d)",cv_maxplayers.value)); else { boolean newnode=false; // client autorised to join nodewaiting[node]=netbuffer->u.clientcfg.localplayers-playerpernode[node]; if(!nodeingame[node]) { newnode = true; SV_AddNode(node); if(!SV_SendServerConfig(node)) { // TODO : fix this !!! CONS_Printf("Internal Error 5 : client lost\n"); continue; // the while } DEBFILE("new node joined\n"); }#ifdef JOININGAME if( nodewaiting[node] ) { if( gamestate == GS_LEVEL && newnode) { SV_SendSaveGame(node); CONS_Printf("send savegame\n"); } SV_AddWaitingPlayers(); }#endif } continue; } // if(netbuffer->packettype == PT_CLIENTJOIN) if( netbuffer->packettype == PT_SERVERSHUTDOWN && node==servernode && !server && cl_mode != cl_searching) { M_StartMessage("Server have Shutdown\n\nPress Esc",NULL,MM_NOTHING); CL_Reset(); D_StartTitle(); continue; } if( netbuffer->packettype == PT_NODETIMEOUT && node==servernode && !server && cl_mode != cl_searching) { M_StartMessage("Server Timeout\n\nPress Esc",NULL,MM_NOTHING); CL_Reset(); D_StartTitle(); continue; } if( netbuffer->packettype == PT_SERVERINFO ) { // compute ping in ms netbuffer->u.serverinfo.time = (I_GetTime()-netbuffer->u.serverinfo.time)*1000/TICRATE; netbuffer->u.serverinfo.servername[MAXSERVERNAME-1]=0; SL_InsertServer( &netbuffer->u.serverinfo, node); continue; } if(!nodeingame[node]) { if( node!=servernode ) DEBFILE(va("Received packet from unknow host %d\n",node)); // anyone trying to join ! switch(netbuffer->packettype) { case PT_ASKINFO: if(server && serverrunning) { SV_SendServerInfo(node, netbuffer->u.askinfo.time); Net_CloseConnection(node); } break; case PT_SERVERREFUSE : // negative responce of client join request if( cl_mode==cl_waitjoinresponce ) { M_StartMessage(va("Server refuse connection\n\nReason :\n%s" ,netbuffer->u.serverrefuse.reason), NULL, MM_NOTHING); CL_Reset(); D_StartTitle(); } break; case PT_SERVERCFG : // positive responce of client join request { int j; byte *p; if( cl_mode!=cl_waitjoinresponce ) break; if(!server) maketic = gametic = neededtic = netbuffer->u.servercfg.gametic;;#ifdef CLIENTPREDICTION2 localgametic = gametic;#endif nodeingame[(byte)servernode]=true; serverplayer = netbuffer->u.servercfg.serverplayer; doomcom->numplayers = SHORT(netbuffer->u.servercfg.totalplayernum); mynode = netbuffer->u.servercfg.clientnode; if (serverplayer>=0) playernode[(byte)serverplayer]=servernode; CONS_Printf("Join accepted, wait next map change...\n"); DEBFILE(va("Server accept join gametic=%d mynode=%d\n",gametic,mynode)); for(j=0;j<MAXPLAYERS;j++) playeringame[j]=(netbuffer->u.servercfg.playerdetected & (1<<j))!=0; p = netbuffer->u.servercfg.netcvarstates; CV_LoadNetVars( (char**)&p );#ifdef JOININGAME if( netbuffer->u.servercfg.gamestate == GS_LEVEL ) cl_mode = cl_downloadsavegame; else#endif cl_mode = cl_connected; break; } // handled in d_netfil.c case PT_FILEFRAGMENT : if( !server ) Got_Filetxpak(); break; case PT_REQUESTFILE : if( server ) Got_RequestFilePak(node); break; case PT_NODETIMEOUT: case PT_CLIENTQUIT: if( server ) Net_CloseConnection(node); break; case PT_SERVERTICS: // do not remove my own server (we have just get a out of order packet) if( node == servernode ) break; default: DEBFILE(va("unknow packet received (%d) from unknow host !\n",netbuffer->packettype)); Net_CloseConnection(node); break; // ignore it } // switch continue; //while } netconsole = nodetoplayer[node];#ifdef PARANOIA if(!(netconsole & DRONE) && netconsole>=MAXPLAYERS) I_Error("bad table nodetoplayer : node %d player %d" ,doomcom->remotenode,netconsole);#endif switch(netbuffer->packettype) {// -------------------------------------------- SERVER RECEIVE ---------- case PT_CLIENTCMD : case PT_CLIENT2CMD : case PT_CLIENTMIS : case PT_CLIENT2MIS : case PT_NODEKEEPALIVE : case PT_NODEKEEPALIVEMIS : if(!server) break; // to save bytes, only the low byte of tic numbers are sent // Figure out what the rest of the bytes are realstart = ExpandTics (netbuffer->u.clientpak.client_tic); realend = ExpandTics (netbuffer->u.clientpak.resendfrom); if( netbuffer->packettype==PT_CLIENTMIS || netbuffer->packettype==PT_CLIENT2MIS || netbuffer->packettype==PT_NODEKEEPALIVEMIS || supposedtics[node] < realend) { supposedtics[node] = realend; } // discard out of order packet if( nettics[node] > realend ) { DEBFILE(va("out of order ticcmd discarded nettics = %d\n",nettics[node])); break; } // update the nettics nettics[node] = realend; // don't do anything for drones just update there nettics if((netconsole & DRONE)!=0 || netconsole==-1 || netbuffer->packettype==PT_NODEKEEPALIVE || netbuffer->packettype==PT_NODEKEEPALIVEMIS) break; // check consistancy if(realstart<=gametic && realstart>gametic-BACKUPTICS+1 && consistancy[realstart%BACKUPTICS]!=netbuffer->u.clientpak.consistancy) {#if 1 char buf[3]; buf[0]=netconsole; buf[1]=KICK_MSG_CON_FAIL; SendNetXCmd(XD_KICK,&buf,2); DEBFILE(va("player %d kicked [%d] %d!=%d\n",netconsole,realstart,consistancy[realstart%BACKUPTICS],netbuffer->u.clientpak.consistancy));#else CONS_Printf("\2player %d kicked [%d] consistancy failure\n",netconsole,realstart);#endif } // copy ticcmd memcpy(&netcmds[maketic%BACKUPTICS][netconsole] ,&netbuffer->u.clientpak.cmd ,sizeof(ticcmd_t)); if( netbuffer->packettype==PT_CLIENT2CMD && nodetoplayer2[node]>=0) { memcpy(&netcmds[maketic%BACKUPTICS][(byte)nodetoplayer2[node]] ,&netbuffer->u.client2pak.cmd2 ,sizeof(ticcmd_t)); } break; case PT_TEXTCMD2 : // splitscreen special netconsole=nodetoplayer2[node]; case PT_TEXTCMD : if(!server) break; if( netconsole<0 || netconsole>=MAXPLAYERS ) Net_UnAcknowledgPacket(node); else { int j; tic_t tic=maketic; // check if tic that we are making isn't too large else we cannot send it :( // doomcom->numplayers+1 "+1" since doomcom->numplayers can change within this time and sent time
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -