1 //
2 // Copyright(C) 1993-1996 Id Software, Inc.
3 // Copyright(C) 2005-2014 Simon Howard
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // DESCRIPTION:
16 // DOOM Network game communication and protocol,
17 // all OS independend parts.
18 //
19
20 #include <stdlib.h>
21
22 #include "i_system.h"
23 #include "i_timer.h"
24 #include "i_video.h"
25 #include "doomdef.h"
26 #include "m_argv.h"
27 #include "m_misc.h"
28 #include "w_checksum.h"
29
30 #include "deh_main.h"
31
32 #include "d_loop.h"
33
34 ticcmd_t *netcmds;
35
36 extern void D_DoAdvanceDemo(void);
37 extern void D_ProcessEvents(void);
38 extern void G_BuildTiccmd(ticcmd_t *cmd, int maketic);
39 extern boolean G_CheckDemoStatus(void);
40
41 // Called when a player leaves the game
42
PlayerQuitGame(player_t * player)43 static void PlayerQuitGame(player_t *player)
44 {
45 static char exitmsg[80];
46 unsigned int player_num;
47
48 player_num = player - players;
49
50 // Note:
51 // The Heretic source code does this, which doesn't actually work.
52 // As a result, the exit message is never seen.
53
54 M_StringCopy(exitmsg, "PLAYER 1 LEFT THE GAME", sizeof(exitmsg));
55 exitmsg[7] += player_num;
56 players[consoleplayer].message = exitmsg;
57
58 playeringame[player_num] = false;
59 players[consoleplayer].message = exitmsg;
60
61 // [crispy] don't interpolate players who left the game
62 player->mo->interp = false;
63
64 // TODO: check if it is sensible to do this:
65
66 if (demorecording)
67 {
68 G_CheckDemoStatus ();
69 }
70 }
71
RunTic(ticcmd_t * cmds,boolean * ingame)72 static void RunTic(ticcmd_t *cmds, boolean *ingame)
73 {
74 extern boolean advancedemo;
75 unsigned int i;
76
77 // Check for player quits.
78
79 for (i = 0; i < MAXPLAYERS; ++i)
80 {
81 if (!demoplayback && playeringame[i] && !ingame[i])
82 {
83 PlayerQuitGame(&players[i]);
84 }
85 }
86
87 netcmds = cmds;
88
89 // check that there are players in the game. if not, we cannot
90 // run a tic.
91
92 if (advancedemo)
93 D_DoAdvanceDemo ();
94
95 G_Ticker ();
96 }
97
98 static loop_interface_t doom_loop_interface = {
99 D_ProcessEvents,
100 G_BuildTiccmd,
101 RunTic,
102 MN_Ticker
103 };
104
105
106 // Load game settings from the specified structure and
107 // set global variables.
108
LoadGameSettings(net_gamesettings_t * settings)109 static void LoadGameSettings(net_gamesettings_t *settings)
110 {
111 unsigned int i;
112
113 deathmatch = settings->deathmatch;
114 ticdup = settings->ticdup;
115 startepisode = settings->episode;
116 startmap = settings->map;
117 startskill = settings->skill;
118 // TODO startloadgame = settings->loadgame;
119 lowres_turn = settings->lowres_turn;
120 nomonsters = settings->nomonsters;
121 respawnparm = settings->respawn_monsters;
122 consoleplayer = settings->consoleplayer;
123
124 if (lowres_turn)
125 {
126 printf("NOTE: Turning resolution is reduced; this is probably "
127 "because there is a client recording a Vanilla demo.\n");
128 }
129
130 for (i = 0; i < MAXPLAYERS; ++i)
131 {
132 playeringame[i] = i < settings->num_players;
133 }
134 }
135
136 // Save the game settings from global variables to the specified
137 // game settings structure.
138
SaveGameSettings(net_gamesettings_t * settings)139 static void SaveGameSettings(net_gamesettings_t *settings)
140 {
141 // Fill in game settings structure with appropriate parameters
142 // for the new game
143
144 settings->deathmatch = deathmatch;
145 settings->episode = startepisode;
146 settings->map = startmap;
147 settings->skill = startskill;
148 // TODO settings->loadgame = startloadgame;
149 settings->gameversion = exe_heretic_1_3;
150 settings->nomonsters = nomonsters;
151 settings->respawn_monsters = respawnparm;
152 settings->timelimit = 0;
153
154 settings->lowres_turn = M_ParmExists("-record")
155 && !M_ParmExists("-longtics");
156 }
157
InitConnectData(net_connect_data_t * connect_data)158 static void InitConnectData(net_connect_data_t *connect_data)
159 {
160 connect_data->drone = false;
161 connect_data->max_players = MAXPLAYERS;
162
163 //
164 // Connect data
165 //
166
167 // Game type fields:
168
169 connect_data->gamemode = gamemode;
170 connect_data->gamemission = heretic;
171
172 // Are we recording a demo? Possibly set lowres turn mode
173
174 connect_data->lowres_turn = M_ParmExists("-record")
175 && !M_ParmExists("-longtics");
176
177 // Read checksums of our WAD directory and dehacked information
178
179 W_Checksum(connect_data->wad_sha1sum);
180 DEH_Checksum(connect_data->deh_sha1sum);
181
182 connect_data->is_freedoom = 0;
183 }
184
D_ConnectNetGame(void)185 void D_ConnectNetGame(void)
186 {
187 net_connect_data_t connect_data;
188
189 InitConnectData(&connect_data);
190 netgame = D_InitNetGame(&connect_data);
191
192 //!
193 // @category net
194 //
195 // Start the game playing as though in a netgame with a single
196 // player. This can also be used to play back single player netgame
197 // demos.
198 //
199
200 if (M_CheckParm("-solo-net") > 0)
201 {
202 netgame = true;
203 }
204 }
205
206 //
207 // D_CheckNetGame
208 // Works out player numbers among the net participants
209 //
210
D_CheckNetGame(void)211 void D_CheckNetGame (void)
212 {
213 net_gamesettings_t settings;
214
215 D_RegisterLoopCallbacks(&doom_loop_interface);
216
217 if (netgame)
218 {
219 autostart = true;
220 }
221
222 SaveGameSettings(&settings);
223 D_StartNetGame(&settings, NULL);
224 LoadGameSettings(&settings);
225 }
226
227