コード例 #1
0
ファイル: cl_parse.c プロジェクト: Rinnegatamante/vitaQuake
/*
==================
CL_KeepaliveMessage

When the client is taking a long time to load stuff, send keepalive messages
so the server doesn't disconnect.
==================
*/
void CL_KeepaliveMessage (void)
{
	float	time;
	static float lastmsg;
	int		ret;
	sizebuf_t	old;
	byte*	olddata;

	if (sv.active)
		return;		// no need if server is local
	if (cls.demoplayback)
		return;

// read messages from server, should just be nops
	old = net_message;
	olddata = Sys_BigStackAlloc(8192 * sizeof(byte), "CL_KeepaliveMessage");
	memcpy (olddata, net_message.data, net_message.cursize);

	do
	{
		ret = CL_GetMessage ();
		switch (ret)
		{
		default:
			Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");
		case 0:
			break;	// nothing waiting
		case 1:
			Host_Error ("CL_KeepaliveMessage: received a message");
			break;
		case 2:
			if (MSG_ReadByte() != svc_nop)
				Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
			break;
		}
	} while (ret);

	net_message = old;
	memcpy (net_message.data, olddata, net_message.cursize);

// check time
	time = Sys_FloatTime ();
	if (time - lastmsg < 5)
	{
		Sys_BigStackFree(8192 * sizeof(byte), "CL_KeepaliveMessage");
		return;
	}
	lastmsg = time;

// write out a nop
	Con_Printf ("--> client to server keepalive\n");

	MSG_WriteByte (&cls.message, clc_nop);
	NET_SendMessage (cls.netcon, &cls.message);
	SZ_Clear (&cls.message);

	Sys_BigStackFree(8192 * sizeof(byte), "CL_KeepaliveMessage");
}
コード例 #2
0
ファイル: host.c プロジェクト: Rinnegatamante/vitaQuake
/*
================
Host_EndGame
================
*/
void Host_EndGame (char *message, ...)
{
	va_list		argptr;
	char*		string = Sys_BigStackAlloc(1024, "Host_EndGame");

	va_start (argptr,message);
	vsprintf (string,message,argptr);
	va_end (argptr);
	Con_DPrintf ("Host_EndGame: %s\n",string);

	if (sv.active)
		Host_ShutdownServer (false);

	if (cls.state == ca_dedicated)
		Sys_Error ("Host_EndGame: %s\n",string);	// dedicated servers exit

	Sys_BigStackFree(1024, "Host_EndGame");

	if (cls.demonum != -1)
	{
		CL_StopPlayback();
		CL_NextDemo();
	}
	else
		CL_Disconnect ();

	longjmp (host_abortserver, 1);
}
コード例 #3
0
ファイル: host.c プロジェクト: Rinnegatamante/vitaQuake
/*
================
Host_Error

This shuts down both the client and server
================
*/
void Host_Error (char *error, ...)
{
	va_list		argptr;
	char*		string;
	static	bool inerror = false;

	if (inerror)
		Sys_Error ("Host_Error: recursively entered");
	inerror = true;

	SCR_EndLoadingPlaque ();		// reenable screen updates

	string = Sys_BigStackAlloc(1024, "Host_Error");

	va_start (argptr,error);
	vsprintf (string,error,argptr);
	va_end (argptr);
	Con_Printf ("Host_Error: %s\n",string);

	if (sv.active)
		Host_ShutdownServer (false);

	if (cls.state == ca_dedicated)
		Sys_Error ("Host_Error: %s\n",string);	// dedicated servers exit

	Sys_BigStackFree(1024, "Host_Error");

	CL_Disconnect ();
	cls.demonum = -1;

	inerror = false;

	longjmp (host_abortserver, 1);
}
コード例 #4
0
ファイル: sv_main.c プロジェクト: Rinnegatamante/vitaQuake
/*
================
SV_SendServerinfo

Sends the first message from the server to a connected client.
This will be sent on the initial connection and upon each server load.
================
*/
void SV_SendServerinfo (client_t *client)
{
    char			**s;
    char*			message = Sys_BigStackAlloc(2048, "SV_SendServerinfo");

    if (svs.maxclients > 1)
    {
        MSG_WriteByte(&client->message, svc_print);
        snprintf(message, sizeof(message), "\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n"
                 "\n   \01\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\03");
        MSG_WriteString(&client->message, message);
        MSG_WriteByte(&client->message, svc_print);
        snprintf(message, sizeof(message), "\02\n   \04ProQuake Server Version %4.2f\06"
                 "\n   \07\10\10\10\10\10\10\10\10\10\10\10\10\10\10\10\10\10\10\10\10\10\10\10\10\10\10\10\10\11", VERSION_PROQUAKE);
        MSG_WriteString(&client->message, message);
    }

    MSG_WriteByte (&client->message, svc_serverinfo);
    MSG_WriteLong (&client->message, PROTOCOL_NETQUAKE);
    MSG_WriteByte (&client->message, svs.maxclients);

    if (!coop.value && deathmatch.value)
        MSG_WriteByte (&client->message, GAME_DEATHMATCH);
    else
        MSG_WriteByte (&client->message, GAME_COOP);

    sprintf (message, pr_strings+sv.edicts->v.message);

    MSG_WriteString (&client->message,message);

    for (s = sv.model_precache+1 ; *s ; s++)
        MSG_WriteString (&client->message, *s);
    MSG_WriteByte (&client->message, 0);

    for (s = sv.sound_precache+1 ; *s ; s++)
        MSG_WriteString (&client->message, *s);
    MSG_WriteByte (&client->message, 0);

// send music
    MSG_WriteByte (&client->message, svc_cdtrack);
    MSG_WriteByte (&client->message, sv.edicts->v.sounds);
    MSG_WriteByte (&client->message, sv.edicts->v.sounds);

// set view
    MSG_WriteByte (&client->message, svc_setview);
    MSG_WriteShort (&client->message, NUM_FOR_EDICT(client->edict));

    if (!pq_fullpitch.value && client->netconnection->proquake_connection != MOD_QSMACK) {	// Ch0wW: Re-add it
        MSG_WriteByte(&client->message, svc_stufftext);
        MSG_WriteString(&client->message, "pq_fullpitch 0; cl_fullpitch 0\n");
    }

    MSG_WriteByte (&client->message, svc_signonnum);
    MSG_WriteByte (&client->message, 1);

    client->sendsignon = true;
    client->spawned = false;		// need prespawn, spawn, etc
    Sys_BigStackFree(2048, "SV_SendServerinfo");
}
コード例 #5
0
ファイル: sv_main.c プロジェクト: Izhido/qrevpak
/*
================
SV_SendServerinfo

Sends the first message from the server to a connected client.
This will be sent on the initial connection and upon each server load.
================
*/
void SV_SendServerinfo (client_t *client)
{
	char			**s;
// >>> FIX: For Nintendo Wii using devkitPPC / libogc
// Allocating in big stack. Stack in this device is pretty small:
	//char			message[2048];
	char*			message = Sys_BigStackAlloc(2048, "SV_SendServerinfo");
// <<< FIX

	MSG_WriteByte (&client->message, svc_print);
	sprintf (message, "%c\nVERSION %4.2f SERVER (%i CRC)", 2, VERSION, pr_crc);
	MSG_WriteString (&client->message,message);

	MSG_WriteByte (&client->message, svc_serverinfo);
	MSG_WriteLong (&client->message, PROTOCOL_VERSION);
	MSG_WriteByte (&client->message, svs.maxclients);

	if (!coop.value && deathmatch.value)
		MSG_WriteByte (&client->message, GAME_DEATHMATCH);
	else
		MSG_WriteByte (&client->message, GAME_COOP);

	sprintf (message, pr_strings+sv.edicts->v.message);

	MSG_WriteString (&client->message,message);

	for (s = sv.model_precache+1 ; *s ; s++)
		MSG_WriteString (&client->message, *s);
	MSG_WriteByte (&client->message, 0);

	for (s = sv.sound_precache+1 ; *s ; s++)
		MSG_WriteString (&client->message, *s);
	MSG_WriteByte (&client->message, 0);

// send music
	MSG_WriteByte (&client->message, svc_cdtrack);
	MSG_WriteByte (&client->message, sv.edicts->v.sounds);
	MSG_WriteByte (&client->message, sv.edicts->v.sounds);

// set view	
	MSG_WriteByte (&client->message, svc_setview);
	MSG_WriteShort (&client->message, NUM_FOR_EDICT(client->edict));

	MSG_WriteByte (&client->message, svc_signonnum);
	MSG_WriteByte (&client->message, 1);

	client->sendsignon = true;
	client->spawned = false;		// need prespawn, spawn, etc

// >>> FIX: For Nintendo Wii using devkitPPC / libogc
// Deallocating from previous fix:
	Sys_BigStackFree(2048, "SV_SendServerinfo");
// <<< FIX
}
コード例 #6
0
ファイル: host.c プロジェクト: Rinnegatamante/vitaQuake
/*
=================
Host_ClientCommands

Send text over to the client to be executed
=================
*/
void Host_ClientCommands (char *fmt, ...)
{
	va_list		argptr;
	char*		string = Sys_BigStackAlloc(1024, "Host_ClientCommands");

	va_start (argptr,fmt);
	vsprintf (string, fmt,argptr);
	va_end (argptr);

	MSG_WriteByte (&host_client->message, svc_stufftext);
	MSG_WriteString (&host_client->message, string);

	Sys_BigStackFree(1024, "Host_ClientCommands");
}
コード例 #7
0
ファイル: host.c プロジェクト: Rinnegatamante/vitaQuake
/*
=================
SV_ClientPrintf

Sends text across to be displayed
FIXME: make this just a stuffed echo?
=================
*/
void SV_ClientPrintf (char *fmt, ...)
{
	va_list		argptr;
	char*		string = Sys_BigStackAlloc(1024, "SV_ClientPrintf");

	va_start (argptr,fmt);
	vsprintf (string, fmt,argptr);
	va_end (argptr);

	MSG_WriteByte (&host_client->message, svc_print);
	MSG_WriteString (&host_client->message, string);

	Sys_BigStackFree(1024, "SV_ClientPrintf");
}
コード例 #8
0
ファイル: gx_model.c プロジェクト: Izhido/qrevpak
void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
{
	byte				fillcolor = *skin; // assume this is the pixel to fill
	floodfill_t*			fifo;
	int					inpt = 0, outpt = 0;
	int					filledcolor = -1;
	int					i;

	if (filledcolor == -1)
	{
		filledcolor = 0;
		// attempt to find opaque black
		for (i = 0; i < 256; ++i)
			if (d_8to24table[i] == (255 << 0)) // alpha 1.0
			{
				filledcolor = i;
				break;
			}
	}

	// can't fill to filled color or to transparent color (used as visited marker)
	if ((fillcolor == filledcolor) || (fillcolor == 255))
	{
		//printf( "not filling skin from %d to %d\n", fillcolor, filledcolor );
		return;
	}

	fifo = Sys_BigStackAlloc(FLOODFILL_FIFO_SIZE * sizeof(floodfill_t), "Mod_FloodFillSkin");

	fifo[inpt].x = 0, fifo[inpt].y = 0;
	inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;

	while (outpt != inpt)
	{
		int			x = fifo[outpt].x, y = fifo[outpt].y;
		int			fdc = filledcolor;
		byte		*pos = &skin[x + skinwidth * y];

		outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;

		if (x > 0)				FLOODFILL_STEP( -1, -1, 0 );
		if (x < skinwidth - 1)	FLOODFILL_STEP( 1, 1, 0 );
		if (y > 0)				FLOODFILL_STEP( -skinwidth, 0, -1 );
		if (y < skinheight - 1)	FLOODFILL_STEP( skinwidth, 0, 1 );
		skin[x + skinwidth * y] = fdc;
	}
	Sys_BigStackFree(FLOODFILL_FIFO_SIZE * sizeof(floodfill_t), "Mod_FloodFillSkin");
}
コード例 #9
0
ファイル: host.c プロジェクト: Rinnegatamante/vitaQuake
/*
=================
SV_BroadcastPrintf

Sends text to all active clients
=================
*/
void SV_BroadcastPrintf (char *fmt, ...)
{
	va_list		argptr;
	char*		string = Sys_BigStackAlloc(1024, "SV_BroadcastPrintf");
	int			i;

	va_start (argptr,fmt);
	vsprintf (string, fmt,argptr);
	va_end (argptr);

	for (i = 0; i < svs.maxclients; i++)
	{
		if (svs.clients[i].active && svs.clients[i].spawned)
		{
			MSG_WriteByte(&svs.clients[i].message, svc_print);
			MSG_WriteString(&svs.clients[i].message, string);
		}
	}

	Sys_BigStackFree(1024, "SV_BroadcastPrintf");	
}
コード例 #10
0
ファイル: r_misc.c プロジェクト: Izhido/qrevpak
/* 
================== 
R_ScreenShot_f
================== 
*/  
void R_ScreenShot_f (void) 
{ 
	int			i; 
// >>> FIX: For Nintendo Wii using devkitPPC / libogc
// Allocating in big stack. Stack in this device is pretty small:
	//char		pcxname[80]; 
	//char		checkname[MAX_OSPATH];
	//FILE		*f;
	//byte		palette[768];
	FILE		*f;
	char*		pcxname = Sys_BigStackAlloc(80, "R_ScreenShot_f"); 
	char*		checkname = Sys_BigStackAlloc(MAX_OSPATH, "R_ScreenShot_f");
	byte*		palette = Sys_BigStackAlloc(768, "R_ScreenShot_f");
// <<< FIX

	// create the scrnshots directory if it doesn't exist
// >>> FIX: For Nintendo Wii using devkitPPC / libogc
// Adjusting for previous fix:
	//Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot", ri.FS_Gamedir());
	Com_sprintf (checkname, MAX_OSPATH, "%s/scrnshot", ri.FS_Gamedir());
// <<< FIX
	Sys_Mkdir (checkname);

// 
// find a file name to save it to 
// 
	strcpy(pcxname,"quake00.pcx");
		
	for (i=0 ; i<=99 ; i++) 
	{ 
		pcxname[5] = i/10 + '0'; 
		pcxname[6] = i%10 + '0'; 
// >>> FIX: For Nintendo Wii using devkitPPC / libogc
// Adjusting for previous fix:
		//Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot/%s", ri.FS_Gamedir(), pcxname);
		Com_sprintf (checkname, MAX_OSPATH, "%s/scrnshot/%s", ri.FS_Gamedir(), pcxname);
// <<< FIX
		f = fopen (checkname, "r");
		if (!f)
			break;	// file doesn't exist
		fclose (f);
	} 
	if (i==100) 
	{
		ri.Con_Printf (PRINT_ALL, "R_ScreenShot_f: Couldn't create a PCX"); 
// >>> FIX: For Nintendo Wii using devkitPPC / libogc
// Deallocating from previous fix:
		Sys_BigStackFree(80 + MAX_OSPATH + 768, "R_ScreenShot_f"); 
// <<< FIX
		return;
	}

	// turn the current 32 bit palette into a 24 bit palette
	for (i=0 ; i<256 ; i++)
	{
		palette[i*3+0] = sw_state.currentpalette[i*4+0];
		palette[i*3+1] = sw_state.currentpalette[i*4+1];
		palette[i*3+2] = sw_state.currentpalette[i*4+2];
	}

// 
// save the pcx file 
// 

	WritePCXfile (checkname, vid.buffer, vid.width, vid.height, vid.rowbytes,
				  palette);

	ri.Con_Printf (PRINT_ALL, "Wrote %s\n", checkname);

// >>> FIX: For Nintendo Wii using devkitPPC / libogc
// Deallocating from previous fix:
	Sys_BigStackFree(80 + MAX_OSPATH + 768, "R_ScreenShot_f"); 
// <<< FIX
} 
コード例 #11
0
ファイル: gx_mesh.c プロジェクト: Izhido/qrevpak
/*
================
BuildTris

Generate a list of trifans or strips
for the model, which holds for all frames
================
*/
void BuildTris (void)
{
	int		i, j, k;
	int		startv;
	mtriangle_t	*last, *check;
	int		m1, m2;
	int		striplength;
	trivertx_t	*v;
	mtriangle_t *tv;
	float	s, t;
	int		index;
	int		len, bestlen, besttype;
	int*		bestverts = Sys_BigStackAlloc(1024 * sizeof(int), "BuildTris");
	int*		besttris = Sys_BigStackAlloc(1024 * sizeof(int), "BuildTris");
	int		type;

	//
	// build tristrips
	//
	numorder = 0;
	numcommands = 0;
	memset (used, 0, sizeof(used));
	for (i=0 ; i<pheader->numtris ; i++)
	{
		// pick an unused triangle and start the trifan
		if (used[i])
			continue;

		bestlen = 0;
		for (type = 0 ; type < 2 ; type++)
//	type = 1;
		{
			for (startv =0 ; startv < 3 ; startv++)
			{
				if (type == 1)
					len = StripLength (i, startv);
				else
					len = FanLength (i, startv);
				if (len > bestlen)
				{
					besttype = type;
					bestlen = len;
					for (j=0 ; j<bestlen+2 ; j++)
						bestverts[j] = stripverts[j];
					for (j=0 ; j<bestlen ; j++)
						besttris[j] = striptris[j];
				}
			}
		}

		// mark the tris on the best strip as used
		for (j=0 ; j<bestlen ; j++)
			used[besttris[j]] = 1;

		if (besttype == 1)
			commands[numcommands++] = (bestlen+2);
		else
			commands[numcommands++] = -(bestlen+2);

		for (j=0 ; j<bestlen+2 ; j++)
		{
			// emit a vertex into the reorder buffer
			k = bestverts[j];
			vertexorder[numorder++] = k;

			// emit s/t coords into the commands stream
			s = stverts[k].s;
			t = stverts[k].t;
			if (!triangles[besttris[0]].facesfront && stverts[k].onseam)
				s += pheader->skinwidth / 2;	// on back side
			s = (s + 0.5) / pheader->skinwidth;
			t = (t + 0.5) / pheader->skinheight;

			*(float *)&commands[numcommands++] = s;
			*(float *)&commands[numcommands++] = t;
		}
	}

	commands[numcommands++] = 0;		// end of list marker

	Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands);

	allverts += numorder;
	alltris += pheader->numtris;
	Sys_BigStackFree(1024 * sizeof(int) + 1024 * sizeof(int), "BuildTris");
}
コード例 #12
0
ファイル: model.c プロジェクト: Izhido/qrevpak
/*
==================
Mod_LoadModel

Loads a model into the cache
==================
*/
model_t *Mod_LoadModel (model_t *mod, qboolean crash)
{
	unsigned *buf;
// >>> FIX: For Nintendo Wii using devkitPPC / libogc
// Deferring allocation. Stack in this device is pretty small:
	//byte	stackbuf[1024];		// avoid dirtying the cache heap
	byte*	stackbuf;		// avoid dirtying the cache heap
// <<< FIX

	if (mod->type == mod_alias)
	{
		if (Cache_Check (&mod->cache))
		{
			mod->needload = NL_PRESENT;
			return mod;
		}
	}
	else
	{
		if (mod->needload == NL_PRESENT)
			return mod;
	}

//
// because the world is so huge, load it one piece at a time
//
	
//
// load the file
//
// >>> FIX: For Nintendo Wii using devkitPPC / libogc
// Allocating for previous fixes (and, this time, expanding the allocated size), in big stack:
	stackbuf = Sys_BigStackAlloc(4096 * sizeof(byte), "Mod_LoadModel");
// <<< FIX
// >>> FIX: For Nintendo Wii using devkitPPC / libogc
// Adjusting for previous fix:
	//buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));
	buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, 4096);
