ref: ab6ecc6404515d6c400b6dc4c3a185df5aca8344
dir: /src/d_net.c/
// Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // // $Id: d_net.c 381 2006-02-23 20:22:57Z fraggle $ // // Copyright(C) 1993-1996 Id Software, Inc. // Copyright(C) 2005 Simon Howard // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // 02111-1307, USA. // // $Log$ // Revision 1.20 2006/02/23 20:22:57 fraggle // Do not allow tics to buffer up in single player (stops the gun instantly // appearing on level start) // // Revision 1.19 2006/02/23 19:12:43 fraggle // Set maketic-gametic lag back to 1 second. // // Revision 1.18 2006/02/23 19:12:01 fraggle // Add lowres_turn to indicate whether we generate angleturns which are // 8-bit as opposed to 16-bit. This is used when recording demos without // -longtics enabled. Sync this option between clients in a netgame, so // that if one player is recording a Vanilla demo, all clients record // in lowres. // // Revision 1.17 2006/02/19 13:42:27 fraggle // Move tic number expansion code to common code. Parse game data packets // received from the server. // Strip down d_net.[ch] to work through the new networking code. Remove // game sync code. // Remove i_net.[ch] as it is no longer needed. // Working networking! // // Revision 1.16 2006/01/13 23:56:00 fraggle // Add text-mode I/O functions. // Use text-mode screen for the waiting screen. // // Revision 1.15 2006/01/02 21:04:10 fraggle // Create NET_SV_Shutdown function to shut down the server. Call it // when quitting the game. Print the IP of the server correctly when // connecting. // // Revision 1.14 2006/01/02 20:14:29 fraggle // Add a "-client" option to test connecting to a local server. // // Revision 1.13 2006/01/02 00:17:42 fraggle // Encapsulate the event queue code properly. Add a D_PopEvent function // to read a new event from the event queue. // // Revision 1.12 2006/01/02 00:00:08 fraggle // Neater prefixes: NET_Client -> NET_CL_. NET_Server -> NET_SV_. // // Revision 1.11 2006/01/01 23:54:31 fraggle // Client disconnect code // // Revision 1.10 2006/01/01 23:53:15 fraggle // Remove GS_WAITINGSTART gamestate. This will be independent of the main // loop to avoid interfering with the main game code too much. // // Revision 1.9 2005/12/30 18:58:22 fraggle // Fix client code to correctly send reply to server on connection. // Add "waiting screen" while waiting for the game to start. // Hook in the new networking code into the main game code. // // Revision 1.8 2005/09/22 13:13:47 fraggle // Remove external statistics driver support (-statcopy): // nonfunctional on modern systems and never used. // Fix for systems where sizeof(int) != sizeof(void *) // // Revision 1.7 2005/09/08 22:10:40 fraggle // Delay calls so we don't use the entire CPU // // Revision 1.6 2005/09/04 18:44:22 fraggle // shut up compiler warnings // // Revision 1.5 2005/08/31 21:24:24 fraggle // Remove the last traces of NORMALUNIX // // Revision 1.4 2005/08/04 22:55:07 fraggle // Use DOOM_VERSION to define the Doom version (don't conflict with // automake's config.h). Display GPL message instead of anti-piracy // messages. // // Revision 1.3 2005/07/23 19:17:11 fraggle // Use ANSI-standard limit constants. Remove LINUX define. // // Revision 1.2 2005/07/23 16:44:55 fraggle // Update copyright to GNU GPL // // Revision 1.1.1.1 2005/07/23 16:20:50 fraggle // Initial import // // // DESCRIPTION: // DOOM Network game communication and protocol, // all OS independend parts. // //----------------------------------------------------------------------------- static const char rcsid[] = "$Id: d_net.c 381 2006-02-23 20:22:57Z fraggle $"; #include "d_main.h" #include "m_argv.h" #include "m_menu.h" #include "i_system.h" #include "i_video.h" #include "g_game.h" #include "doomdef.h" #include "doomstat.h" #include "net_client.h" #include "net_gui.h" #include "net_io.h" #include "net_server.h" #include "net_sdl.h" #include "net_loop.h" #define NCMD_EXIT 0x80000000 #define NCMD_RETRANSMIT 0x40000000 #define NCMD_SETUP 0x20000000 #define NCMD_KILL 0x10000000 // kill game #define NCMD_CHECKSUM 0x0fffffff doomcom_t* doomcom; // // NETWORKING // // gametic is the tic about to (or currently being) run // maketic is the tick that hasn't had control made for it yet // nettics[] has the maketics for all players // // a gametic cannot be run until nettics[] > gametic for all players // #define RESENDCOUNT 10 #define PL_DRONE 0x80 // bit flag in doomdata->player ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS]; int nettics[MAXPLAYERS]; int maketic; int lastnettic; int ticdup; int maxsend; // BACKUPTICS/(2*ticdup)-1 void D_ProcessEvents (void); void G_BuildTiccmd (ticcmd_t *cmd); void D_DoAdvanceDemo (void); // // NetUpdate // Builds ticcmds for console player, // sends out a packet // int gametime; void NetUpdate (void) { int nowtime; int newtics; int i,j; int realstart; int gameticdiv; // Temporary hack - hook new client/server code into Doom NET_CL_Run(); NET_SV_Run(); // check time nowtime = I_GetTime ()/ticdup; newtics = nowtime - gametime; gametime = nowtime; if (newtics <= 0) // nothing new to update return; // build new ticcmds for console player gameticdiv = gametic/ticdup; for (i=0 ; i<newtics ; i++) { ticcmd_t cmd; // If playing single player, do not allow tics to buffer // up very far if ((!netgame || demoplayback) && maketic - gameticdiv > 2) break; // Never go more than a second ahead if (maketic - gameticdiv > 35) break; I_StartTic (); D_ProcessEvents (); //printf ("mk:%i ",maketic); G_BuildTiccmd(&cmd); if (netgame && !demoplayback) { NET_CL_SendTiccmd(&cmd, maketic); } netcmds[consoleplayer][maketic % BACKUPTICS] = cmd; ++maketic; nettics[consoleplayer] = maketic; } } // // D_CheckNetGame // Works out player numbers among the net participants // extern int viewangleoffset; void D_CheckNetGame (void) { net_addr_t *addr = NULL; int i; int num_players; // default values for single player consoleplayer = 0; netgame = false; ticdup = 1; lowres_turn = false; for (i=0; i<MAXPLAYERS; i++) { playeringame[i] = false; nettics[i] = 0; } playeringame[0] = true; // temporary hack if (M_CheckParm("-server") > 0) { NET_SV_Init(); addr = net_loop_client_module.ResolveAddress(""); } if (M_CheckParm("-client") > 0) { addr = net_sdl_module.ResolveAddress("localhost"); } if (addr != NULL) { if (NET_CL_Connect(addr)) { printf("connected to %s\n", NET_AddrToString(addr)); NET_WaitForStart(); } else { printf("failed to connect\n"); } } num_players = 0; for (i=0; i<MAXPLAYERS; ++i) { if (playeringame[i]) ++num_players; } printf ("startskill %i deathmatch: %i startmap: %i startepisode: %i\n", startskill, deathmatch, startmap, startepisode); printf ("player %i of %i (%i nodes)\n", consoleplayer+1, num_players, num_players); } // // D_QuitNetGame // Called before quitting to leave a net game // without hanging the other players // void D_QuitNetGame (void) { int i, j; if (debugfile) fclose (debugfile); NET_SV_Shutdown(); NET_CL_Disconnect(); } static int GetLowTic(void) { int i; int lowtic; if (demoplayback) { lowtic = maketic; } else { lowtic = INT_MAX; for (i=0; i<MAXPLAYERS; ++i) { if (playeringame[i]) { if (nettics[i] < lowtic) lowtic = nettics[i]; } } } return lowtic; } // // TryRunTics // int oldnettics; extern boolean advancedemo; void TryRunTics (void) { int i; int lowtic; int entertic; static int oldentertics; int realtics; int availabletics; int counts; // get real tics entertic = I_GetTime ()/ticdup; realtics = entertic - oldentertics; oldentertics = entertic; // get available tics NetUpdate (); lowtic = GetLowTic(); availabletics = lowtic - gametic/ticdup; // decide how many tics to run if (realtics < availabletics-1) counts = realtics+1; else if (realtics < availabletics) counts = realtics; else counts = availabletics; if (counts < 1) counts = 1; if (debugfile) fprintf (debugfile, "=======real: %i avail: %i game: %i\n", realtics, availabletics,counts); // wait for new tics if needed while (lowtic < gametic/ticdup + counts) { NetUpdate (); lowtic = GetLowTic(); if (lowtic < gametic/ticdup) I_Error ("TryRunTics: lowtic < gametic"); // don't stay in here forever -- give the menu a chance to work if (I_GetTime ()/ticdup - entertic >= 20) { M_Ticker (); return; } I_Sleep(1); } // run the count * ticdup dics while (counts--) { for (i=0 ; i<ticdup ; i++) { if (gametic/ticdup > lowtic) I_Error ("gametic>lowtic"); if (advancedemo) D_DoAdvanceDemo (); M_Ticker (); G_Ticker (); gametic++; // modify command for duplicated tics if (i != ticdup-1) { ticcmd_t *cmd; int buf; int j; buf = (gametic/ticdup)%BACKUPTICS; for (j=0 ; j<MAXPLAYERS ; j++) { cmd = &netcmds[j][buf]; cmd->chatchar = 0; if (cmd->buttons & BT_SPECIAL) cmd->buttons = 0; } } } NetUpdate (); // check for new console commands } }