Jump to content
  • Advertisement
Sign in to follow this  
DMINATOR

Quake 2 server info

This topic is 4862 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi I wan't to get the details of quake 2 server, such as players , frags etc. But I don't know how , I am going to do that. I can work with winsock , and have experience with irc servers. So I am trying to connect to game server, that's ok. But sending message failes. Can anyone one help me out ? Thanks.

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
Hi! Here is my PHP code that do what you want (there could be copy/paste bugs as I copied it from a terminal). It works well with Quake 3, but it's basically the same with quake 2 if I remember well.

classname = "GameQuerier";

$this->MinimumPlayers = 0;
$this->MaximumPing = 0;
$this->MinimumPing = 0;
$this->HostName = "";
$this->MaximumRate = 0;
$this->FloodProtection = 0;
$this->DeathMatchFlags = 0;
$this->FragLimit = 0;
$this->TimeLimit = 0;
$this->MaximumClients = 0;
$this->CaptureLimit = 0;
$this->MaximumGameClients = 0;
$this->PunkBuster = 0;
$this->GameType = "";
$this->Version = "";
$this->Protocol = "Inconnu";
$this->MapName = "";
$this->PrivateClients = 0;
$this->AllowDownload = 0;
$this->GameName = "";
$this->NeedPassword = 0;
$this->NumberOfPlayers = 0;

$this->PlayerInBlue = "";
$this->PlayerInRed = "";
$this->ScoreRed = 0;
$this->ScoreBlue = 0;
}

// The Install function will create all the tables necessary to the use of this module.
function Install()
{
}

function GetGameUrl($strHost,$intPort,$defGame)
{
switch($defGame)
{
case GAME_QUAKE3 : $strGame = "q3a"; break;
case GAME_ENEMYTERRITORY: $strGame = "wet"; break;
}

return ("gsrv://".$strGame."@".$strHost.":".$intPort."/");
}

function QueryGame($strHost,$intPort,$defGame)
{
$sckServer = socket_create(AF_INET,SOCK_DGRAM,SOL_UDP);

socket_set_nonblock($sckServer);

// QUERY PORT
switch($defGame)
{
case GAME_UT2003 : $intPort = $intPort + 10;
}

if(@socket_connect($sckServer,gethostbyname($strHost),$intPort)!==false)
{

switch($defGame)
{
case GAME_QUAKE3 : $strQuery = "\xff\xff\xff\xffgetstatus"; break;
case GAME_ENEMYTERRITORY: $strQuery = "\xff\xff\xff\xffgetstatus"; break;
case GAME_UT2003 : $strQuery = "\\status\\"; break;
}

if(@socket_write($sckServer,$strQuery)===false)
{
socket_close($sckServer);
return false;
}

$currentstamp = time();

while((($strReturnedResult = @socket_read($sckServer,65506))=="") && ($currentstamp+5>time()));

if($strReturnedResult=="")
{
socket_close($sckServer);
return false;
}

socket_close($sckServer);

$this->ParseString($strReturnedResult,$defGame);

return true;
}

return false;
}

