UT99 Server Query

External tools, software and sites for creating or editing UT99 resources.
User avatar
Shvonder
Novice
Posts: 9
Joined: Sat Apr 11, 2015 9:47 pm

UT99 Server Query

Post by Shvonder »

Hi. This tool will allow you to watch your favorite server.
This is the first version, the idea was born for a long time, although it is very easy, almost all of the code is taken from a browser game. My job was to make the shell. At first, I wanted to make a complete copy of the browser, but then refused.
Attachments
UT99Query.zip
(323.98 KiB) Downloaded 172 times
preview_ut99query.jpg
User avatar
Shvonder
Novice
Posts: 9
Joined: Sat Apr 11, 2015 9:47 pm

Re: UT99 Server Query

Post by Shvonder »

If you're interested, here's the part that informs. (C ++ code)
Engine.cpp

Code: Select all

/////////////////////////////////////////////////////////////////////////////
// Engine.cpp
//
//
//	Запрос и обработка ответа сервера.
//
//
#include "stdafx.h"
#include "App.h"
#include "QueryServer.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

TCHAR Buffer[4096]	= TEXT("");
FString m_sValue	= Buffer;
FString m_sIn		= Buffer;
FString m_sOut		= Buffer;

/////////////////////////////////////////////////////////////////////////////
//
//	Запрос и обработка ответа сервера.
//
/////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////
// DefaultData
//
// Обнулить данные, адрес, порт сервера, установить по умолчанию.
//
void CMainFrame::DefaultData()
{
	m_sHostAddress	= m_sDefaultHostAddress;
	m_nHostPort		= m_nDefaultHostPort;

	m_sPlayerName.Empty();
	m_nPlayerFrags	= 0;
	m_nPlayerPing	= 0;
	m_sPlayerTeam.Empty();
	m_sPlayerMesh.Empty();
	m_sPlayerSkin.Empty();
	m_sPlayerFace.Empty();
	m_nPlayerID		= 0;
	m_sPlayerStats.Empty();

	m_sPlayer.Empty();
}

int CMainFrame::Int(FString Text)
{
	return _wtoi( *Text );
}
FString CMainFrame::LocalizeTeam(FString TeamNum)
{
	if( TeamNum == TEXT("255") )
		return TEXT("");

	return TeamNum;
}
FString CMainFrame::GetItemName(FString FullName)
{
	int pos;
	pos = FullName.InStr( TEXT(".") );
	while( pos != -1 )
	{
		FullName = FullName.Right( FullName.Len() - pos - 1 );
		pos = FullName.InStr( TEXT(".") );
	}
	return FullName;
}
FString CMainFrame::LocalizeBoolValue(FString Value)
{
	if( Value != TEXT("True") )
		return m_sTrueString;

	if( Value != TEXT("False") )
		return m_sFalseString;

	return Value;
}
FString CMainFrame::LocalizeSkin(FString SkinName)
{
	static FString MeshName;
	MeshName = SkinName.Left( SkinName.InStr(TEXT(".")) );
	return MeshName;
}
BOOL CMainFrame::GetNextValue(FString In, FString Out, FString Result)
{
	m_sValue.Empty();
	Result = TEXT("");

	BOOL bFoundStart = FALSE;
	int i;

	for( i = 0; i < In.Len(); ++i ) 
	{
		if( bFoundStart )
		{
			if( In.Mid( i, 1 ) == "\\" )
			{
				m_sOut = In.Right( In.Len() - i );
				return TRUE;
			}
			else
			{
				Result += In.Mid( i, 1 );
				m_sValue = Result;
			}
		}
		else
		{
			if( In.Mid( i, 1 ) == "\\" )
			{
				bFoundStart = TRUE;
			}
		}
	}
	return FALSE;
}
FString CMainFrame::ParseReply(FString Text, FString Key)
{
	FString key = FString::Printf( TEXT( "\\%s\\" ), *Key );

	FString Temp;
	int i = Text.InStr( key );
	//Temp = Text.Mid( i + key.Len() + 2 );
	Temp = Text.Mid( i + key.Len() );
	return Temp.Left( Temp.InStr( TEXT( "\\") ) );
}

/////////////////////////////////////////////////////////////////////////////
// AddRule
//
// Добавить к ListView.
//
void CMainFrame::AddRule( FString PlayerName, int nPlayerFrags,
					int nPlayerPing, FString PlayerTeam,
					FString PlayerMesh, FString PlayerSkin,
					FString PlayerFace, int nPlayerID
					)

{
	CString s;

	BuildItems( INDEX_NAME, *PlayerName );
	m_sPlayer += *PlayerName;
	m_sPlayer += _T("\n");

	s.Format( _T("%d"), nPlayerFrags );
	BuildItems( INDEX_FRAGS, s );

	//m_sPlayer += _T(" Frags: ");
	//m_sPlayer += s;

	s.Format( TEXT("%d"), nPlayerPing );
	BuildItems( INDEX_PING, s );

	//m_sPlayer += _T(" Ping: ");
	//m_sPlayer += s;
	//m_sPlayer += _T("\n");

	BuildItems( INDEX_TEAM, *PlayerTeam );
	BuildItems( INDEX_MESH, *PlayerMesh );
	BuildItems( INDEX_SKIN, *PlayerSkin );
	BuildItems( INDEX_FACE, *PlayerFace );
	
	s.Format( TEXT( "%d" ), nPlayerID );
	BuildItems( INDEX_ID, s );
}

/////////////////////////////////////////////////////////////////////////////
// GetInfo
//
// Разбор.
//