// <<< FIX
	if (!buf)
	{
		if (crash)
			Sys_Error ("Mod_NumForName: %s not found", mod->name);
// >>> FIX: For Nintendo Wii using devkitPPC / libogc
// Deallocating from previous fixes:
		Sys_BigStackFree(4096 * sizeof(byte), "Mod_LoadModel");
// <<< FIX
		return NULL;
	}
	
//
// allocate a new model
//
	COM_FileBase (mod->name, loadname);
	
	loadmodel = mod;

//
// fill it in
//

// call the apropriate loader
	mod->needload = NL_PRESENT;

	switch (LittleLong(*(unsigned *)buf))
	{
	case IDPOLYHEADER:
		Mod_LoadAliasModel (mod, buf);
		break;
		
	case IDSPRITEHEADER:
		Mod_LoadSpriteModel (mod, buf);
		break;
	
	default:
		Mod_LoadBrushModel (mod, buf);
		break;
	}

// >>> FIX: For Nintendo Wii using devkitPPC / libogc
// Deallocating from previous fixes:
	Sys_BigStackFree(4096 * sizeof(byte), "Mod_LoadModel");
// <<< FIX

	return mod;
}
コード例 #13
0
ファイル: gx_model.c プロジェクト: Izhido/qrevpak
/*
==================
Mod_LoadModel

Loads a model into the cache
==================
*/
model_t *Mod_LoadModel (model_t *mod, qboolean crash)
{
	void	*d;
	unsigned *buf;
	byte*	stackbuf;

	if (!mod->needload)
	{
		if (mod->type == mod_alias)
		{
			d = Cache_Check (&mod->cache);
			if (d)
				return mod;
		}
		else
			return mod;		// not cached at all
	}

//
// because the world is so huge, load it one piece at a time
//
	if (!crash)
	{
	
	}
	
//
// load the file
//
	stackbuf = Sys_BigStackAlloc(1024 * sizeof(byte), "Mod_LoadModel");
	buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, 1024);
	if (!buf)
	{
		if (crash)
			Sys_Error ("Mod_NumForName: %s not found", mod->name);
		return NULL;
	}
	