function ParseString($strParse,$defGame)
{

switch($defGame)
{
case GAME_QUAKE3 : $strParse = str_replace("\n","\\",$strParse); $strData = explode("\\",$strParse);
case GAME_ENEMYTERRITORY: $strParse = str_replace("\n","\\",$strParse); $strData = explode("\\",$strParse);
case GAME_UT2003 : $strData = explode("\\",$strParse);
}

for($i=0;$iMinimumPlayers = $strData[++$i]; break;
case "sv_maxPing" : $this->MaximumPing = $strData[++$i]; break;
case "sv_minPing" : $this->MinimumPing = $strData[++$i]; break;
case "sv_hostname" : $this->HostName = $strData[++$i]; break;
case "sv_maxRate" : $this->MaximumRate = $strData[++$i]; break;
case "sv_floodProtect" : $this->FloodProtection = $strData[++$i]; break;
case "dmflags" : $this->DeathMatchFlags = $strData[++$i]; break;
case "fraglimit" : $this->FragLimit = $strData[++$i]; break;
case "timelimit" : $this->TimeLimit = $strData[++$i]; break;
case "sv_maxclients" : $this->MaximumClients = $strData[++$i]; break;
case "capturelimit" : $this->CaptureLimit = $strData[++$i]; break;
case "g_maxGameClients" : $this->MaximumGameClients = $strData[++$i]; break;
case "sv_punkbuster" : $this->PunkBuster = $strData[++$i]; break;
case "g_gametype" : $this->GameType = $strData[++$i]; break;
case "version" : $this->Version = $strData[++$i]; break;
case "protocol" : $this->Protocol = $strData[++$i]; break;
case "mapname" : $this->MapName = $strData[++$i]; break;
case "sv_privateClients" : $this->PrivateClients = $strData[++$i]; break;
case "sv_allowDownload" : $this->AllowDownload = $strData[++$i]; break;
case "gamename" : $this->GameName = $strData[++$i]; break;
case "g_needpass" : $this->NeedPassword = $strData[++$i]; break;

// OSP
case "Players_Blue" : $this->PlayerInBlue = $strData[++$i]; break;
case "Players_Red" : $this->PlayerInRed = $strData[++$i]; break;
case "Score_Blue" : $this->ScoreBlue = $strData[++$i]; break;
case "Score_Red" : $this->ScoreRed = $strData[++$i]; break;

// ENEMY TERRITORY
case "Players_Allies" : $this->PlayerInBlue = $strData[++$i]; break;
case "Players_Axis" : $this->PlayerInRed = $strData[++$i]; break;

//UT2003
// no equivalent case "bot_minplayers" : $this->MinimumPlayers = $strData[++$i]; break;
// no equivalent case "sv_maxPing" : $this->MaximumPing = $strData[++$i]; break;
case "hostname" : $this->HostName = $strData[++$i]; break;
// no equivalent case "sv_maxRate" : $this->MaximumRate = $strData[++$i]; break;
// no equivalent case "sv_floodProtect" : $this->FloodProtection = $strData[++$i]; break;
// no equivalent case "dmflags" : $this->DeathMatchFlags = $strData[++$i]; break;
case "maxplayers" : $this->MaximumClients = $strData[++$i]; break;
// no equivalent case "capturelimit" : $this->CaptureLimit = $strData[++$i]; break;
// no equivalent case "g_maxGameClients" : $this->MaximumGameClients = $strData[++$i]; break;
// no equivalent case "sv_punkbuster" : $this->PunkBuster = $strData[++$i]; break;
case "gametype" : $this->GameType = $strData[++$i]; break;
case "gamever" : $this->Version = $strData[++$i]; break;
case "minnetver" : $this->Protocol = $strData[++$i]; break;
// no equivalent case "sv_privateClients" : $this->PrivateClients = $strData[++$i]; break;
// no equivalent case "sv_allowDownload" : $this->AllowDownload = $strData[++$i]; break;
case "password" : $this->NeedPassword = $strData[++$i]; break;

default:
switch($defGame)
{
case GAME_QUAKE3:
case GAME_ENEMYTERRITORY:
$strPlayerData = explode(" ",$strData[$i]);
if(count($strPlayerData)==3 && is_numeric($strPlayerData[0]) && is_numeric($strPlayerData[1]))
{
$this->PlayerDetails[$this->NumberOfPlayers]->Score = $strPlayerData[0];
$this->PlayerDetails[$this->NumberOfPlayers]->Ping = $strPlayerData[1];
$this->PlayerDetails[$this->NumberOfPlayers]->Player = trim(str_replace("\"","",$strPlayerData[2]));

$this->PlayerDetails[$this->NumberOfPlayers]->Team = 0;

if(strstr(" ".$this->PlayerInBlue." "," ".($this->NumberOfPlayers+1)." "))
$this->PlayerDetails[$this->NumberOfPlayers]->Team = 1;

if(strstr(" ".$this->PlayerInRed." "," ".($this->NumberOfPlayers+1)." "))
$this->PlayerDetails[$this->NumberOfPlayers]->Team = 2;

$this->NumberOfPlayers++;
}
break;
case GAME_UT2003:
if(substr($strData[$i],0,7)=="player_")
{
$this->PlayerDetails[$this->NumberOfPlayers]->Player = $strData[++$i];
$i = $i + 2;
$this->PlayerDetails[$this->NumberOfPlayers]->Score = $strData[$i];
$i = $i + 2;

if(IsTeamGame(GAME_UT2003,$this->GameType))
$this->PlayerDetails[$this->NumberOfPlayers]->Team = $strData[$i]+1;
else
$this->PlayerDetails[$this->NumberOfPlayers]->Team = 0;

$this->NumberOfPlayers++;
}
break;
}
break;
}
}
}
}
?>


Share this post


Link to post
Share on other sites
Ok great thank's I am going to try it , and see the results :)

Here is how I am doing this:


//creating socket - all ok sockfd = 1900

sockfd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);

//then i am making connection - result = 0

connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr))


//but the problem is that I can't send the text to the server somehow , the message is stored in the buffer
memset(buffer,0,BUFSIZE);


//let's add finishing message
sprintf(buffer,"%c%c%c%c%s",c,c,c,c,temp);


//let's use this text ("ÿÿÿÿgetstatus") and send it to the server
//here is the error
if(send(smsg, (char*)(buffer),strlen(buffer), 0) == SOCKET_ERROR)
MessageBox(NULL,buffer,"Can't send",0);




