Inside3D!
     

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

 
Post new topic   Reply to topic    Inside3d Forums Forum Index -> Programming Tutorials
View previous topic :: View next topic  
Author Message
Team Xlink



Joined: 25 Jun 2009
Posts: 320

PostPosted: Fri Nov 20, 2009 12:05 am    Post subject: [Tutorial PSP/PC] - In Game Server List -PSP Use Other Tut Reply with quote

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:

/*
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:

/*
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:
///=============================================================================
/* 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:
void M_Init (void)


Before this:

Code:
Cmd_AddCommand ("menu_quit", M_Menu_Quit_f);


Add this:

Code:

Cmd_AddCommand ("menu_serverlist", M_Menu_ServerList_f);


Now when you want to load your server list go to the console and type:
Code:
menu_serverlist


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

Code:
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:

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


Change that to this:

Code:
   $(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
_________________
Anonymous wrote:
if it works, it works. if it doesn't, HAHAHA!


Last edited by Team Xlink on Sun Jul 11, 2010 6:59 pm; edited 9 times in total
Back to top
View user's profile Send private message
ceriux



Joined: 06 Sep 2008
Posts: 969
Location: Florida, USA

PostPosted: Fri Nov 20, 2009 2:21 am    Post subject: Reply with quote

so this would add a server list to the engine (so you dont have to know an ip and connect manually?)
_________________
QuakeDB - Quake ModDB Group
Back to top
View user's profile Send private message Yahoo Messenger
Team Xlink



Joined: 25 Jun 2009
Posts: 320

PostPosted: Wed Dec 02, 2009 1:19 am    Post subject: Reply with quote

Yes.

They are stored in the Servers.lst file.
_________________
Anonymous wrote:
if it works, it works. if it doesn't, HAHAHA!
Back to top
View user's profile Send private message
ceriux



Joined: 06 Sep 2008
Posts: 969
Location: Florida, USA

PostPosted: Wed Dec 02, 2009 3:25 am    Post subject: Reply with quote

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(5Cool : error C2059: syntax error : '}'
C:\Program Files\Microsoft Visual Studio 9.0\VC\include\excpt.h(59)
[/code]


and it goes on...
_________________
QuakeDB - Quake ModDB Group


Last edited by ceriux on Wed Dec 02, 2009 7:10 am; edited 2 times in total
Back to top
View user's profile Send private message Yahoo Messenger
ceriux



Joined: 06 Sep 2008
Posts: 969
Location: Florida, USA

PostPosted: Wed Dec 02, 2009 5:52 am    Post subject: Reply with quote

sorry cut it down to this

Code:
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

_________________
QuakeDB - Quake ModDB Group
Back to top
View user's profile Send private message Yahoo Messenger
Team Xlink



Joined: 25 Jun 2009
Posts: 320

PostPosted: Thu Dec 10, 2009 8:51 pm    Post subject: Reply with quote

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.
_________________
Anonymous wrote:
if it works, it works. if it doesn't, HAHAHA!
Back to top
View user's profile Send private message
ceriux



Joined: 06 Sep 2008
Posts: 969
Location: Florida, USA

PostPosted: Fri Dec 11, 2009 7:37 am    Post subject: Reply with quote

cool tutorial =p but my first suggestion would be to rename it to in-game player list =p instead of in-game server list.
_________________
QuakeDB - Quake ModDB Group
Back to top
View user's profile Send private message Yahoo Messenger
Team Xlink



Joined: 25 Jun 2009
Posts: 320

PostPosted: Thu Dec 24, 2009 7:34 am    Post subject: Reply with quote

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.
_________________
Anonymous wrote:
if it works, it works. if it doesn't, HAHAHA!
Back to top
View user's profile Send private message
ceriux



Joined: 06 Sep 2008
Posts: 969
Location: Florida, USA

PostPosted: Thu Dec 24, 2009 7:37 am    Post subject: Reply with quote

yeah lol thats what i thought this was.
_________________
QuakeDB - Quake ModDB Group
Back to top
View user's profile Send private message Yahoo Messenger
Baker



Joined: 14 Mar 2006
Posts: 1538

PostPosted: Thu Dec 24, 2009 9:03 am    Post subject: Reply with quote

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).



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
Back to top
View user's profile Send private message
Team Xlink



Joined: 25 Jun 2009
Posts: 320

PostPosted: Fri Dec 25, 2009 3:52 am    Post subject: Reply with quote

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.
_________________
Anonymous wrote:
if it works, it works. if it doesn't, HAHAHA!
Back to top
View user's profile Send private message
Baker



Joined: 14 Mar 2006
Posts: 1538

PostPosted: Fri Dec 25, 2009 6:05 am    Post subject: Reply with quote

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 Wink
Back to top
View user's profile Send private message
Team Xlink



Joined: 25 Jun 2009
Posts: 320

PostPosted: Mon Jan 04, 2010 11:31 pm    Post subject: Reply with quote

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.
_________________
Anonymous wrote:
if it works, it works. if it doesn't, HAHAHA!
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Inside3d Forums Forum Index -> Programming Tutorials All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2004 phpBB Group