/*
void CMainFrame::GetInfo(FString Text)
{
	CString sMsg;
	FString Temp;

	// Получить имя сервера.
	Temp = ParseReply(Text, TEXT("hostname") );
	if( Temp != TEXT("") )
		m_sHostName = Temp;

	// Имя сервера:
	//sMsg += TEXT( "Имя сервера:\n" );
	//sMsg += *Temp;
	//sMsg += TEXT( "\n" );

	// Получить порт сервера.
	Temp = ParseReply(Text, TEXT("hostport") );
	if( Temp != TEXT("") )
		m_nGamePort = Int(Temp);

	// debug - Порт сервера:
	//sMsg += TEXT( "Порт сервера:\n" );
	//sMsg += *Temp;
	//sMsg += TEXT( "\n" );

	// Получить название карты.
	Temp = ParseReply(Text, TEXT("mapname") );
	if( Temp != TEXT("") )
		m_sMapName = Temp;

	// debug - Имя карты:
	//sMsg += TEXT( "Название карты:\n" );
	//sMsg += *Temp;
	//sMsg += TEXT( "\n" );

	// Получить заголовок карты.
	Temp = ParseReply(Text, TEXT("maptitle") );
	if( Temp != TEXT("") )
	{
		m_sMapTitle = Temp;
		m_sMapDisplayName = m_sMapTitle;
		//if( m_sMapTitle == GEmpty || m_sMapTitle == GUntitled )
		if( m_sMapTitle == TEXT("") || m_sMapTitle == TEXT("Untitled") )
			m_sMapDisplayName = m_sMapName;
	}
		
	// debug - Зоголовок карты:
	//sMsg += TEXT( "Зоголовок карты:\n" );
	//sMsg += *Temp;
	//sMsg += TEXT( "\n" );

	Temp = ParseReply(Text, TEXT("gametype") );
	if( Temp != TEXT("") )
		m_sGameType = Temp;

	// debug - Тип игры
	//sMsg += TEXT( "Тип игры:\n" );
	//sMsg += *Temp;
	//sMsg += TEXT( "\n" );

	// Получить число игроков.
	Temp = ParseReply(Text, TEXT("numplayers") );
	if( Temp != TEXT("") )
		m_nNumPlayers = Int(Temp);

	// debug - Число игроков:
	//sMsg += TEXT( "Число игроков:\n" );
	//sMsg += *Temp;
	//sMsg += TEXT( "\n" );
	
	// Получить число допустимых игроков.
	Temp = ParseReply(Text, TEXT("maxplayers") );
	if( Temp != TEXT("") )
		m_nMaxPlayers = Int(Temp);
	
	// debug - Максимум игроков:
	//sMsg += TEXT( "Максимум игроков:\n" );
	//sMsg += *Temp;
	//sMsg += TEXT( "\n" );

	// Получить режим игры.
	Temp = ParseReply(Text, TEXT("gamemode") );
	if( Temp != TEXT("") )
		m_sGameMode = Temp;

	// debug - Режим игры:
	//sMsg += TEXT( "Режим игры:\n" );
	//sMsg += *Temp;
	//sMsg += TEXT( "\n" );
	
	// Получить версию игры.
	Temp = ParseReply(Text, TEXT("gamever") );
	if( Temp != TEXT("") )
		m_nGameVer = Int(Temp);

	// debug - Версия игры:
	//sMsg += TEXT( "Версия игры:\n" );
	//sMsg += *Temp;
	//sMsg += TEXT( "\n" );
	

	// Получить минимально поддерживаемую версию игры.
	Temp = ParseReply(Text, TEXT("minnetver") );
	if( Temp != TEXT("") )
		m_nMinNetVer = Int(Temp);

	// debug - Минимально поддерживаемаю версия игры:
	//sMsg += TEXT( "Минимально поддерживаемаю версия:\n" );
	//sMsg += *Temp;
	//sMsg += TEXT( "\n" );
	//MessageBox( sMsg, TEXT("Information"),MB_OK|MB_ICONINFORMATION|MB_SETFOREGROUND|MB_TOPMOST);
}
*/

/////////////////////////////////////////////////////////////////////////////
// GetStatus
//
// Основной разбор.
//
void CMainFrame::GetStatus(FString Text)
{
	int Result = CheckEngine();
	if( Result ) return;

	// Очистить список ListView.
	ClearResponse();

	int nID;
	BOOL bOK;

	m_sOut.Empty();
	m_sValue.Empty();

	m_sIn = *Text;

	do {		
		bOK		= GetNextValue(m_sIn,m_sOut,m_sValue);
		m_sIn	= m_sOut;
		if( m_sValue.Left( 7 )==TEXT("player_") )
		{
			nID = Int(m_sValue.Right(m_sValue.Len() - 7));

			++nID;

			m_nPlayerID		= nID;
			bOK				= GetNextValue(m_sIn,m_sOut,m_sValue);
			m_sIn			= m_sOut;
			m_sPlayerName	= m_sValue;
		} 
		else if( m_sValue.Left( 6 ) == TEXT("frags_") )
		{
			nID				= Int(m_sValue.Right(m_sValue.Len() - 6));
			bOK				= GetNextValue(m_sIn,m_sOut,m_sValue);
			m_sIn			= m_sOut;
			m_nPlayerFrags	= Int(m_sValue);
		}
		else if( m_sValue.Left( 5 ) == TEXT("ping_") )
		{
			nID				= Int(m_sValue.Right(m_sValue.Len() - 5));
			bOK				= GetNextValue(m_sIn,m_sOut,m_sValue);
			m_sIn			= m_sOut;
			m_nPlayerPing	= Int(m_sValue.Right(m_sValue.Len() - 1));
		}
		else if( m_sValue.Left( 5 ) == TEXT("team_") )
		{
			nID				= Int(m_sValue.Right(m_sValue.Len() - 5));
			bOK				= GetNextValue(m_sIn,m_sOut,m_sValue);
			m_sIn			= m_sOut;

			m_sPlayerTeam	= LocalizeTeam(m_sValue);
			if( m_sPlayerTeam == TEXT("") )
				m_sPlayerTeam = TEXT("255");
		}
		else if( m_sValue.Left( 5 ) == TEXT("skin_") )
		{
			nID				= Int(m_sValue.Right(m_sValue.Len() - 5));
			bOK				= GetNextValue(m_sIn,m_sOut,m_sValue);
			m_sIn			= m_sOut;			
			m_sPlayerSkin	= LocalizeSkin(m_sValue);
		}
		else if( m_sValue.Left( 5 ) == TEXT("face_") )
		{
			nID				= Int(m_sValue.Right(m_sValue.Len() - 5));
			bOK				= GetNextValue(m_sIn,m_sOut,m_sValue);
			m_sIn			= m_sOut;
			m_sPlayerFace	= GetItemName(m_sValue);
		}
		else if( m_sValue.Left( 5 ) == TEXT("mesh_") )
		{
			nID				= Int(m_sValue.Right(m_sValue.Len() - 5));
			bOK				= GetNextValue(m_sIn,m_sOut,m_sValue);
			m_sIn			= m_sOut;			
			m_sPlayerMesh	= m_sValue;

			//
			// Out...
			// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
			//
			AddRule(
				m_sPlayerName,
				m_nPlayerFrags,
				m_nPlayerPing,
				m_sPlayerTeam,
				m_sPlayerMesh,
				m_sPlayerSkin,
				m_sPlayerFace,
				m_nPlayerID
				);

			// Check exit?
			Result = CheckEngine();
			if( Result ) return;
		}

		/*
		else if( m_sValue.Left( 9 ) == TEXT("ngsecret_") )
		{
			nID				= Int(m_sValue.Right(m_sValue.Len() - 9));
			bOK				= GetNextValue(m_sIn,m_sOut,m_sValue);
			m_sIn			= m_sOut;		
			m_sPlayerStats	= m_sValue;
		}
		*/

		//
		// Имя сервера.
		//
		else if( m_sValue.Left( 8 ) == TEXT("hostname") )
		{
			nID				= Int(m_sValue.Right(m_sValue.Len() - 8));
			bOK				= GetNextValue(m_sIn,m_sOut,m_sValue);
			m_sIn			= m_sOut;		
			m_sServername	= *m_sValue;
		}

		else if( m_sValue == TEXT("final") )
		{
			//
			// __ F i n a l __
			//
			m_nStatusDone = TRUE;
			return;
		}
		else if( m_sValue == TEXT("gamever") )
		{
			bOK	= GetNextValue(m_sIn,m_sOut,m_sValue);
			
			//Temp = *m_sIn;
			//Temp = *m_sOut;
			//Temp = *m_sValue;

			//AddRule(GameVersionText, m_sValue);
		}
		else if( m_sValue == TEXT("minnetver") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(MinNetVersionText, m_sValue);
		}
		else if( m_sValue == TEXT("gametype") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(GameTypeText, m_sValue);
		}	
		else if( m_sValue == TEXT("timelimit") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(TimeLimitText, m_sValue);
		}
		else if( m_sValue == TEXT("fraglimit") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(FragLimitText, m_sValue);
		}
		else if( m_sValue == TEXT("MultiplayerBots") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(MultiplayerBotsText, LocalizeBoolValue(m_sValue));
		}
		else if( m_sValue == TEXT("AdminName") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(AdminNameText, m_sValue);
		}
		else if( m_sValue == TEXT("AdminEMail") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(AdminEmailText, m_sValue);
		}
		else if( m_sValue == TEXT("WantWorldLog") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(WorldLogText, LocalizeBoolValue(m_sValue));
		}
		else if( m_sValue == TEXT("WorldLog") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			/*
			if( Server.GameVer >= 406 )
			{
				if( m_sValue ~= TEXT("True") )
					AddRule(WorldLogWorkingText, WorldLogWorkingTrue);
				else
					AddRule(WorldLogWorkingText, WorldLogWorkingFalse);
			}
			else
				AddRule(WorldLogText, LocalizeBoolValue(m_sValue));
			*/
		}
		else if( m_sValue == TEXT("mutators") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(MutatorsText, m_sValue);
		}
		else if( m_sValue == TEXT("goalteamscore") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(GoalTeamScoreText, m_sValue);		
		}
		else if( m_sValue == TEXT("minplayers") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			/*
			if( m_sValue == TEXT( "0" ) )
				//AddRule(MultiplayerBotsText, FalseString);
			else
				//AddRule(MinPlayersText, m_sValue@PlayersText);

				//AddRule(MinPlayersText, m_sValue);
			*/
		}
		else if( m_sValue == TEXT("changelevels") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(ChangeLevelsText, LocalizeBoolValue(m_sValue));		
		}
		else if( m_sValue == TEXT("botskill") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(BotSkillText, m_sValue);		
		}
		else if( m_sValue == TEXT("maxteams") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(MaxTeamsText, m_sValue);
		}
		else if( m_sValue == TEXT("balanceteams") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(BalanceTeamsText, LocalizeBoolValue(m_sValue));
		}
		else if( m_sValue == TEXT("playersbalanceteams") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(PlayersBalanceTeamsText, LocalizeBoolValue(m_sValue));
		}
		else if( m_sValue == TEXT("friendlyfire") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(FriendlyFireText, m_sValue);
		}
		else if( m_sValue == TEXT("gamestyle") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(GameModeText, m_sValue);
		}
		else if( m_sValue == TEXT("tournament") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(TournamentText, LocalizeBoolValue(m_sValue));
		}
		else if( m_sValue == TEXT("listenserver") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			/*
			if(bool(m_sValue))
				AddRule(ServerModeText, NonDedicatedText);
			else
				AddRule(ServerModeText, DedicatedText);
			*/
		}
		else if( m_sValue == TEXT("password") )
		{
			bOK = GetNextValue(m_sIn,m_sOut,m_sValue);
			//AddRule(PasswordText, LocalizeBoolValue(m_sValue));
		}
	} while( bOK );
}

