I am an old user (programming is my hobby) in UT99 I have been playing for more than twenty years. Maybe. Someone remembers me, I played under the nickname Shvonder, Sword. In general, I often changed nicknames (I can't remember them all).
In recent years I haven't played because there was no opportunity - there were no servers. The ones that were available didn't suit me. Not long ago, it became so boring that I set a goal to find a suitable server and start playing on it, which successfully came true!
I found a server and I really liked it. Probably it existed before, but was unknown to me. Yes. As I was researching, I found out that the server is quite old and has a forum. I visited the forum - tried to register, but it didn't work (probably registration was disabled). I wanted to post this program (QueryUT99). So - I decided to leave it here.
The program is written in C++. The source code is attached. You can build it using VC 6.0 (or higher) or Borland C++ 5.x
This is what the request looks like when the server is empty:

So, when there is a player/players on the server:

If found players - message beep (play sound if found the file "Entered.wav").
Default query server port 7778.
Launch program without parameters: query the server 185.145.201.61, if the players are not played until the player is discovered.
The request interval is one and a half minutes. Will try to play sound if
the sound file ("Entered.wav") is located next to the program.
Exit "Escape", key "Delete" - cls (clear screen system).
QueryUT99.cpp
Code: Select all
/* QueryUT99.cpp
*
* Query server Unreal Tournament 1999.
* If found players - message beep
* (play sound if found the file "Entered.wav").
* Default query server port 7778.
* Launch program without parameters:
* query the server 185.145.201.61
* if the players are not played until the player
* is discovered.
* The request interval is one and a half minutes.
* Will try to play sound if the sound file "Entered.wav"
* is located next to the program.
* Exit "Escape", key "Delete" - cls (clear screen system).
*/
#include "QueryUT99.h"
char* GAppname="QueryUT99 -- v1.1";
WORD wAttributes;
void GeneralErrorMessage(char* svStr) {
printf("%s\n",svStr);
system("pause");
exit(1);
}
void Usage()
{
puts(" Usage:");
printf(" QueryUT99 185.145.201.61\n");
puts(" If no standart port (default 7778)");
printf(" QueryUT99 127.0.0.1:31337\n");
system("pause");
exit(1);
}
char* ParseReply(char* svStr, char* svMatch)
{
DWORD dwBytes=strlen(svStr);
if (!dwBytes) return NULL;
char* pBuffer=(char*)malloc(dwBytes+1);
if (!pBuffer)
GeneralErrorMessage("Failed allocate output buffer.");
pBuffer[dwBytes]=0;
strcpy(pBuffer,svStr);
int x=1, nFound=0;
char* ptr=(char*)strchr(pBuffer,'\\');
while (ptr) {
*ptr=0;
if(!x) {
if (!strcmpi(pBuffer,svMatch))
nFound=1;
++x;
} else {
if (nFound)
break;
x=0;
}
strcpy(pBuffer,ptr+1);
ptr=(char*)strchr(pBuffer,'\\');
}
if (!nFound) {
free(pBuffer);
return NULL;
}
return pBuffer;
}
void ParsePlayers_UT99(char* svStr)
{
DWORD dwBytes=strlen(svStr);
if (!dwBytes) return;
char* pBuffer=(char*)malloc(dwBytes+1);
if (!pBuffer)
GeneralErrorMessage("Failed allocate output buffer.");
pBuffer[dwBytes]=0;
strcpy(pBuffer,svStr);
int x=1, nFound=0, nDone=0, nPlayers=0;
char* ptr=(char*)
strchr(pBuffer,'\\');
while (ptr) {
*ptr=0;
if (!x) {
if (strstr(pBuffer,"player_") ||
strstr(pBuffer,"frags_") ||
strstr(pBuffer,"ping_")) {
nFound=1;
printf("%s: ",pBuffer);
}
if (strstr(pBuffer,"mesh_")) {
nFound=1;
nDone=1;
printf("%s: ",pBuffer);
}
++x;
} else {
if (*pBuffer) {
if (nFound) {
nFound=0;
if (!nDone)
{
wAttributes = savecolor();
setcolor(WHITE);
printf("%s ",pBuffer);
restorecolor(wAttributes);
}
else
{
printf("%s\n",pBuffer);
nDone=0;
++nPlayers;
}
printf("\n");
}
}
x=0;
}
strcpy(pBuffer,ptr+1);
ptr=(char*)strchr(pBuffer,'\\');
}
if (nPlayers>0)
{
wAttributes = savecolor();
setcolor(WHITE);
printf("--- %d Players\n",nPlayers);
restorecolor(wAttributes);
}
}
int ParseStatus_UT99(char* svStr)
{
int nNumplayers=0;
while (1) {
unsigned char c=*svStr;
if (c>=32 && c<127)
break;
*svStr++;
}
/* Get "hostname" */
char* svHostname=ParseReply(svStr,"hostname");
if (svHostname) {
printf("hostname: %s\n",svHostname);
char svBuff[512];
sprintf(svBuff,"%s %s",GAppname,svHostname);
SetConsoleTitle(svBuff);
}
/* Get "gamever" */
char* svGamever=ParseReply(svStr,"gamever");
if (svGamever) {
printf("gamever: ");
wAttributes = savecolor();
setcolor(LIGHTGREEN);
printf("%s\n",svGamever);
restorecolor(wAttributes);
}
/* Get "minnetver" */
printf("minnetver: %s\n",ParseReply(svStr,"minnetver"));
/* Get "hostport" */
printf("hostport: %s\n",ParseReply(svStr,"hostport"));
/* Get "mapname" */
printf("mapname: %s\n",ParseReply(svStr,"mapname"));
/* Get "maptitle" */
char* svMaptitle=ParseReply(svStr,"maptitle");
if (svMaptitle)
printf("maptitle: %s\n",svMaptitle);
/* Get "gametype" */
printf("gametype: %s\n",ParseReply(svStr,"gametype"));
/* Get "numplayers" */
char* svNumplayers=ParseReply(svStr,"numplayers");
if (svNumplayers) {
printf("numplayers: %s\n",svNumplayers);
nNumplayers=atoi(svNumplayers);
}
/* Get "maxplayers" */
printf("maxplayers: %s\n",ParseReply(svStr,"maxplayers"));
/* Get "gamemode" */
printf("gamemode: %s\n",ParseReply(svStr,"gamemode"));
/* Get "mutators" */
printf("mutators: %s\n",ParseReply(svStr,"mutators"));
/* Get "timelimit" */
printf("timelimit: %s\n",ParseReply(svStr,"timelimit"));
/* Get "changelevels" */
printf("changelevels: %s\n",ParseReply(svStr,"changelevels"));
/* Get "gamestyle" */
printf("gamestyle: %s\n",ParseReply(svStr,"gamestyle"));
/* Get "AdminName" */
char* svAdminName=ParseReply(svStr,"AdminName");
if (svAdminName)
printf("AdminName: %s\n",svAdminName);
/* Get "AdminEMail" */
char* AdminEMail=ParseReply(svStr,"AdminEMail");
if (AdminEMail)
printf("AdminEMail: %s\n",AdminEMail);
/* Get "queryid" */
printf("queryid: %s\n\n",ParseReply(svStr,"queryid"));
return nNumplayers;
}
int Timeout(SOCKET sock) {
fd_set fds;
FD_ZERO(&fds);
FD_SET(sock,&fds);
struct timeval tv;
tv.tv_usec=0;
tv.tv_sec=TIMEOUT;
int nRet=select(sock+1,&fds,NULL,NULL,&tv);
if (nRet<0 || !nRet)
return -1;
return 0;
}
u_long GetHostAddress(char* svHostname) {
u_long Addr=inet_addr(svHostname);
if (INADDR_NONE==Addr) {
struct hostent* h;
h=gethostbyname(svHostname);
if (h) Addr=*(u_long*)h->h_addr;
}
return Addr;
}
int CheckIp(char* svStr)
{
int count=0;
if (*svStr>='0' && *svStr<='9') {
int len=strlen(svStr);
char* svTemp=(char*)malloc(len+1);
if (!svTemp)
GeneralErrorMessage("Failed allocate memory.");
svTemp[len]=0;
strcpy(svTemp,svStr);
char *ptr, *s;
s=svTemp;
ptr=(char*)strchr(s,'.');
while (ptr) {
*ptr=0;
++count;
s=ptr+1;
if (*s>='0' && *s<='9')
ptr=(char*)strchr(s,'.');
else {
count=0;
break;
}
}
if (3!=count)
count=0;
free(svTemp);
}
return count;
}
void setcolor(WORD color) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),color);
}
void gotoxy(SHORT x, SHORT y) {
COORD coord;
coord.X=x;
coord.Y=y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
}
WORD savecolor(void)
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
WORD wAttributes = LIGHTGRAY;
if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
wAttributes = csbi.wAttributes;
return wAttributes;
}
void restorecolor(WORD wAttributes) {
/* Set the attribute to the original. */
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
wAttributes);
}
char* TimeCalc(int nTotal) {
static char svBuff[64];
int minutes=nTotal / 60;
int seconds=nTotal % 60;
int hours=minutes / 60;
minutes=minutes % 60;
if (!hours) {
if (!minutes)
sprintf(svBuff,"%d secs",seconds);
else
sprintf(svBuff,"%02d:%02d",minutes,seconds);
}
else
sprintf(svBuff,"%2d:%02d:%02d",hours,minutes,seconds);
return svBuff;
}
char* appBaseDir() {
static char svBuff[MAX_PATH];
if (!svBuff[0]) {
GetModuleFileName(GetModuleHandle(NULL),svBuff,MAX_PATH);
int i;
for (i=lstrlen(svBuff)-1;i>0;--i) {
if ('\\'==svBuff[i-1] || '/'==svBuff[i-1])
break;
}
svBuff[i]=0;
}
return svBuff;
}
/*
* Entry point.
*/
void main(int argc, char* argv[])
{
int nPortDest=7778; /* Default query server port. */
char svBuff[1024];
char svHostname[256];
svBuff[0]=svHostname[0]=0;
SetConsoleTitle(GAppname);
if (argc<2)
strcpy(svHostname,"185.145.201.61");
else {
for (int x=1;x<argc;++x) {
if (!svBuff[0])
{
if (0==strcmpi(argv[x],"-?") ||
0==strcmpi(argv[x],"-HELP"))
{
Usage();
}
strcpy(svBuff,argv[x]);
continue;
}
} /* End "for" */
if (strstr(svBuff,":"))
{
char* svTemp=svBuff;
char* ptr=strchr(svTemp,':');
while (ptr) {
*ptr=0;
if (*svTemp)
strcpy(svHostname,svTemp);
svTemp=ptr+1;
ptr=strchr(svTemp,':');
} /* End "while" */
nPortDest=atoi(svTemp);
if (7777==nPortDest || 0==nPortDest)
nPortDest=7778;
}
else
strcpy(svHostname,svBuff);
if (nPortDest>0xFFFF) /* 65535 */
{
sprintf(svBuff,
"Failed the port number \"%d\".\n"
"Maximum the port number 65535.",
nPortDest);
GeneralErrorMessage(svBuff);
}
if (!svHostname[0]) {
printf("Failed. Missing hostname.\n");
Usage();
}
if (!CheckIp(svHostname)) {
printf("Failed hostname.\n");
Usage();
}
}
/* Level #1 */
WSADATA wsadata;
if (WSAStartup(MAKEWORD(2,2),&wsadata))
GeneralErrorMessage("Error initializing winsock.");
AGAIN:
/* Resolving host. */
struct sockaddr_in ToAddr;
ToAddr.sin_family=AF_INET;
ToAddr.sin_port=htons((WORD)nPortDest);
ToAddr.sin_addr.s_addr=GetHostAddress(svHostname);
if (INADDR_NONE==ToAddr.sin_addr.s_addr) {
sprintf(svBuff,"Failed resolving hostname \"%s\"",svHostname);
GeneralErrorMessage(svBuff);
}
SOCKET sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if (INVALID_SOCKET==sock)
GeneralErrorMessage("Failed create socket.");
time_t curtime=time(NULL);
char* svTime=ctime(&curtime);
if ('\n'==svTime[strlen(svTime)-1])
svTime[strlen(svTime)-1]=0;
printf("---[ %s port: %d, %s ]---\r\n",inet_ntoa(ToAddr.sin_addr),nPortDest,svTime);
/* Current "\\status\\"
* or: "\\basic\\", "\\info\\", "\\players\\"
*/
strcpy(svBuff,"\\status\\");
int nLen=strlen(svBuff);
int nRet=sendto(sock,svBuff,nLen,0,(struct sockaddr*)&ToAddr,sizeof(ToAddr));
if (nRet<0) {
closesocket(sock);
GeneralErrorMessage("Failed SendTo.");
}
if (Timeout(sock)<0) {
closesocket(sock);
GeneralErrorMessage("Failed socket timeout, no reply received.");
}
nRet=recvfrom(sock,svBuff,1024,0,NULL,NULL);
if (nRet<0) {
closesocket(sock);
GeneralErrorMessage("Failed receive data.");
}
svBuff[nRet]=0;
int nNumplayers=ParseStatus_UT99(svBuff);
if (nNumplayers)
{
ParsePlayers_UT99(svBuff);
closesocket(sock);
WSACleanup();
/* Play sound if found "Entered.wav". */
char svFilename[MAX_PATH];
wsprintf(svFilename,"%Entered.wav",appBaseDir());
WIN32_FIND_DATA FindFile;
HANDLE handle=FindFirstFile(svFilename,&FindFile);
if (INVALID_HANDLE_VALUE!=handle) {
FindClose(handle);
if (!PlaySound(svFilename,NULL,SND_FILENAME|SND_NODEFAULT|SND_NOWAIT|SND_ASYNC))
printf("Unable to play sound.\n");
}
system("pause");
exit(1);
}
else
{
wAttributes = savecolor();
setcolor(LIGHTRED);
printf("--- NO players.\n");
restorecolor(wAttributes);
}
puts("");
MSG msg;
nRet=3000;
while (nRet)
{
/* Press key "Escape"? */
SHORT ptr=GetAsyncKeyState(VK_ESCAPE);
if (ptr)
exit(1);
/* Press key "Delete"? */
ptr=GetAsyncKeyState(VK_DELETE);
if (ptr)
system("cls");
Sleep(20);
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
--nRet;
//printf("\rNext launch query left %d", nRet);
printf("\rNext launch query left %s",TimeCalc(nRet));
}
puts("");
__asm jmp AGAIN
}
QueryUT99.h
Code: Select all
/* QueryUT99.h */
#pragma once
#ifdef _MSC_VER
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"winmm.lib")
#endif
#include <windows.h>
#include <time.h>
#include <stdio.h>
#ifndef _MSC_VER
#pragma option -w-aus
#pragma option -w-par
#endif
#define TIMEOUT 3
enum COLORS {
BLACK,
BLUE,
GREEN,
CYAN,
RED,
MAGENTA,
BROWN,
LIGHTGRAY,
DARKGRAY,
LIGHTBLUE,
LIGHTGREEN,
LIGHTCYAN,
LIGHTRED,
LIGHTMAGENTA,
YELLOW,
WHITE
};
void setcolor(WORD color);
void gotoxy(SHORT x, SHORT y);
WORD savecolor(void);
void restorecolor(WORD wAttributes);