//
// allocate a new model
//
	COM_FileBase (mod->name, loadname);
	
	loadmodel = mod;

//
// fill it in
//

// call the apropriate loader
	mod->needload = false;
	
	switch (LittleLong(*(unsigned *)buf))
	{
	case IDPOLYHEADER:
		Mod_LoadAliasModel (mod, buf);
		break;
		
	case IDSPRITEHEADER:
		Mod_LoadSpriteModel (mod, buf);
		break;
	
	default:
		Mod_LoadBrushModel (mod, buf);
		break;
	}

	Sys_BigStackFree(1024 * sizeof(byte), "Mod_LoadModel");
	return mod;
}
コード例 #14
0
ファイル: cl_parse.c プロジェクト: Rinnegatamante/vitaQuake
/*
==================
CL_ParseServerInfo
==================
*/
void CL_ParseServerInfo (void)
{
	char	*str;
	int		i, maxlen;
	int		nummodels, numsounds;
	char**	sound_precache;
	char**	model_precache;
	char	tempname[MAX_QPATH];
	Con_DPrintf ("Serverinfo packet received.\n");
//
// wipe the client_state_t struct
//
	CL_ClearState ();

// parse protocol version number
	i = MSG_ReadLong ();
	if (i != PROTOCOL_NETQUAKE && i != PROTOCOL_FITZQUAKE)
	{
		Host_Error("Server returned version %i, not %i (Net/ProQuake) or %i (FitzQuake)", i, PROTOCOL_NETQUAKE, PROTOCOL_FITZQUAKE);
		Con_Printf ("Server returned version %i, not %i", i, PROTOCOL_NETQUAKE);
		return;
	}

// parse maxclients
	cl.maxclients = MSG_ReadByte ();
	if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
	{
		Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
		return;
	}
	cl.scores = Hunk_AllocName (cl.maxclients*sizeof(*cl.scores), "scores");

// parse gametype
	cl.gametype = MSG_ReadByte ();

// parse signon message
	str = MSG_ReadString ();
	strncpy (cl.levelname, str, sizeof(cl.levelname)-1);

// seperate the printfs so the server message can have a color
	Con_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n");
	Con_Printf ("%c%s\n", 2, str);

//
// first we go through and touch all of the precache data that still
// happens to be in the cache, so precaching something else doesn't
// needlessly purge it
//

	model_precache = Sys_BigStackAlloc(MAX_MODELS * sizeof(char*), "CL_ParseServerInfo");
	for (i = 0; i < MAX_MODELS; i++)
	{
		model_precache[i] = Sys_BigStackAlloc(MAX_QPATH, "CL_ParseServerInfo");
	};

// precache models
	memset (cl.model_precache, 0, sizeof(cl.model_precache));
	for (nummodels=1 ; ; nummodels++)
	{
		str = MSG_ReadString ();
		if (!str[0])
			break;
		if (nummodels == MAX_MODELS)
		{
			Con_Printf("Server sent too many model precaches\n");
			for (i = MAX_MODELS - 1; i >= 0; i--) {
				free(model_precache[i]);
			};
			free(model_precache);
			return;
		}
		strcpy (model_precache[nummodels], str);
		Mod_TouchModel (str);
	}

// precache sounds

	sound_precache = Sys_BigStackAlloc(MAX_SOUNDS * sizeof(char*), "CL_ParseServerInfo");
	for (i = 0; i < MAX_SOUNDS; i++)
	{
		sound_precache[i] = Sys_BigStackAlloc(MAX_QPATH, "CL_ParseServerInfo");
	};

	memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
	for (numsounds=1 ; ; numsounds++)
	{
		str = MSG_ReadString ();
		if (!str[0])
			break;
		if (numsounds == MAX_SOUNDS)
		{
			Con_Printf("Server sent too many sound precaches\n");
			Sys_BigStackFree(MAX_MODELS * sizeof(char*) + MAX_MODELS * MAX_QPATH + MAX_SOUNDS * sizeof(char*) + MAX_SOUNDS * MAX_QPATH, "CL_ParseServerInfo");
			return;
		}
		strcpy (sound_precache[numsounds], str);
		S_TouchSound (str);
	}

//
// now we try to load everything else until a cache allocation fails
//
	for (i=1 ; i<nummodels ; i++)
	{
		cl.model_precache[i] = Mod_ForName (model_precache[i], false);
		if (cl.model_precache[i] == NULL)
		{
			Con_Printf("Model %s not found\n", model_precache[i]);
			Sys_BigStackFree(MAX_MODELS * sizeof(char*) + MAX_MODELS * MAX_QPATH + MAX_SOUNDS * sizeof(char*) + MAX_SOUNDS * MAX_QPATH, "CL_ParseServerInfo");
			return;
		}
		CL_KeepaliveMessage ();
	}

	S_BeginPrecaching ();
	for (i=1 ; i<numsounds ; i++)
	{
		cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
		CL_KeepaliveMessage ();
	}
	S_EndPrecaching ();


// local state
	cl_entities[0].model = cl.worldmodel = cl.model_precache[1];
	R_NewMap ();
	Hunk_Check ();		// make sure nothing is hurt

	noclip_anglehack = false;		// noclip is turned off at start

	Sys_BigStackFree(MAX_MODELS * sizeof(char*) + MAX_MODELS * MAX_QPATH + MAX_SOUNDS * sizeof(char*) + MAX_SOUNDS * MAX_QPATH, "CL_ParseServerInfo");
}