[Tutorial PSP/PC] - In Game Server List -PSP Use Other Tut

Post tutorials on how to do certain tasks within game or engine code here.
Post Reply
Team Xlink
Posts: 368
Joined: Thu Jun 25, 2009 4:45 am
Location: Michigan

[Tutorial PSP/PC] - In Game Server List -PSP Use Other Tut

Post by Team Xlink »

NOTICE
this is NOT recommended for the PSP

For the psp use the tutorial located here:

http://forums.inside3d.com/viewtopic.php?t=2175

Hello.


Today you will learn (hopefully) how to add an in game server list to the Quake Engine.

This tutorial is very simple and easy to do.

Step one

Create a new file called slist.c

Step Two

In that file add this code:

Code: Select all

/*
Copyright (C) 1999-2000, contributors of the QuakeForge project

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.

*/
// slist.c -- serverlist addressbook

#include "quakedef.h"

server_entry_t	slist[MAX_SERVER_LIST];

void SList_Init (void)
{
	memset (&slist, 0, sizeof(slist));	
}

void SList_Shutdown (void)
{  
	FILE	*f;

	if (!(f = fopen (va("%s/servers.lst", com_gamedir), "wt")))
	{
		Con_DPrintf ("Couldn't open servers.lst\n");
		return;
	}
	SList_Save (f);
	fclose (f);
}
			
void SList_Set (int i, char *addr, char *desc)
{
	if (i >= MAX_SERVER_LIST || i < 0)
		Sys_Error ("SList_Set: Bad index %d", i);

	if (slist[i].server)
		Z_Free (slist[i].server);
	if (slist[i].description)
		Z_Free (slist[i].description);

	slist[i].server = CopyString (addr);
	slist[i].description = CopyString (desc);
}

void SList_Reset_NoFree (int i)
{ 
	if (i >= MAX_SERVER_LIST || i < 0)
		Sys_Error ("SList_Reset_NoFree: Bad index %d", i);

	slist[i].description = slist[i].server = NULL;
}

void SList_Reset (int i)
{
	if (i >= MAX_SERVER_LIST || i < 0)
		Sys_Error ("SList_Reset: Bad index %d", i);

	if (slist[i].server)
	{
		Z_Free (slist[i].server);
		slist[i].server = NULL;
	}

	if (slist[i].description)
	{
		Z_Free (slist[i].description);
		slist[i].description = NULL;
	}
}

void SList_Switch (int a, int b)
{
	server_entry_t	temp;

	if (a >= MAX_SERVER_LIST || a < 0)
		Sys_Error ("SList_Switch: Bad index %d", a);
	if (b >= MAX_SERVER_LIST || b < 0)
		Sys_Error ("SList_Switch: Bad index %d", b);

	memcpy (&temp, &slist[a], sizeof(temp));
	memcpy (&slist[a], &slist[b], sizeof(temp));
	memcpy (&slist[b], &temp, sizeof(temp));
}

int SList_Length (void)
{
	int	count;

	for (count = 0 ; count < MAX_SERVER_LIST && slist[count].server ; count++)
		;

	return count;
}

void SList_Load (void)
{
	int	c, len, argc, count;
	char	line[128], *desc, *addr;
	FILE	*f;

	if (!(f = fopen (va("%s/servers.lst", com_gamedir), "rt")))
		return;

	count = len = 0;
	while ((c = getc(f)))
	{
		if (c == '\n' || c == '\r' || c == EOF)
		{
			if (c == '\r' && (c = getc(f)) != '\n' && c != EOF)
				ungetc (c, f);

			line[len] = 0;
			len = 0;
			Cmd_TokenizeString (line);

			if ((argc = Cmd_Argc()) >= 1)
			{
				addr = Cmd_Argv(0);
				desc = (argc >= 2) ? Cmd_Args() : "Unknown";
				SList_Set (count, addr, desc);
				if (++count == MAX_SERVER_LIST)
					break;
			}
			if (c == EOF)
				break;	//just in case an EOF follows a '\r'
		}
		else
		{
			if (len + 1 < sizeof(line))
				line[len++] = c;
		}
	}

	fclose (f);
}

void SList_Save (FILE *f)
{
	int	i;

	for (i=0 ; i<MAX_SERVER_LIST ; i++)
	{
		if (!slist[i].server)
			break;

		fprintf (f, "%s\t%s\n", slist[i].server, slist[i].description);
	}
}
Step Three