/////////////////////////////////////////////////////////////////////////////
// DoQuery
//
// Подготовка запроса.
//
int CMainFrame::DoQuery() 
{
	debugf( m_sStartQuery );
	
	m_nPlayerID = 0;

	// Проверка на 'Выход' ?
	int Result = CheckEngine();
	if( Result )
	{
		// Да, выход.
		return Result;
	}

	const TCHAR* Magicstring;
	Magicstring = TEXT( "\\status\\" );
	//Magicstring = TEXT( "\\info\\" );
	//Magicstring = TEXT( "\\players\\" );
	
	//
	// -- Текущий -- Madrixis --
	//
	// Server: Multiplay :: Public DM #13 (Deck16 - All Weapons)
	//m_sHostAddress = TEXT("85.236.100.115");
	//m_nHostPort = 8178;

	//nPort = 8078;
	//nPort = 8278;
	//nPort = 7878;
	//nPort = 7978;
	//nPort = 8177;

	// 1
	// Server: zp| [=======] [PURE] [INSTAGIB] [UK] [======
	//Hostaddress = TEXT("185.16.85.10");
	//nPort = 7778;

	// 2
	// Server: ROCKET - OLYMPIC - PHOENIX
	//m_sHostaddress = TEXT("108.61.254.168");
	//nPort = 7778;


	// Нет ли в текущем каталоге файла "servers.txt" ?
	// Если есть, попытаться получить данные оттуда.
	CheckFileServer();


	// Инициализация класса "QueryServer".
	QueryServer* query;
	query = new QueryServer();

	Result = query->Start(m_sHostAddress, m_nHostPort, Magicstring);
	if( Result < 0 )
	{
		Sleep(100);
		//MessageBox(TEXT("-->FAILED: QueryServer = 0x0FFFFFFFF"),
		//	TEXT("UDP Ping Server"),MB_OK|MB_ICONSTOP|MB_SETFOREGROUND|MB_TOPMOST);

		// Удалить Queryserver.
		delete query;
		return -2;
	}

	// Проверка на 'Выход' ?
	Result = CheckEngine();
	if( Result )
	{
		// Да, выход.
		delete query;
		return Result;
	}

	// Копировать данные.
	FString Buffer = query->GetResponse();
	if( Buffer.Len()==0 )
	{
		// Данных нет.
		debugf( TEXT("No data from server: %s port: %i"), m_sHostAddress,  m_nHostPort);
		delete query;
		return -3;
	}

	// Обработка данных.
	GetStatus( Buffer );
	delete query;

	debugf( m_sEndQuery );
	return m_nPlayerID;
}

/////////////////////////////////////////////////////////////////////////////
// GetServerAddressPort

