• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 
21 #include "qwsvdef.h"
22 
23 server_static_t	svs;				// persistant server info
24 server_t		sv;					// local server
25 
26 char	localmodels[MAX_MODELS][5];	// inline model names for precache
27 
28 char localinfo[MAX_LOCALINFO_STRING+1]; // local game info
29 
30 /*
31 ================
32 SV_ModelIndex
33 
34 ================
35 */
SV_ModelIndex(char * name)36 int SV_ModelIndex (char *name)
37 {
38 	int		i;
39 
40 	if (!name || !name[0])
41 		return 0;
42 
43 	for (i=0 ; i<MAX_MODELS && sv.model_precache[i] ; i++)
44 		if (!strcmp(sv.model_precache[i], name))
45 			return i;
46 	if (i==MAX_MODELS || !sv.model_precache[i])
47 		SV_Error ("SV_ModelIndex: model %s not precached", name);
48 	return i;
49 }
50 
51 /*
52 ================
53 SV_FlushSignon
54 
55 Moves to the next signon buffer if needed
56 ================
57 */
SV_FlushSignon(void)58 void SV_FlushSignon (void)
59 {
60 	if (sv.signon.cursize < sv.signon.maxsize - 512)
61 		return;
62 
63 	if (sv.num_signon_buffers == MAX_SIGNON_BUFFERS-1)
64 		SV_Error ("sv.num_signon_buffers == MAX_SIGNON_BUFFERS-1");
65 
66 	sv.signon_buffer_size[sv.num_signon_buffers-1] = sv.signon.cursize;
67 	sv.signon.data = sv.signon_buffers[sv.num_signon_buffers];
68 	sv.num_signon_buffers++;
69 	sv.signon.cursize = 0;
70 }
71 
72 /*
73 ================
74 SV_CreateBaseline
75 
76 Entity baselines are used to compress the update messages
77 to the clients -- only the fields that differ from the
78 baseline will be transmitted
79 ================
80 */
SV_CreateBaseline(void)81 void SV_CreateBaseline (void)
82 {
83 	int			i;
84 	edict_t			*svent;
85 	int				entnum;
86 
87 	for (entnum = 0; entnum < sv.num_edicts ; entnum++)
88 	{
89 		svent = EDICT_NUM(entnum);
90 		if (svent->free)
91 			continue;
92 		// create baselines for all player slots,
93 		// and any other edict that has a visible model
94 		if (entnum > MAX_CLIENTS && !svent->v.modelindex)
95 			continue;
96 
97 	//
98 	// create entity baseline
99 	//
100 		VectorCopy (svent->v.origin, svent->baseline.origin);
101 		VectorCopy (svent->v.angles, svent->baseline.angles);
102 		svent->baseline.frame = svent->v.frame;
103 		svent->baseline.skinnum = svent->v.skin;
104 		if (entnum > 0 && entnum <= MAX_CLIENTS)
105 		{
106 			svent->baseline.colormap = entnum;
107 			svent->baseline.modelindex = SV_ModelIndex("progs/player.mdl");
108 		}
109 		else
110 		{
111 			svent->baseline.colormap = 0;
112 			svent->baseline.modelindex =
113 				SV_ModelIndex(PR_GetString(svent->v.model));
114 		}
115 
116 		//
117 		// flush the signon message out to a seperate buffer if
118 		// nearly full
119 		//
120 		SV_FlushSignon ();
121 
122 		//
123 		// add to the message
124 		//
125 		MSG_WriteByte (&sv.signon,svc_spawnbaseline);
126 		MSG_WriteShort (&sv.signon,entnum);
127 
128 		MSG_WriteByte (&sv.signon, svent->baseline.modelindex);
129 		MSG_WriteByte (&sv.signon, svent->baseline.frame);
130 		MSG_WriteByte (&sv.signon, svent->baseline.colormap);
131 		MSG_WriteByte (&sv.signon, svent->baseline.skinnum);
132 		for (i=0 ; i<3 ; i++)
133 		{
134 			MSG_WriteCoord(&sv.signon, svent->baseline.origin[i]);
135 			MSG_WriteAngle(&sv.signon, svent->baseline.angles[i]);
136 		}
137 	}
138 }
139 
140 
141 /*
142 ================
143 SV_SaveSpawnparms
144 
145 Grabs the current state of the progs serverinfo flags
146 and each client for saving across the
147 transition to another level
148 ================
149 */
SV_SaveSpawnparms(void)150 void SV_SaveSpawnparms (void)
151 {
152 	int		i, j;
153 
154 	if (!sv.state)
155 		return;		// no progs loaded yet
156 
157 	// serverflags is the only game related thing maintained
158 	svs.serverflags = pr_global_struct->serverflags;
159 
160 	for (i=0, host_client = svs.clients ; i<MAX_CLIENTS ; i++, host_client++)
161 	{
162 		if (host_client->state != cs_spawned)
163 			continue;
164 
165 		// needs to reconnect
166 		host_client->state = cs_connected;
167 
168 		// call the progs to get default spawn parms for the new client
169 		pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
170 		PR_ExecuteProgram (pr_global_struct->SetChangeParms);
171 		for (j=0 ; j<NUM_SPAWN_PARMS ; j++)
172 			host_client->spawn_parms[j] = (&pr_global_struct->parm1)[j];
173 	}
174 }
175 
176 /*
177 ================
178 SV_CalcPHS
179 
180 Expands the PVS and calculates the PHS
181 (Potentially Hearable Set)
182 ================
183 */
SV_CalcPHS(void)184 void SV_CalcPHS (void)
185 {
186 	int		rowbytes, rowwords;
187 	int		i, j, k, l, index, num;
188 	int		bitbyte;
189 	unsigned	*dest, *src;
190 	byte	*scan;
191 	int		count, vcount;
192 
193 	Con_Printf ("Building PHS...\n");
194 
195 	num = sv.worldmodel->numleafs;
196 	rowwords = (num+31)>>5;
197 	rowbytes = rowwords*4;
198 
199 	sv.pvs = Hunk_Alloc (rowbytes*num);
200 	scan = sv.pvs;
201 	vcount = 0;
202 	for (i=0 ; i<num ; i++, scan+=rowbytes)
203 	{
204 		memcpy (scan, Mod_LeafPVS(sv.worldmodel->leafs+i, sv.worldmodel),
205 			rowbytes);
206 		if (i == 0)
207 			continue;
208 		for (j=0 ; j<num ; j++)
209 		{
210 			if ( scan[j>>3] & (1<<(j&7)) )
211 			{
212 				vcount++;
213 			}
214 		}
215 	}
216 
217 
218 	sv.phs = Hunk_Alloc (rowbytes*num);
219 	count = 0;
220 	scan = sv.pvs;
221 	dest = (unsigned *)sv.phs;
222 	for (i=0 ; i<num ; i++, dest += rowwords, scan += rowbytes)
223 	{
224 		memcpy (dest, scan, rowbytes);
225 		for (j=0 ; j<rowbytes ; j++)
226 		{
227 			bitbyte = scan[j];
228 			if (!bitbyte)
229 				continue;
230 			for (k=0 ; k<8 ; k++)
231 			{
232 				if (! (bitbyte & (1<<k)) )
233 					continue;
234 				// or this pvs row into the phs
235 				// +1 because pvs is 1 based
236 				index = ((j<<3)+k+1);
237 				if (index >= num)
238 					continue;
239 				src = (unsigned *)sv.pvs + index*rowwords;
240 				for (l=0 ; l<rowwords ; l++)
241 					dest[l] |= src[l];
242 			}
243 		}
244 
245 		if (i == 0)
246 			continue;
247 		for (j=0 ; j<num ; j++)
248 			if ( ((byte *)dest)[j>>3] & (1<<(j&7)) )
249 				count++;
250 	}
251 
252 	Con_Printf ("Average leafs visible / hearable / total: %i / %i / %i\n"
253 		, vcount/num, count/num, num);
254 }
255 
SV_CheckModel(char * mdl)256 unsigned SV_CheckModel(char *mdl)
257 {
258 	byte	stackbuf[1024];		// avoid dirtying the cache heap
259 	byte *buf;
260 	unsigned short crc;
261 //	int len;
262 
263 	buf = (byte *)COM_LoadStackFile (mdl, stackbuf, sizeof(stackbuf));
264 	crc = CRC_Block(buf, com_filesize);
265 //	for (len = com_filesize; len; len--, buf++)
266 //		CRC_ProcessByte(&crc, *buf);
267 
268 	return crc;
269 }
270 
271 /*
272 ================
273 SV_SpawnServer
274 
275 Change the server to a new map, taking all connected
276 clients along with it.
277 
278 This is only called from the SV_Map_f() function.
279 ================
280 */
SV_SpawnServer(char * server)281 void SV_SpawnServer (char *server)
282 {
283 	edict_t		*ent;
284 	int			i;
285 
286 	Con_DPrintf ("SpawnServer: %s\n",server);
287 
288 	SV_SaveSpawnparms ();
289 
290 	svs.spawncount++;		// any partially connected client will be
291 							// restarted
292 
293 	sv.state = ss_dead;
294 
295 	Mod_ClearAll ();
296 	Hunk_FreeToLowMark (host_hunklevel);
297 
298 	// wipe the entire per-level structure
299 	memset (&sv, 0, sizeof(sv));
300 
301 	sv.datagram.maxsize = sizeof(sv.datagram_buf);
302 	sv.datagram.data = sv.datagram_buf;
303 	sv.datagram.allowoverflow = true;
304 
305 	sv.reliable_datagram.maxsize = sizeof(sv.reliable_datagram_buf);
306 	sv.reliable_datagram.data = sv.reliable_datagram_buf;
307 
308 	sv.multicast.maxsize = sizeof(sv.multicast_buf);
309 	sv.multicast.data = sv.multicast_buf;
310 
311 	sv.master.maxsize = sizeof(sv.master_buf);
312 	sv.master.data = sv.master_buf;
313 
314 	sv.signon.maxsize = sizeof(sv.signon_buffers[0]);
315 	sv.signon.data = sv.signon_buffers[0];
316 	sv.num_signon_buffers = 1;
317 
318 	strcpy (sv.name, server);
319 
320 	// load progs to get entity field count
321 	// which determines how big each edict is
322 	PR_LoadProgs ();
323 
324 	// allocate edicts
325 	sv.edicts = Hunk_AllocName (MAX_EDICTS*pr_edict_size, "edicts");
326 
327 	// leave slots at start for clients only
328 	sv.num_edicts = MAX_CLIENTS+1;
329 	for (i=0 ; i<MAX_CLIENTS ; i++)
330 	{
331 		ent = EDICT_NUM(i+1);
332 		svs.clients[i].edict = ent;
333 //ZOID - make sure we update frags right
334 		svs.clients[i].old_frags = 0;
335 	}
336 
337 	sv.time = 1.0;
338 
339 	strcpy (sv.name, server);
340 	sprintf (sv.modelname,"maps/%s.bsp", server);
341 	sv.worldmodel = Mod_ForName (sv.modelname, true);
342 	SV_CalcPHS ();
343 
344 	//
345 	// clear physics interaction links
346 	//
347 	SV_ClearWorld ();
348 
349 	sv.sound_precache[0] = pr_strings;
350 
351 	sv.model_precache[0] = pr_strings;
352 	sv.model_precache[1] = sv.modelname;
353 	sv.models[1] = sv.worldmodel;
354 	for (i=1 ; i<sv.worldmodel->numsubmodels ; i++)
355 	{
356 		sv.model_precache[1+i] = localmodels[i];
357 		sv.models[i+1] = Mod_ForName (localmodels[i], false);
358 	}
359 
360 	//check player/eyes models for hacks
361 	sv.model_player_checksum = SV_CheckModel("progs/player.mdl");
362 	sv.eyes_player_checksum = SV_CheckModel("progs/eyes.mdl");
363 
364 	//
365 	// spawn the rest of the entities on the map
366 	//
367 
368 	// precache and static commands can be issued during
369 	// map initialization
370 	sv.state = ss_loading;
371 
372 	ent = EDICT_NUM(0);
373 	ent->free = false;
374 	ent->v.model = PR_SetString(sv.worldmodel->name);
375 	ent->v.modelindex = 1;		// world model
376 	ent->v.solid = SOLID_BSP;
377 	ent->v.movetype = MOVETYPE_PUSH;
378 
379 	pr_global_struct->mapname = PR_SetString(sv.name);
380 	// serverflags are for cross level information (sigils)
381 	pr_global_struct->serverflags = svs.serverflags;
382 
383 	// run the frame start qc function to let progs check cvars
384 	SV_ProgStartFrame ();
385 
386 	// load and spawn all other entities
387 	ED_LoadFromFile (sv.worldmodel->entities);
388 
389 	// look up some model indexes for specialized message compression
390 	SV_FindModelNumbers ();
391 
392 	// all spawning is completed, any further precache statements
393 	// or prog writes to the signon message are errors
394 	sv.state = ss_active;
395 
396 	// run two frames to allow everything to settle
397 	host_frametime = 0.1;
398 	SV_Physics ();
399 	SV_Physics ();
400 
401 	// save movement vars
402 	SV_SetMoveVars();
403 
404 	// create a baseline for more efficient communications
405 	SV_CreateBaseline ();
406 	sv.signon_buffer_size[sv.num_signon_buffers-1] = sv.signon.cursize;
407 
408 	Info_SetValueForKey (svs.info, "map", sv.name, MAX_SERVERINFO_STRING);
409 	Con_DPrintf ("Server spawned.\n");
410 }
411 
412