Create another new file called slist.h

Step Four

In that file add this code:

Code: Select all

/*
Copyright (C) 1999-2000, contributors of the QuakeForge project

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.

*/
// slist.h

#define	MAX_SERVER_LIST	256
#define MAX_PLAYERS		16

typedef struct
{
    int		id;
    int		frags;
    int		time;
    char	*name;
    int		top;
    int		bottom;
} playerinfo_t;

typedef struct 
{
	char	*server;
	char	*description;
} server_entry_t;

extern	server_entry_t	slist[MAX_SERVER_LIST];

void SList_Init (void);
void SList_Shutdown (void);
void SList_Set (int i,char *addr,char *desc);
void SList_Reset_NoFree (int i);
void SList_Reset (int i);
void SList_Switch (int a,int b);
int SList_Length (void);
void SList_Load (void);
void SList_Save (FILE *f);
Step Five:


Open up Quakedef.h and at the bottom of the include list add this line of code:

#include "slist.h"

Step Six


Open up menu.c and replace the sever list menu with this:

Code: Select all

///=============================================================================
/* SERVER LIST MENU */

#define	MENU_X	50
#define	MENU_Y	21
#define TITLE_Y 4
#define	STAT_Y	166
extern qboolean	keydown[256];
int	slist_cursor = 0, slist_mins = 0, slist_maxs = 15, slist_state;

#define	SLIST_BUFSIZE	128

playerinfo_t plist[16]; int numPlayers;

void M_Menu_ServerList_f (void)
{
SList_Load ();
	key_dest = key_menu;
	m_state = m_slist;
	m_entersound = true;

	slist_state = 0;
}

void M_ServerList_Draw (void)
{
	int	serv, line;

	M_DrawTextBox (MENU_X, TITLE_Y, 23, 1);
	M_PrintWhite (MENU_X + 60, TITLE_Y + 8, "Server List");

	if (!slist[0].server)
	{
		M_PrintWhite	(84, MENU_Y + 32, "Empty server list");
		M_Print			(60, MENU_Y + 48, "By Team Xlink");
		return;
	}

	M_DrawTextBox (MENU_X, STAT_Y, 23, 1);
	M_DrawTextBox (MENU_X, MENU_Y, 23, slist_maxs - slist_mins + 1);
	for (serv = slist_mins, line = 1 ; serv <= slist_maxs && serv < MAX_SERVER_LIST && slist[serv].server ; serv++, line++)
		M_Print (MENU_X + 18, line * 8 + MENU_Y, va("%1.21s", slist[serv].description));
	M_Print (MENU_X - 36, STAT_Y - 4, "By Team Xlink");
	M_PrintWhite (MENU_X + 18, STAT_Y + 8, va("%1.22s", slist[slist_cursor].server));
	M_DrawCharacter (MENU_X + 8, (slist_cursor - slist_mins + 1) * 8 + MENU_Y, 12+((int)(realtime*4)&1));
}

void M_ServerList_Key (key)
{

	if (!slist[0].server && key != K_ESCAPE && key != K_INS)
		return;

	switch (key)
	{
	case K_ESCAPE:
		M_Menu_MultiPlayer_f ();
		break;

	case K_UPARROW:
		S_LocalSound ("misc/menu1.wav");
		if (slist_cursor > 0)
		{
			if (keydown[K_CTRL])
				SList_Switch (slist_cursor, slist_cursor - 1);
			slist_cursor--;
		}
		break;

	case K_DOWNARROW:
		S_LocalSound ("misc/menu1.wav");
		if (keydown[K_CTRL])
		{
			if (slist_cursor != SList_Length() - 1)
			{
				SList_Switch (slist_cursor, slist_cursor + 1);
				slist_cursor++;
			}
		}
		else if (slist_cursor < MAX_SERVER_LIST - 1 && slist[slist_cursor+1].server)
			slist_cursor++;
		break;

	case K_HOME:
		S_LocalSound ("misc/menu1.wav");
		slist_cursor = 0;
		break;

	case K_END:
		S_LocalSound ("misc/menu1.wav");
		slist_cursor = SList_Length() - 1;
		break;
		
	case K_AUX1:
		S_LocalSound ("misc/menu1.wav");
		slist_cursor -= (slist_maxs - slist_mins);
		if (slist_cursor < 0)
			slist_cursor = 0;
		break;

	case K_AUX2:
		S_LocalSound ("misc/menu1.wav");
		slist_cursor += (slist_maxs - slist_mins);
		if (slist_cursor >= MAX_SERVER_LIST)
			slist_cursor = MAX_SERVER_LIST - 1;
		while (!slist[slist_cursor].server)
			slist_cursor--;
		break;

	case K_ENTER:
		m_state = m_main;
		M_ToggleMenu_f ();
		Cbuf_AddText ( va ("connect \"%s\"\n", slist[slist_cursor].server) );
break;


	}

	if (slist_cursor < slist_mins)
	{
		slist_maxs -= (slist_mins - slist_cursor);
		slist_mins = slist_cursor;
	}
	if (slist_cursor > slist_maxs)
	{
		slist_mins += (slist_cursor - slist_maxs);
		slist_maxs = slist_cursor;
	}

}
Step 7
Scroll down to:

Code: Select all

void M_Init (void)
Before this:

Code: Select all

Cmd_AddCommand ("menu_quit", M_Menu_Quit_f);
Add this:

Code: Select all

Cmd_AddCommand ("menu_serverlist", M_Menu_ServerList_f);
Now when you want to load your server list go to the console and type:

Code: Select all

menu_serverlist
Or you can add a menu option in your engine by calling it like this:

Code: Select all

Cbuf_AddText ("menu_serverlist");
Make sure to include slist.c in your engine.

PSP

Step 8


Well, since more people are interested in PSP Quake then I thought, I will throw in the steps for the psp.

Go to your subdirectory called psp and open up the file called makefile

*It will most likely make a confirmation pop up that talks about which program to use to open it. You can use any text editor (As long as it doesn't have automatic formatting) *cough* Microsoft Word, if you have no idea what to use, just use notepad

Find this:

Code: Select all

	$(OBJ_DIR)/world.o \
	$(OBJ_DIR)/zone.o 
Change that to this:

Code: Select all

	$(OBJ_DIR)/world.o \
	$(OBJ_DIR)/zone.o \
	$(OBJ_DIR)/slist.o

**PSP TIP START**

Whenever you need to add a file to your engine at the end of the file, your last line of the $(OBJ_DIR) has to NOT have a frontslash \.
Every other &(OBG_DIR) line MUST have a front slash \.

**PSP TIP END**


There you go.

If you have any comments or questions, improvements or anything just replay away!

Additional Credit:

Quake Forge Project

Team Xlink
Last edited by Team Xlink on Sun Jul 11, 2010 6:59 pm, edited 9 times in total.
ceriux
Posts: 2230
Joined: Sat Sep 06, 2008 3:30 pm
Location: Indiana, USA

Post by ceriux »

so this would add a server list to the engine (so you dont have to know an ip and connect manually?)
Team Xlink
Posts: 368
Joined: Thu Jun 25, 2009 4:45 am
Location: Michigan

Post by Team Xlink »

Yes.

They are stored in the Servers.lst file.
ceriux
Posts: 2230
Joined: Sat Sep 06, 2008 3:30 pm
Location: Indiana, USA

Post by ceriux »

awesome thanks for the tutorial im going to try it out.

[code
mycoolbuild
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
worlda.s
Assembling: .\release_gl\worlda.asm
Microsoft (R) Macro Assembler Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
mycoolbuild
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
sys_wina.s
Assembling: .\release_gl\sys_wina.asm
Microsoft (R) Macro Assembler Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
mycoolbuild
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
snd_mixa.s
Assembling: .\release_gl\snd_mixa.asm
Microsoft (R) Macro Assembler Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
mycoolbuild
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
math.s
Assembling: .\release_gl\math.asm
Microsoft (R) Macro Assembler Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
Compiling...
zone.c
c:\fantasy\slist.h(53) : error C2061: syntax error : identifier 'slist'
c:\fantasy\slist.h(53) : error C2059: syntax error : ';'
c:\fantasy\slist.h(54) : error C2449: found '{' at file scope (missing function header?)
c:\fantasy\slist.h(58) : error C2059: syntax error : '}'
C:\Program Files\Microsoft Visual Studio 9.0\VC\include\excpt.h(59)
[/code]


and it goes on...
Last edited by ceriux on Wed Dec 02, 2009 7:10 am, edited 2 times in total.
ceriux
Posts: 2230
Joined: Sat Sep 06, 2008 3:30 pm
Location: Indiana, USA

Post by ceriux »

sorry cut it down to this

Code: Select all

1>slist.c
1>.\slist.c(35) : error C2065: 'com_basedir' : undeclared identifier
1>.\slist.c(54) : warning C4047: '=' : 'char *' differs in levels of indirection from 'int'
1>.\slist.c(55) : warning C4047: '=' : 'char *' differs in levels of indirection from 'int'
1>.\slist.c(114) : error C2065: 'com_basedir' : undeclared identifier
Team Xlink
Posts: 368
Joined: Thu Jun 25, 2009 4:45 am
Location: Michigan

Post by Team Xlink »

Alright, I will look into that because it works in my engine.

Of course my engine is for the PSP but I didn't see anything that is platform specific so this post will be edited later tonight with the fix for your problem.

EDIT: I fixed it, it turns out I had something spelled differently in both of my engines.
ceriux
Posts: 2230
Joined: Sat Sep 06, 2008 3:30 pm
Location: Indiana, USA

Post by ceriux »

cool tutorial =p but my first suggestion would be to rename it to in-game player list =p instead of in-game server list.
Team Xlink
Posts: 368
Joined: Thu Jun 25, 2009 4:45 am
Location: Michigan

Post by Team Xlink »

I just noticed I didn't write the last step for the tutorial.

So I updated the tutorial.

Also a proper server list would get a list of all servers being hosted from a master server like QuakeWorld does it.
ceriux
Posts: 2230
Joined: Sat Sep 06, 2008 3:30 pm
Location: Indiana, USA

Post by ceriux »

yeah lol thats what i thought this was.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

Team Xlink wrote:from a master server like QuakeWorld does it.
For the stock Quake engine, that'd be a large amount of work. Servers don't send out a heartbeat to a master server, you'd have to setup a master server and you'd be messing with network code (fun!) and even worse, probably platform specific network code for a PSP targeted mod.

You can get 80% of the benefit using libcurl just to download a text file of the servers. Downsider told me that libcurl has been ported to the PSP (libcurl 7.19 release), so libcurl is available on at least 4 platforms (Windows, Linux, OS X, PSP).

Image

This is an example of the server browser in ProQuake 4.01, which obviously is a bit more sophisticated than just a server list, but the information is retrieved via libcurl in a similar way as this little tutorial: http://forums.inside3d.com/viewtopic.php?t=1669
Team Xlink
Posts: 368
Joined: Thu Jun 25, 2009 4:45 am
Location: Michigan

Post by Team Xlink »

Well there is a box in my server list that I am trying to fix.

In the SERVERS.lst file if you have one in there that uses a different port like this:
The syntax is this:

q1.terra.com.br:26011 Terra

That in the server list will show up as

q1.terra.com.br :26011 Terra

Soto get the port to display right you have to do this:

q1.terra.com.br;26011 Terra

Which won't let you connect.


I am going to upload a fix for that right away.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Post by Baker »

Team Xlink wrote:Well there is a box in my server list that I am trying to fix.

In the SERVERS.lst file if you have one in there that uses a different port like this:
The syntax is this:

q1.terra.com.br:26011 Terra

That in the server list will show up as

q1.terra.com.br :26011 Terra

Soto get the port to display right you have to do this:

q1.terra.com.br;26011 Terra

Which won't let you connect.

I am going to upload a fix for that right away.
Well, you are likely to have another problem.

GLQuake didn't support ip:port, so that feature will likely need to be added into the engine until someone has ported that into the engine being modified.

GLQuake can't do, for instance: "connect myserver.com:26001" but would have to do "port 26001; connect myserver.com"

The easiest Quake engine to borrow ip:port connecting from would be from either ProQuake or JoeQuake.

I'm personally waiting on a USB to 5 pin cable for my PSP, once I receive that in the mail I can be a little more proactive in helping ;)
Team Xlink
Posts: 368
Joined: Thu Jun 25, 2009 4:45 am
Location: Michigan

Post by Team Xlink »

I updated the tutorial by adding a PSP part to it.

Baker, I was totally unaware that stock Quake didn't have the :ip port code, now I know why it never seemed to work for me.

So, I could either add the :ipport support or do some hackish code based on the console commands you just gave me.

I will go with the first but I may add some hackish code as an optional thing to this tutorial to make it work fully, I may even make another tutorial for the :ipport support after I port it.
Post Reply