BOOL CMainFrame::GetServerAddressPort(const TCHAR* Stream)
{
	BOOL bResult = 0x0FFFFFFFF;
	TCHAR Temp[256], *URL=Temp;

	TCHAR Line[256];
	while( ParseLine( &Stream, Line, ARRAY_COUNT(Line),1) )
	{
		const TCHAR* Data = Line;		
		if(	Data[0]==';' || Data[0]=='/' )
			continue;

		FString Str( Line );
		TCHAR* Start = const_cast<TCHAR*>(*Str);
		TCHAR* End   = Start + Str.Len();
		//while( Start<End && (Start[0]=='\r' || Start[0]=='\n' || Start[0]==' ') )
		while( Start<End && (Start[0]=='\r' || Start[0]=='\n' || Start[0]=='\t' || Start[0]==' ') )
			++Start;
		//while( End>Start && (End [-1]=='\r' || End [-1]=='\n' || End [-1]==' ') )
		while( End>Start && (End [-1]=='\r' || End [-1]=='\n' || End [-1]=='\t' || End [-1]==' ') )
			--End;
		*End = 0;
		
		appStrncpy( Temp, Start, ARRAY_COUNT(Temp) );
		
		// Skip leading blanks.
		//while( *URL == ' ' )
		//	URL++;

		if( appStrlen(URL)>2 && URL[1]==':' )
		{
			return bResult;
		}
		else
		{
			// Parse optional host name and port.
			const TCHAR* Dot = appStrchr(URL,'.');
			if(	( Dot ) && ( Dot - URL > 0 ) )
			{
				TCHAR* s = URL;
				TCHAR* t = appStrchr(s,':');
				if( t )
				{
					// Порт сервера.
					*t++ = 0;
					m_nHostPort = appAtoi( t );
				}

				// Адрес сервера.
				m_sHostAddress = CString( s );
				return 0;
			}
		}
	}
	return bResult;
}

/*
//
// Get port 1.
//
FString GetPort( FString Input )
{
	int pos;
	pos = Input.InStr( TEXT(":") );
	while( pos != -1 )
	{
		Input = Input.Right( Input.Len() - pos - 1 );
		pos = Input.InStr( TEXT(":") );
	}
	return Input;
}
// Return the server's port number.
int GetServerPort(FString Input)
{
	int i;
	// Figure out the server's port.
	//Input = Level.GetAddressURL();
	i = Input.InStr( TEXT(":") );
	//assert(i>=0);
	return int( Input.Mid( i+1 ) );
}
*/

/////////////////////////////////////////////////////////////////////////////
// CheckFileServer
//
// Перед каждым запросом, программа будет смотреть, если в текущем
// каталоге текстовой файл "servers.txt", при его наличии: адрес и порт сервера
// считывается оттуда. Файл размером больше 8 килобайт игнорируется.
// Формат записи, пример:
// 85.236.100.115:8178
// Берётся только одна строка, символ точки с запятой является комментарием.
// Если адрес корректный вы будете видеть отображение сервера.
//
void CMainFrame::CheckFileServer()
{
	const TCHAR* Filename;
	//Filename = TEXT("c:\\servers.txt");
	Filename = TEXT("servers.txt");
	FString Data;
	if( appLoadFileToString(Data,Filename)==0 )
	{
		//debugf( TEXT("Could not open file %s"), Filename );
		//FString Msg = FString::Printf(TEXT("Could not open file %s"), Filename);
		//MessageBox( *Msg, TEXT("Error"), MB_OK|MB_ICONWARNING|MB_SETFOREGROUND|MB_TOPMOST);
		return;
	}

	// Проверить размер файла.
	// Если пустой или больше 8 килобайт, не обрабатывать.
	int nSize = Data.Len();
	if( nSize==0 )
	{
		// Файл пуст, установить по умолчанию.
		debugf( TEXT("Empty file %s"), Filename );
		DefaultData();
		return;
	}
	if( nSize > 8000 )
	{
		// Файл больше 8 kb, установить по умолчанию.
		debugf( TEXT("File %s large 8 kb"), Filename );
		DefaultData();
		return;
	}

	// Чтение данных из файла "servers.txt".
	if( GetServerAddressPort( *Data ) != 0)
	{
		// Данных нет.
		debugf( TEXT("Missing data %s"), Filename );
		DefaultData();
		return;
	}

	debugf( TEXT("New host query %s:%d"), m_sHostAddress, m_nHostPort );

	//FString Msg;
	//Msg = FString::Printf( TEXT( "%s" ), GetServerAddressPort( *Data ) );
	//MessageBox( *Msg, TEXT("Error"), MB_OK|MB_ICONWARNING|MB_SETFOREGROUND|MB_TOPMOST);
}

/////////////////////////////////////////////////////////////////////////////
// <<eof>> Engine.cpp
/////////////////////////////////////////////////////////////////////////////

--Edit by UnrealGecko--
QueryServer.cpp

Code: Select all

////////////////////////////////////////////////////////////////////////////////
// QueryServer.cpp

#include "stdafx.h"
#include "App.h"
#include "QueryServer.h"

BOOL GWSAInitialized;

////////////////////////////////////////////////////////////////////////////////
// InitSockets

UBOOL InitSockets( FString& Error )
{
	GWSAInitialized = 1;
	return GWSAInitialized;

/*
	// Init WSA.
	static UBOOL Tried = 0;
	if( !Tried )
	{
		Tried = 1;
		WSADATA WSAData;
		int Code = WSAStartup( 0x0101, &WSAData );
		if( Code==0 )
		{
			//GHostByNameCriticalSection	= GSynchronizeFactory->CreateCriticalSection();
			GWSAInitialized			= 1;
			debugf
			(
				NAME_Init,
				TEXT("WinSock: version %i.%i (%i.%i), MaxSocks=%i, MaxUdp=%i"),
				WSAData.wVersion>>8,WSAData.wVersion&255,
				WSAData.wHighVersion>>8,WSAData.wHighVersion&255,
				WSAData.iMaxSockets,WSAData.iMaxUdpDg
			);
			//debugf( NAME_Init, TEXT("WinSock: %s"), WSAData.szDescription );
		} else {
			TCHAR Error256[256];
			appSprintf( Error256, TEXT("WSAStartup failed (%s)"), SocketError(Code) );
			Error = FString::Printf( TEXT("%s"), Error256 );
		}
	}
	return GWSAInitialized;
	*/
}

////////////////////////////////////////////////////////////////////////////////
// SocketError
//
// Преобразование кода ошибки к тексту.

TCHAR* SocketError( int Code )
{
	if( Code == -1 )
		Code = WSAGetLastError();
	switch( Code )
	{
		case WSAEINTR:				return TEXT("WSAEINTR");
		case WSAEBADF:				return TEXT("WSAEBADF");
		case WSAEACCES:				return TEXT("WSAEACCES");
		case WSAEFAULT:				return TEXT("WSAEFAULT");
		case WSAEINVAL:				return TEXT("WSAEINVAL");
		case WSAEMFILE:				return TEXT("WSAEMFILE");
		case WSAEWOULDBLOCK:		return TEXT("WSAEWOULDBLOCK");
		case WSAEINPROGRESS:		return TEXT("WSAEINPROGRESS");
		case WSAEALREADY:			return TEXT("WSAEALREADY");
		case WSAENOTSOCK:			return TEXT("WSAENOTSOCK");
		case WSAEDESTADDRREQ:		return TEXT("WSAEDESTADDRREQ");
		case WSAEMSGSIZE:			return TEXT("WSAEMSGSIZE");
		case WSAEPROTOTYPE:			return TEXT("WSAEPROTOTYPE");
		case WSAENOPROTOOPT:		return TEXT("WSAENOPROTOOPT");
		case WSAEPROTONOSUPPORT:	return TEXT("WSAEPROTONOSUPPORT");
		case WSAESOCKTNOSUPPORT:	return TEXT("WSAESOCKTNOSUPPORT");
		case WSAEOPNOTSUPP:			return TEXT("WSAEOPNOTSUPP");
		case WSAEPFNOSUPPORT:		return TEXT("WSAEPFNOSUPPORT");
		case WSAEAFNOSUPPORT:		return TEXT("WSAEAFNOSUPPORT");
		case WSAEADDRINUSE:			return TEXT("WSAEADDRINUSE");
		case WSAEADDRNOTAVAIL:		return TEXT("WSAEADDRNOTAVAIL");
		case WSAENETDOWN:			return TEXT("WSAENETDOWN");
		case WSAENETUNREACH:		return TEXT("WSAENETUNREACH");
		case WSAENETRESET:			return TEXT("WSAENETRESET");
		case WSAECONNABORTED:		return TEXT("WSAECONNABORTED");
		case WSAECONNRESET:			return TEXT("WSAECONNRESET");
		case WSAENOBUFS:			return TEXT("WSAENOBUFS");
		case WSAEISCONN:			return TEXT("WSAEISCONN");
		case WSAENOTCONN:			return TEXT("WSAENOTCONN");
		case WSAESHUTDOWN:			return TEXT("WSAESHUTDOWN");
		case WSAETOOMANYREFS:		return TEXT("WSAETOOMANYREFS");
		case WSAETIMEDOUT:			return TEXT("WSAETIMEDOUT");
		case WSAECONNREFUSED:		return TEXT("WSAECONNREFUSED");
		case WSAELOOP:				return TEXT("WSAELOOP");
		case WSAENAMETOOLONG:		return TEXT("WSAENAMETOOLONG");
		case WSAEHOSTDOWN:			return TEXT("WSAEHOSTDOWN");
		case WSAEHOSTUNREACH:		return TEXT("WSAEHOSTUNREACH");
		case WSAENOTEMPTY:			return TEXT("WSAENOTEMPTY");
		case WSAEPROCLIM:			return TEXT("WSAEPROCLIM");
		case WSAEUSERS:				return TEXT("WSAEUSERS");
		case WSAEDQUOT:				return TEXT("WSAEDQUOT");
		case WSAESTALE:				return TEXT("WSAESTALE");
		case WSAEREMOTE:			return TEXT("WSAEREMOTE");
		case WSAEDISCON:			return TEXT("WSAEDISCON");
		case WSASYSNOTREADY:		return TEXT("WSASYSNOTREADY");
		case WSAVERNOTSUPPORTED:	return TEXT("WSAVERNOTSUPPORTED");
		case WSANOTINITIALISED:		return TEXT("WSANOTINITIALISED");
		case WSAHOST_NOT_FOUND:		return TEXT("WSAHOST_NOT_FOUND");
		case WSATRY_AGAIN:			return TEXT("WSATRY_AGAIN");
		case WSANO_RECOVERY:		return TEXT("WSANO_RECOVERY");
		case WSANO_DATA:			return TEXT("WSANO_DATA");
		case 0:						return TEXT("WSANO_ERROR");
		default:					return TEXT("WSA_Unknown");
	}
}

////////////////////////////////////////////////////////////////////////////////
// bindnextport
//
// Bind to next available port.
// Привязать к следующему доступному порту.

int bindnextport( SOCKET s, struct sockaddr_in* addr, int portcount, int portinc )
{
	for( int i=0; i<portcount; ++i )
	{
		if( !bind( s, (sockaddr*)addr, sizeof(sockaddr_in) ) )
		{
			if (ntohs(addr->sin_port) != 0)
				return ntohs(addr->sin_port);
			else
			{
				// 0 означает выделить порт для нас,
				// так что найти, что этот порт был
				struct sockaddr_in boundaddr;
				SOCKLEN size = sizeof(boundaddr);
				getsockname ( s, (sockaddr*)(&boundaddr), &size);
				return ntohs(boundaddr.sin_port);
			}
		}
		if( addr->sin_port==0 )
			break;
		addr->sin_port = htons( ntohs(addr->sin_port) + portinc );
	}
	return 0;
}

UBOOL IpMatches( sockaddr_in& A, sockaddr_in& B )
{
	return	A.sin_addr.S_un.S_addr == B.sin_addr.S_un.S_addr
	&&		A.sin_port             == B.sin_port
	&&		A.sin_family           == B.sin_family;
}
void IpGetBytes( in_addr Addr, BYTE& Ip1, BYTE& Ip2, BYTE& Ip3, BYTE& Ip4 )
{
	Ip1 = IP(Addr,1);
	Ip2 = IP(Addr,2);
	Ip3 = IP(Addr,3);
	Ip4 = IP(Addr,4);
}
void IpSetBytes( in_addr& Addr, BYTE Ip1, BYTE Ip2, BYTE Ip3, BYTE Ip4 )
{
	IP(Addr,1) = Ip1;
	IP(Addr,2) = Ip2;
	IP(Addr,3) = Ip3;
	IP(Addr,4) = Ip4;
}
void IpGetInt( in_addr Addr, DWORD& Ip )
{
	Ip = Addr.S_un.S_addr;
}
void IpSetInt( in_addr& Addr, DWORD Ip )
{
	Addr.S_un.S_addr = Ip;
}
FString IpString( in_addr Addr, int Port )
{
	FString Result = FString::Printf( TEXT("%i.%i.%i.%i"), IP(Addr,1), IP(Addr,2), IP(Addr,3), IP(Addr,4) );
	if( Port )
		Result += FString::Printf( TEXT(":%i"), Port );
	return Result;
}
UBOOL SetNonBlocking( int Socket )
{
	DWORD NoBlock = 1;
	return ioctlsocket( Socket, FIONBIO, &NoBlock ) == 0;
}
UBOOL SetSocketReuseAddr( int Socket, UBOOL ReUse )
{
	int optval = ReUse?1:0;
	return setsockopt( Socket, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(int) );
}
UBOOL SetSocketLinger( int Socket )
{
	LINGER ling;
	ling.l_onoff  = 1;	// linger on
	ling.l_linger = 0;	// timeout in seconds
	return ( setsockopt( Socket, SOL_SOCKET, SO_LINGER, (LPSTR)&ling, sizeof(ling) ) == 0 );
}

////////////////////////////////////////////////////////////////////////////////
// Конструктор

QueryServer::QueryServer()
{
	m_UDPSoket			= INVALID_SOCKET;
	GWSAInitialized		= 1;
	StatBytesReceived	= 0;
	m_sResponse.Empty();
}

////////////////////////////////////////////////////////////////////////////////
// Деструктор

QueryServer::~QueryServer()
{
	Disconnect();
}

////////////////////////////////////////////////////////////////////////////////
// Disconnect

void QueryServer::Disconnect()
{
	// Отключение от сервера, если подключен.
	if( m_bConnected ) {
		// Сброс состояния подключенного.
		m_bConnected = FALSE;
	}

	// Освободить гнездо.
	if( m_UDPSoket != INVALID_SOCKET)
	{
		warnf(TEXT("Closing UDP socket, port: %d"), m_UDPPort);
		closesocket( m_UDPSoket );
		m_UDPSoket = INVALID_SOCKET;
	}
}

////////////////////////////////////////////////////////////////////////////////
// SetHostname

void QueryServer::SetHostname(const TCHAR* Hostname)
{
	m_Hostname = Hostname;
}

////////////////////////////////////////////////////////////////////////////////
// SendMsg

void QueryServer::SendMsg( const FString& Text )
{
	/*
	CWnd* pWnd = AfxGetMainWnd();
	if( pWnd )
	{
		// Get edit control to display response.
		CHistoryEdit* pEdt=(CHistoryEdit*)pWnd->GetDlgItem(IDC_EDIT1);
		if( pEdt==NULL )
			return;
	
		// Get number of lines originally.
		int nLineOrig = pEdt->GetLineCount();

		// Get original window text.
		//CString sText;
		//pEdt->GetWindowText( sText );
		FString Msg = FString::Printf( TEXT( "%s\n" ),Text );

		// Put append text to the edit control.
		//pEdt->AppendString( *Text );
		pEdt->AppendString( *Msg );
	}
	*/
}

////////////////////////////////////////////////////////////////////////////////
// GetAddr

ULONG QueryServer::GetAddr(const TCHAR* Hostname, struct in_addr* inaddr)
{
	u_long Result=INADDR_ANY;
	LPHOSTENT HostEnt=NULL;
	struct in_addr InAddr;
	if( *Hostname ) {
		InAddr.s_addr=inet_addr( TCHAR_TO_ANSI(Hostname) );
		if(( InAddr.s_addr==INADDR_NONE ) && ( lstrcmpi( Hostname,TEXT("255.255.255.255") ))) {
			HostEnt=gethostbyname( TCHAR_TO_ANSI(Hostname) );
			if( HostEnt ) {
				Result=*((u_long *)(HostEnt->h_addr));
				if( inaddr )
					inaddr->s_addr=*((u_long *)(HostEnt->h_addr));
			} else {
				Result=INADDR_ANY;
				if( inaddr )
					inaddr->s_addr=INADDR_ANY;
			}
		} else {
			Result=InAddr.s_addr;
			if( inaddr )
				inaddr->s_addr=InAddr.s_addr;
		}
	}
	return Result;
}

////////////////////////////////////////////////////////////////////////////////
// Start

BOOL QueryServer::Start( const TCHAR* Hostaddress, int Port, const TCHAR* Magicstring )
{
	BOOL Result = 0x0FFFFFFFF;
	//const FString& Msg = TEXT("Query Server: Start");
	//SendMsg( Msg );

	// Проверить, если строки пустые - ошибка.
	if( appStrlen( Hostaddress ) == 0 || Port == 0  || Port < 0 )
	{
		//const FString& Error = TEXT("-->FAILED: QueryServer: Start: appStrlen() Hostaddress");
		//SendMsg( Error );
		debugf( TEXT("-->FAILED: QueryServer: Start: appStrlen() Hostaddress") );
		return Result;
	}

	// Привязать гнездо.
	Result = BindPort();
	if( Result == -1 )
	{
		//const FString& Error = TEXT("-->FAILED: QueryServer: BindPort");
		//SendMsg( Error );
		Disconnect();
		return Result;
	}

	// Гнездо привязано, отметить.
	m_bConnected = TRUE;

	// Отправить запрос серверу.
	Result = SendTo( Hostaddress, Port, Magicstring );
	if( Result <= 0 )
	{
		//const FString& Error = TEXT("-->FAILED: QueryServer: SendTo");
		//SendMsg( Error );
		//debugf( TEXT("-->FAILED: QueryServer: SendTo") );
		Disconnect();
		return -1;
	}

	// Задержка.
	Sleep( QUERY_DELAY );

	// Получить ответ сервера.
	Result = RecvFrom();
	if( Result == -1 )
	{
		//const FString& Error = TEXT("-->FAILED: QueryServer: RecvFrom");
		//SendMsg( Error );
		Disconnect();
		return Result;
	}

	Disconnect();

	//const FString& Msg = TEXT("Query Server: Disconnect");
	//SendMsg( Msg );

	return 0;
}

////////////////////////////////////////////////////////////////////////////////
// BindPort
//
// Устанавливается на любой порт.
// Если требуемый номер порта не доступен, устанавливается
// на следующий, увеличивая значение на еденицу.
// По умолчанию, номер порта: 2000, "bUseNextAvailable = TRUE"
// в случае занятости порта, будет испольоваться: 2001 или
// 2002 и т.д.

BOOL QueryServer::BindPort( int InPort, BOOL bUseNextAvailable )
{
	// Выбрать любой, локальный интерфейс IP:
	in_addr BindAddr;
	IpSetInt( BindAddr, INADDR_ANY );

	if( GWSAInitialized )
	{
		if( m_UDPSoket==INVALID_SOCKET )
		{
			m_UDPSoket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
			if( m_UDPSoket != INVALID_SOCKET )
			{
				UBOOL TrueBuffer=1;
				if( setsockopt( m_UDPSoket, SOL_SOCKET, SO_BROADCAST, (char*)&TrueBuffer, sizeof(TrueBuffer) )==0 )
				{
					sockaddr_in Addr;
					Addr.sin_family      = AF_INET;
					Addr.sin_addr        = BindAddr;
					Addr.sin_port        = htons(InPort);

					int boundport = bindnextport( m_UDPSoket, &Addr, bUseNextAvailable ? 20 : 1, 1 );
					if( boundport )
					{
						DWORD NoBlock = 1;
						if( ioctlsocket( m_UDPSoket, FIONBIO, &NoBlock )==0 )
						{
							// Success.
							//*(int*)Result = boundport;
							m_UDPPort = ntohs( Addr.sin_port );
							
							// Узнать номер локального порта.
							//SOCKLEN size = sizeof(Addr);
							//getsockname ( m_UDPSoket, (sockaddr*)(&Addr), &size);
							//int port = ntohs( Addr.sin_port );
							
							warnf(TEXT("Opening UDP socket, port: %d"), m_UDPPort);
							return 0;
						}
						else
							debugf( TEXT("-->FAILED: BindPort: ioctlsocket") );
					}
					else
						debugf( TEXT("-->FAILED: BindPort: bind") );
				}
				else
					debugf( TEXT("-->FAILED: BindPort: setsockopt") );
			}
			else
				debugf( TEXT("-->FAILED: BindPort: socket") );
			Disconnect();
		}
		else
			debugf( TEXT("-->FAILED: BindPort: already bound") );
	}
	else
		debugf( TEXT("-->FAILED: BindPort: winsock") );

	return 0x0FFFFFFFF;
}

////////////////////////////////////////////////////////////////////////////////
// SendTo

int QueryServer::SendTo( const TCHAR* Hostaddress, int Port, const TCHAR* Magicstring )
{
	unsigned long ServerAddress = GetAddr( Hostaddress );
	if( !ServerAddress )
		return -1;
	
	struct sockaddr_in Addr;
	Addr.sin_family			= AF_INET;
	Addr.sin_port			= htons((u_short)Port);
	Addr.sin_addr.s_addr	= ServerAddress;

	fd_set fdset;
	FD_ZERO( &fdset );
	FD_SET( m_UDPSoket, &fdset );

	struct timeval tv;
	tv.tv_sec	= 10;
	tv.tv_usec	= 0;

	int SelectStatus = select( m_UDPSoket + 1, NULL, &fdset, NULL, &tv );
	if( SelectStatus==0 || SelectStatus==SOCKET_ERROR )
	{
		warnf( TEXT("-->FAILED: SendTo: checking socket status: %d"), SelectStatus );
		return -2;
	}
	
	// Создать строку запроса:
	FString Str = Magicstring;

	// Отправить:
	int SentBytes = sendto( m_UDPSoket, TCHAR_TO_ANSI(*Str), sizeof(ANSICHAR)*Str.Len(), MSG_NOSIGNAL, (sockaddr*)&Addr, sizeof(Addr) );
	if( SentBytes == SOCKET_ERROR )
	{
		TCHAR* error = SocketError(WSAGetLastError());
		warnf( TEXT("-->FAILED: SendTo: %s"), error );
		SentBytes = 0;
	}
	else
	{
		debugf( TEXT("QueryServer: Sent %i bytes"), SentBytes);
	}
	return SentBytes;
}

BOOL QueryServer::RecvFrom()
{
	if( !m_sResponse.IsEmpty() )
		m_sResponse.Empty();

	m_sResponse.Preallocate(MAXRECVDATASIZE);

	BYTE Buffer[MAXRECVDATASIZE];

	BOOL Result = 0;
	int Count = 0;
	int SelectStatus = 0;

	int WaitTime = 0;
	TIMEVAL SelectTime = {WaitTime, 0};

	fd_set SocketSet;
	FD_ZERO( &SocketSet );
	FD_SET( m_UDPSoket, &SocketSet );

	struct sockaddr_in FromAddr;
	int FromSize = sizeof(FromAddr);

	for(;;)
	{
		SelectStatus = select( m_UDPSoket + 1, &SocketSet, 0, 0, &SelectTime );
		if ( SelectStatus == SOCKET_ERROR )
		{
			warnf( TEXT("-->FAILED: RecvFrom: checking socket status: %d"), WSAGetLastError());
			Result = -1;
			break;
		}
		else
		if ( SelectStatus == 0 )
		{
			if( WSAGetLastError() == SOCKET_ERROR )
			{
				warnf( TEXT("-->FAILED: RecvFrom: checking socket status: %d"), WSAGetLastError() );
				Result = -2;
			}
			break;
		}

		Count = recvfrom( m_UDPSoket, (char*)Buffer, ARRAY_COUNT(Buffer)-1, MSG_NOSIGNAL, (sockaddr*)&FromAddr, &FromSize );
		if( Count == SOCKET_ERROR )
		{
			if( WSAGetLastError() == WSAEWOULDBLOCK )
			{
				// Принимающая сторона не успевает читать данные.
				warnf( TEXT("-->FAILED: RecvFrom: operation could not be: %d"), WSAGetLastError() );
				Result = -3;
				break;
			}
			else
			if( WSAGetLastError() != WSAECONNRESET )
			{
				// ICMP недоступен, должен продолжать вызывать recv().
				warnf( TEXT("-->FAILED: RecvFrom: ICMP unreachable: %d"), WSAGetLastError() );
				Result = -4;
				break;
			}
		}
		else
		if( Count > 0 )
		{
			StatBytesReceived	+= Count;
			Buffer[Count]		= 0;

			//
			// Сохраняю данные.
			//

			// Данные добавляются.
			m_sResponse += *FString((ANSICHAR*)Buffer);

		}
		else
			break;
	}
	if( StatBytesReceived > 0 )
		debugf( TEXT("QueryServer: Received %i bytes"), StatBytesReceived);

	return Result;
}

////////////////////////////////////////////////////////////////////////////////
// <<eof>> QueryServer.cpp
////////////////////////////////////////////////////////////////////////////////

User avatar
UnrealGGecko
Godlike
Posts: 2900
Joined: Wed Feb 01, 2012 11:26 am
Personal rank: GEx the Gecko
Location: Kaunas, Lithuania
Contact:

Re: UT99 Server Query

Post by UnrealGGecko »

I've merged the posts (we have a "no-double posts within 24 hours" rule here), now you owe me a cookie :mrgreen:

Will try this new tool out soon, :gj:
User avatar
Shvonder
Novice
Posts: 9
Joined: Sat Apr 11, 2015 9:47 pm

Re: UT99 Server Query

Post by Shvonder »

I have already tearing the roof, I probably donkey.
... i love this music
User avatar
Shvonder
Novice
Posts: 9
Joined: Sat Apr 11, 2015 9:47 pm

Re: UT99 Server Query

Post by Shvonder »

Ello ( :-) )
Everything - the end I decided to do a full-featured browser.
Just the problem is that the name for it does not come up with...
Probably so, and leave "UTQuery v1.1", or think.., called "UT99Browser".
anons:
Attachments
preview_UT99Query_v2.JPG
User avatar
Shvonder
Novice
Posts: 9
Joined: Sat Apr 11, 2015 9:47 pm

Re: UT99 Server Query

Post by Shvonder »

Hi. I'm still alive. I met a nice music:
User avatar
sektor2111
Godlike
Posts: 6403
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: UT99 Server Query

Post by sektor2111 »

If helps for UT'99 Server Query I also have found this one:
User avatar
Shvonder
Novice
Posts: 9
Joined: Sat Apr 11, 2015 9:47 pm

Re: UT99 Server Query

Post by Shvonder »

sektor2111 wrote:If helps for UT'99 Server Query I also have found this one:
Thank you thank you!
At the time I served in the army (1990-92), I came on vacation and heard "Technotronic" ...
Thank you, this composition, I remember youth (of course I did too old, but still) I am very pleased!
---
A full server - not a question to make just such a program will clog your adapter ...
So it's pointless. Therefore, I lost interest. Anyway, if someone has to - send source.
---
:-)
--
Tom Keifer & Lzzy Hale - Nobody's Fool Nashville Apr 15 2015:
User avatar
Shvonder
Novice
Posts: 9
Joined: Sat Apr 11, 2015 9:47 pm

Re: UT99 Server Query

Post by Shvonder »

I decided to put the source code here on this site.
I would be glad if someone come in handy.
Collect program, you can in the presence of a development environment:
Microsoft Visual C ++ 2005 (+) SP2 (SP.050727-7600)
Enjoy your Shvonder always - for you!

Я решил выложить исходный код здесь, на этом участке.
Буду рад, если кому-то пригодиться.
Собрать программу, вы сможете при наличии среды разработки:
Microsoft Visual C++ 2005 ( + ) SP2 (SP.050727-7600)
Наслаждайтесь, всегда ваш Швондер!

18:40 11.06.2015
Attachments
UT99Query.zip
(5.66 MiB) Downloaded 138 times
User avatar
Shvonder
Novice
Posts: 9
Joined: Sat Apr 11, 2015 9:47 pm

Re: UT99 Server Query

Post by Shvonder »

to me there are some customers printed (private) message ...
i understand joke... - I have never offended, because I'm an elite person ...
: - )
User avatar
Shvonder
Novice
Posts: 9
Joined: Sat Apr 11, 2015 9:47 pm

Re: UT99 Server Query

Post by Shvonder »

I am sorry.
I do nihochu nothing wanted to emphasize its importance.
I apologize if I offended anyone ...
(I'm not out of malice ... I just thought I was drunk ...
- I guess I understood that all my work - should go to the benefit of new people, and I not only I predschemtvuyushee our generation - must pass the experience - children.
I do not think that I may say (OUR) - TIM - was offended by the fact that I am somewhat curtailed its program to examine its superior quality.
=== All this is the last - I hope no one evil for me or keeps -.


Нет никакого Человека, который именно придерживался бы пафосного мнения.
- Во всяком случае, для меня да: люди которые ни такие тупые как я
- Швондер ( или прочее - больше не сушествует, как никогда и не было...
- Хочу, чтобы стерли мою невнятную тему, скорее всего - я разозлился по-пьяни
- Всё ну-его на фиг ничего не хочу - Тема закрыта.
- Душад, если прочитаешь - встретиться сей монускрипт - объясни в натуре, чтобы
- комрады - зла ни держали ( если сможешь - Прошу, Пожалуйста! ).
-
Bye ...


<< eof - Shvonder
User avatar
Dr.Flay
Godlike
Posts: 3347
Joined: Thu Aug 04, 2011 9:26 pm
Personal rank: Chaos Evangelist
Location: Kernow, UK
Contact:

Re: UT99 Server Query

Post by Dr.Flay »

Is there a problem with this tool ?
Perhaps it may be best to post when you are sober.
User avatar
Darkelarious
Skilled
Posts: 175
Joined: Sat Feb 08, 2014 12:02 pm
Personal rank: 333networks admin
Location: Phobos Moon
Contact:

Re: UT99 Server Query

Post by Darkelarious »

At the risk of digging up old posts, what I get so far from the (source) code and the program itself is that Shvonder attempted to write a server browser list/client in MS Visual C++ and decided to share the code here. He can browse and query servers, but all servers need to be entered manually.

If Shvonder is still around, we could work towards a 333networks API so he (and any other programmer) can access the masterserver list directly.
--Darkelarious
Image
Masterserver | Discord Channel
Oh, and we still are ready to receive donations. The url works, right? It doesn't seem to be doing anything...
3anon
Novice
Posts: 8
Joined: Sat May 11, 2019 11:25 pm

Re: UT99 Server Query

Post by 3anon »

Hey. I redid the program a bit, it loads the server list from a file, maximum seven servers.
An example server list is attached. In order to get the port number in the package there is a utility GetServerList.
Well, you can immediately start the game on the current server "Run UT Here."

p.s. If you used the previous version, then you may have to reset the settings with the command -reset

Format list-servers:

Code: Select all

//
// Semicolon ";", "//" is a comment.
// Maximum Seven servers!
//

; --------------------------------------------------------------------------------------[ 01
RomainianNet TDM New Server
; https://www.gametracker.com/server_info/108.61.253.20:7777/
108.61.253.20:7778

; --------------------------------------------------------------------------------------[ 02
New Noobies{NoRules}
; https://www.gametracker.com/server_info/18.222.158.59:7777/
18.222.158.59:7778

; --------------------------------------------------------------------------------------[ 03
Fast Download SMoKiNG 4 Everyone >GRAPPLE<
; https://www.gametracker.com/server_info/31.220.4.155:2250/
31.220.4.155:2251

; --------------------------------------------------------------------------------------[ 04
EL DORADO
; https://www.gametracker.com/server_info/31.186.251.181:3529/
31.186.251.181:3711

; --------------------------------------------------------------------------------------[ 05
-=CoN=-Freestyle Sniper
; https://www.gametracker.com/server_info/8.26.21.89:7777/
8.26.21.89:9002

; --------------------------------------------------------------------------------------[ 06
[UT] FUNNEL-ACTION unrealteam.de
; https://www.gametracker.com/server_info/85.14.221.179:8888/
85.14.221.179:8889

; --------------------------------------------------------------------------------------[ 07 --- Maximum Seven !
zp| [=======] [PURE] [INSTAGIB] [UK] [=======]
; https://www.gametracker.com/server_info/185.107.96.18:7777/
185.107.96.18:7778
That's probably all :-)
Attachments
1.jpg
UT99Query.zip
(286.78 KiB) Downloaded 35 times
User avatar
Dr.Flay
Godlike
Posts: 3347
Joined: Thu Aug 04, 2011 9:26 pm
Personal rank: Chaos Evangelist
Location: Kernow, UK
Contact:

Re: UT99 Server Query

Post by Dr.Flay »

333networks now has a JSON API, so feel free to make a wrapper for a query tool
http://333networks.com/json
Post Reply