I can hardly guess what is the problem :(


[Edited by - DMINATOR on July 22, 2005 4:21:20 AM]

Share this post


Link to post
Share on other sites
<old post removed>

Ok I found out how to use udp sockets
well here is the code I am using right now



//Socket initialization routine
int InitializeSock(char* dadress,int dport)
{

//value used for getting hostname by ip adress
unsigned int addr;


//now we create destip and desthostname
destip = (char*)malloc(sizeof(char) * 255);
desthostname = (char*)malloc(sizeof(char) * 255);

// THIS SHOULD BE DONE BEFORE ANYTHIN ELSE
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
return(-1);
}

//now this is a hard part we need to find out from
//the input did we receve hostname or ip adress
//for this we use special function
//is ip ?

if(IsIP(dadress))
{
//working with ip

addr = inet_addr(dadress);

if((servinfo = gethostbyaddr((char *)&addr, 4, AF_INET) ) == NULL)
{
return -1;
}

//putting values
sprintf(desthostname,"%s",servinfo->h_name);
sprintf(destip,"%s",dadress);
}
else
{
//working with hostname
if((servinfo = gethostbyname(dadress)) == NULL)
{
return -1;
}

//putting values
sprintf(destip,"%s",inet_ntoa(*((struct in_addr *)servinfo->h_addr)));
sprintf(desthostname,"%s",dadress);

}



char buffer[30];
char buf[4048];
char c = 0;
int numbytes;

int addr_len;


if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {

AW_ShowError();
exit(1);
}



dest_addr.sin_family = AF_INET; // host byte order
dest_addr.sin_port = htons((short)destport); // short, network byte order
dest_addr.sin_addr.s_addr = inet_addr(destip);

memset(&(dest_addr.sin_zero), '\0', 8); // zero the rest of the struct




sprintf(buffer,"%c%c%c%cgetinfo",c,c,c,c);




if ((numbytes=sendto(sockfd,buffer, 12, 0,
(struct sockaddr *)&dest_addr, sizeof(struct sockaddr))) == -1) {
AW_ShowError();
return -1;
}


sprintf(buffer,"sent %d bytes to %s\n", numbytes,
inet_ntoa(dest_addr.sin_addr));





addr_len = sizeof(struct sockaddr);


//here is the porblem it causes my program to freese ?

if ((numbytes=recvfrom(sockfd,buf, 4047, 0,
(struct sockaddr *)&dest_addr, &addr_len)) == -1) {

sprintf(buffer,"receaved %d bytes from %s\n", numbytes,
inet_ntoa(dest_addr.sin_addr));

MessageBox(NULL,buffer,"SENDED",0);

AW_ShowError();
exit(1);
}



return 0;

}





The Problem is in this line, once I call it the program freeses:
numbytes=recvfrom(sockfd,buf, 4047, 0,(struct sockaddr *)&dest_addr, &addr_len))

I understand that my program is waiting for the packet to come , but I don't think it should wait for this forever, maybe I am doing something wrong.

Can anyone help me ? What can be the problem ?

[Edited by - DMINATOR on July 25, 2005 2:40:44 PM]

Share this post


Link to post
Share on other sites
Ok I finally did it :). I think the problem was by calling "status" instead of "getstatus" , and using first bytes ff not 0 :). So everything is good :).

Here Is the code if anyone is interested:

#include <winsock.h>
#include <stdio.h>
#include <stdlib.h>



//SOCKET REQUIRED INFORMATION
WSADATA wsaData;

//wsock32.lib
char hostname[80] = "playground.ru";
char message[2048];


#define MYPORT 27910 // standart quake 2 port


void AW_ShowError()
{

printf("Error - %d\n",WSAGetLastError());

}

int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in their_addr; // connector's address information
struct hostent *he;
int numbytes;
char c = 0;


// THIS SHOULD BE DONE BEFORE ANYTHIN ELSE
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
{
AW_ShowError();
return(-1);
}
//here is the message that caused so much trouble
sprintf(message,"\xff\xff\xff\xffstatus");

if ((he=gethostbyname(hostname)) == NULL) { // get the host info
AW_ShowError();
exit(1);
}

if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
AW_ShowError();
exit(1);
}


their_addr.sin_family = AF_INET; // host byte order
their_addr.sin_port = htons(MYPORT); // short, network byte order
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(&(their_addr.sin_zero), '\0', 8); // zero the rest of the struct

if ((numbytes=sendto(sockfd, message, 11, 0,
(struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1) {
perror("sendto");
exit(1);
}

printf("sent %d [%s] bytes to %s:%d\n", numbytes,message,
inet_ntoa(their_addr.sin_addr),MYPORT);


numbytes = recv(sockfd, message, sizeof(message), 0);

printf("[%d],%s\n",numbytes,message);
AW_ShowError();


closesocket(sockfd);

return 0;
}



The only thing that I need to add is timeout check :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!