📄 d_clisrv.c
字号:
j=software_MAXPACKETLENGTH-(netbuffer->u.textcmd[0]+2+BASESERVERTICSSIZE+(doomcom->numplayers+1)*sizeof(ticcmd_t)); // search a tic that have enougth space in the ticcmd while((TotalTextCmdPerTic(tic)>j || netbuffer->u.textcmd[0]+textcmds[tic % BACKUPTICS][netconsole][0]>MAXTEXTCMD) && tic<firstticstosend+BACKUPTICS) tic++; if(tic>=firstticstosend+BACKUPTICS) { DEBFILE(va("GetPacket: Too much textcmd (max %d, used %d, mak %d,tosend %d,node %d, player %d)\n",j,TotalTextCmdPerTic(maketic),maketic,firstticstosend,node,netconsole)); Net_UnAcknowledgPacket(node); break; } DEBFILE(va("textcmd put in tic %d at position %d (player %d) ftts %d mk %d\n",tic,textcmds[p][netconsole][0]+1,netconsole,firstticstosend,maketic)); p=tic % BACKUPTICS; memcpy(&textcmds[p][netconsole][textcmds[p][netconsole][0]+1] ,netbuffer->u.textcmd+1 ,netbuffer->u.textcmd[0]); textcmds[p][netconsole][0]+=netbuffer->u.textcmd[0]; } break; case PT_NODETIMEOUT: case PT_CLIENTQUIT: if(!server) break; // nodeingame will be put false in the execution of kick command // this allow to send some packets to the quiting client to have there ack back nodewaiting[node]= 0; if(netconsole!=-1 && playeringame[netconsole]) { char buf[2]; buf[0]=netconsole; if( netbuffer->packettype == PT_NODETIMEOUT ) buf[1]=KICK_MSG_TIMEOUT; else buf[1]=KICK_MSG_PLAYER_QUIT; SendNetXCmd(XD_KICK,&buf,2); nodetoplayer[node]=-1; if(nodetoplayer2[node]!=-1 && nodetoplayer2[node]>=0 && playeringame[(byte)nodetoplayer2[node]]) { buf[0]=nodetoplayer2[node]; SendNetXCmd(XD_KICK,&buf,2); nodetoplayer2[node]=-1; } } Net_CloseConnection(node); nodeingame[node]=false; break;// -------------------------------------------- CLIENT RECEIVE ---------- case PT_SERVERTICS : realstart = ExpandTics (netbuffer->u.serverpak.starttic); realend = realstart+netbuffer->u.serverpak.numtics; txtpak=(char *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numplayers*netbuffer->u.serverpak.numtics]; if( realend>gametic+BACKUPTICS ) realend=gametic+BACKUPTICS; cl_packetmissed=realstart>neededtic; if(realstart<=neededtic && realend>neededtic) { tic_t i,j; pak=(char *)&netbuffer->u.serverpak.cmds; for(i=realstart;i<realend;i++) { // clear first D_Clearticcmd(i); // copy the tics memcpy(netcmds[i%BACKUPTICS] ,pak ,netbuffer->u.serverpak.numplayers*sizeof(ticcmd_t)); pak+=netbuffer->u.serverpak.numplayers*sizeof(ticcmd_t); // copy the textcmds numtxtpak=*txtpak++; for(j=0;j<numtxtpak;j++) { int k=*txtpak++; // playernum memcpy(textcmds[i%BACKUPTICS][k] ,txtpak ,txtpak[0]+1); txtpak+=txtpak[0]+1; } } neededtic=realend; } else DEBFILE(va("frame not in bound : %u\n", neededtic)); break; case PT_SERVERCFG : break; case PT_FILEFRAGMENT : if( !server ) Got_Filetxpak(); break; default: DEBFILE(va("UNKNOW PACKET TYPE RECEIVED %f from host %d\n",netbuffer->packettype,node)); } // end switch } // end while}//// NetUpdate// Builds ticcmds for console player,// sends out a packet//// no more use random generator, because at very first tic isn't yet synchronizedstatic short Consistancy(void){ short ret=0; int i; DEBFILE(va("TIC %d ",gametic)); for(i=0;i<MAXPLAYERS;i++) if( playeringame[i] && players[i].mo ) { DEBFILE(va("p[%d].x = %f ",i,FIXED_TO_FLOAT(players[i].mo->x))); ret+=players[i].mo->x; } DEBFILE(va("pos = %d, rnd %d\n",ret,P_GetRandIndex())); ret+=P_GetRandIndex(); return ret;}// send the client packet to the serverstatic void CL_SendClientCmd (void){/* oops can do that until i have implemented a real dead reckoning static ticcmd_t lastcmdssent; static int lastsenttime=-TICRATE; if( memcmp(&localcmds,&lastcmdssent,sizeof(ticcmd_t))!=0 || lastsenttime+TICRATE/3<I_GetTime()) { lastsenttime=I_GetTime();*/ int packetsize=0; netbuffer->packettype=PT_CLIENTCMD; if (cl_packetmissed) netbuffer->packettype++; netbuffer->u.clientpak.resendfrom = neededtic; netbuffer->u.clientpak.client_tic = gametic; if(gamestate==GS_WAITINGPLAYERS) { // send NODEKEEPALIVE packet netbuffer->packettype+=4; packetsize = sizeof(clientcmd_pak)-sizeof(ticcmd_t)-sizeof(short); HSendPacket (servernode,false,0,packetsize); } else if( gamestate!=GS_NULL ) { memcpy(&netbuffer->u.clientpak.cmd, &localcmds, sizeof(ticcmd_t)); netbuffer->u.clientpak.consistancy = consistancy[gametic%BACKUPTICS]; // send a special packet with 2 cmd for splitscreen if (cv_splitscreen.value) { netbuffer->packettype+=2; memcpy(&netbuffer->u.client2pak.cmd2, &localcmds2, sizeof(ticcmd_t)); packetsize = sizeof(client2cmd_pak); } else packetsize = sizeof(clientcmd_pak); HSendPacket (servernode,false,0,packetsize); } if( cl_mode == cl_connected ) { // send extra data if needed if (localtextcmd[0]) { netbuffer->packettype=PT_TEXTCMD; memcpy(netbuffer->u.textcmd,localtextcmd,localtextcmd[0]+1); // all extra data have been sended if( HSendPacket(servernode,true,0,localtextcmd[0]+1) ) // send can fail for some reasons... localtextcmd[0]=0; } // send extra data if needed for player 2 (splitscreen) if (localtextcmd2[0]) { netbuffer->packettype=PT_TEXTCMD2; memcpy(netbuffer->u.textcmd,localtextcmd2,localtextcmd2[0]+1); // all extra data have been sended if( HSendPacket(servernode,true,0,localtextcmd2[0]+1) ) // send can fail for some reasons... localtextcmd2[0]=0; } }}// send the server packet// send tic from firstticstosend to maketic-1static void SV_SendTics (void){ tic_t realfirsttic,lasttictosend,i; ULONG n; int j,packsize; char *bufpos; char *ntextcmd; // send to all client but not to me // for eatch node create a packet with x tics and send it // x is computed using supposedtics[n], max packet size and maketic for(n=1;n<MAXNETNODES;n++) if( nodeingame[n] ) { lasttictosend=maketic; // assert supposedtics[n]>=nettics[n] realfirsttic = supposedtics[n]; if(realfirsttic>=maketic) { // well we have sent all tics we will so use extrabandwidth // to resent packet that are supposed lost (this is necessary since lost // packet detection work when we have received packet with firsttic>neededtic // (getpacket servertics case) DEBFILE(va("Nothing to send node %d mak=%u sup=%u net=%u \n", n, maketic, supposedtics[n], nettics[n])); realfirsttic = nettics[n]; if( realfirsttic >= maketic || (I_GetTime()+n)&3) // all tic are ok continue; DEBFILE(va("Sent %d anyway\n", realfirsttic)); } if( realfirsttic<firstticstosend ) realfirsttic=firstticstosend; // compute the lenght of the packet and cut it if too large packsize=BASESERVERTICSSIZE; for(i=realfirsttic;i<lasttictosend;i++) { packsize+=sizeof(ticcmd_t)*doomcom->numplayers; packsize+=TotalTextCmdPerTic(i); if(packsize>software_MAXPACKETLENGTH) { DEBFILE(va("packet too large (%d) at tic %d (should be from %d to %d)\n", packsize, i, realfirsttic, lasttictosend)); lasttictosend=i; // too bad : too much player have send extradata and there is too // mutch data in one tic. // Too avoid it put the data on the next tic. (see getpacket // textcmd case) but when numplayer chang the computation can be different if(lasttictosend==realfirsttic) { if( packsize>MAXPACKETLENGTH ) I_Error("Too mush players can't send %d data for %d players to node %d\n" "Well sorry nobody is perfect....\n", packsize, doomcom->numplayers, n); else { lasttictosend++; // send it anyway ! DEBFILE("sending it anyway\n"); } } break; } } // Send the tics netbuffer->packettype=PT_SERVERTICS; netbuffer->u.serverpak.starttic=realfirsttic; netbuffer->u.serverpak.numtics=lasttictosend-realfirsttic; netbuffer->u.serverpak.numplayers=SHORT(doomcom->numplayers); bufpos=(char *)&netbuffer->u.serverpak.cmds; for(i=realfirsttic;i<lasttictosend;i++) { memcpy(bufpos ,netcmds[i%BACKUPTICS] ,doomcom->numplayers*sizeof(ticcmd_t)); bufpos+=doomcom->numplayers*sizeof(ticcmd_t); } // add textcmds for(i=realfirsttic;i<lasttictosend;i++) { ntextcmd=bufpos++; *ntextcmd=0; for(j=0;j<MAXPLAYERS;j++) { int size=textcmds[i%BACKUPTICS][j][0]; if(((j==0) || playeringame[j]) && size) { (*ntextcmd)++; *bufpos++ = j; memcpy(bufpos,textcmds[i%BACKUPTICS][j],size+1); bufpos += size+1; } } } packsize = bufpos - (char *)&(netbuffer->u); HSendPacket(n,false,0,packsize); // when tic are too large, only one tic is sent so don't go backward ! if( lasttictosend-doomcom->extratics > realfirsttic ) supposedtics[n] = lasttictosend-doomcom->extratics; else supposedtics[n] = lasttictosend; if( supposedtics[n] < nettics[n] ) supposedtics[n] = nettics[n]; } // node 0 is me ! supposedtics[0] = maketic;}//// TryRunTics//static void Local_Maketic(int realtics){ I_OsPolling(); // i_getevent D_ProcessEvents (); // menu responder ???!!! // Cons responder // game responder call : // HU_responder,St_responder, Am_responder // F_responder (final) // and G_MapEventsToControls rendergametic=gametic; // translate inputs (keyboard/mouse/joystick) into game controls G_BuildTiccmd (&localcmds,realtics); if (cv_splitscreen.value) G_BuildTiccmd2(&localcmds2,realtics);#ifdef CLIENTPREDICTION2 if( !paused && localgametic<gametic+BACKUPTICS) { P_MoveSpirit ( &players[consoleplayer], &localcmds, realtics ); localgametic+=realtics; }#endif localcmds.angleturn |= TICCMD_RECEIVED;}void SV_SpawnPlayer(int playernum, int x, int y, angle_t angle){ // for futur copytic use the good x,y and angle! if( server ) {#ifdef CLIENTPREDICTION2 netcmds[maketic%BACKUPTICS][playernum].x=x; netcmds[maketic%BACKUPTICS][playernum].y=y;#endif netcmds[maketic%BACKUPTICS][playernum].angleturn=(angle>>16) | TICCMD_RECEIVED; }}// create missed ticvoid SV_Maketic(void){ int j; for(j=0;j<MAXNETNODES;j++) if(playerpernode[j]) { int player=nodetoplayer[j]; if((netcmds[maketic%BACKUPTICS][player].angleturn & TICCMD_RECEIVED) == 0) // we don't received this tic { int i; DEBFILE(va("MISS tic%4u for node %d\n",maketic,j));#ifdef PARANOIA if( devparm ) CONS_Printf("\2Client Misstic %d\n",maketic);#endif // copy the old tic for(i=0;i<playerpernode[j];i++,player=nodetoplayer2[j]) { netcmds[maketic%BACKUPTICS][player] = netcmds[(maketic-1)%BACKUPTICS][player]; netcmds[maketic%BACKUPTICS][player].angleturn &=~TICCMD_RECEIVED; } } } // all tic are now proceed make the next maketic++;}extern boolean advancedemo;static int load;void TryRunTics (tic_t realtics){ // the machine have laged but is not so bad if(realtics>TICRATE/7) { if(server) realtics=1; else realtics=TICRATE/7; } if(singletics) realtics = 1; if( realtics>= 1) COM_BufExecute(); NetUpdate(); if(demoplayback) { neededtic = gametic + realtics + cv_playdemospeed.value; // start a game after a demo maketic+=realtics; firstticstosend=maketic; tictoclear=firstticstosend; }#ifdef DEBUGFILE if(realtics==0) if(load) load--;#endif GetPackets ();#ifdef DEBUGFILE if (debugfile && (realtics || neededtic>gam
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -