UT99 Server Query
-
- Novice
- Posts: 9
- Joined: Sat Apr 11, 2015 9:47 pm
UT99 Server Query
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.
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.
You do not have the required permissions to view the files attached to this post.
-
- Novice
- Posts: 9
- Joined: Sat Apr 11, 2015 9:47 pm
Re: UT99 Server Query
If you're interested, here's the part that informs. (C ++ code)
--Edit by UnrealGecko--
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
/////////////////////////////////////////////////////////////////////////////
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
////////////////////////////////////////////////////////////////////////////////
-
- Godlike
- Posts: 2962
- Joined: Wed Feb 01, 2012 11:26 am
- Personal rank: GEx the Gecko
- Location: Kaunas, Lithuania
Re: UT99 Server Query
I've merged the posts (we have a "no-double posts within 24 hours" rule here), now you owe me a cookie
Will try this new tool out soon,
Will try this new tool out soon,
My work for UT99: (NEW!) Mute, Counter-Strike VP, MaleOne+, FemaleOne+ and the FemaleTwo220 voicepacks DM-XC-NaliTreeV2 (from the 2012 Xmas Contest mappack), DM/DOM-20AC-CastleGeorgeV3 (from the 20th Anniversary Contest mappack), DM-UFFO, DM-WreckingBall, CTFM-Sundial
my small spec of files at Google Drive
List of console converted maps, models & more!
-
- Novice
- Posts: 9
- Joined: Sat Apr 11, 2015 9:47 pm
-
- Novice
- Posts: 9
- Joined: Sat Apr 11, 2015 9:47 pm
Re: UT99 Server Query
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:
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:
You do not have the required permissions to view the files attached to this post.
-
- Novice
- Posts: 9
- Joined: Sat Apr 11, 2015 9:47 pm
-
- Godlike
- Posts: 6435
- Joined: Sun May 09, 2010 6:15 pm
- Location: On the roof.
-
- Novice
- Posts: 9
- Joined: Sat Apr 11, 2015 9:47 pm
Re: UT99 Server Query
Thank you thank you!sektor2111 wrote:If helps for UT'99 Server Query I also have found this one:
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:
-
- Novice
- Posts: 9
- Joined: Sat Apr 11, 2015 9:47 pm
Re: UT99 Server Query
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
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
You do not have the required permissions to view the files attached to this post.
-
- Novice
- Posts: 9
- Joined: Sat Apr 11, 2015 9:47 pm
Re: UT99 Server Query
to me there are some customers printed (private) message ...
i understand joke... - I have never offended, because I'm an elite person ...
: - )
i understand joke... - I have never offended, because I'm an elite person ...
: - )
-
- Novice
- Posts: 9
- Joined: Sat Apr 11, 2015 9:47 pm
Re: UT99 Server Query
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
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
-
- Godlike
- Posts: 3350
- Joined: Thu Aug 04, 2011 9:26 pm
- Personal rank: Chaos Evangelist
- Location: Kernow, UK
Re: UT99 Server Query
Is there a problem with this tool ?
Perhaps it may be best to post when you are sober.
Perhaps it may be best to post when you are sober.
UT99.org House Rules
ChaosUT https://chaoticdreams.org
Your Unreal resources: https://yourunreal.wordpress.com
The UT99/UnReal Directory: https://forumdirectory.freeforums.org
Find me on Steam and GoG
ChaosUT https://chaoticdreams.org
Your Unreal resources: https://yourunreal.wordpress.com
The UT99/UnReal Directory: https://forumdirectory.freeforums.org
Find me on Steam and GoG
-
- Skilled
- Posts: 177
- Joined: Sat Feb 08, 2014 12:02 pm
- Personal rank: 333networks admin
- Location: Phobos Moon
Re: UT99 Server Query
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.
If Shvonder is still around, we could work towards a 333networks API so he (and any other programmer) can access the masterserver list directly.
-
- Novice
- Posts: 8
- Joined: Sat May 11, 2019 11:25 pm
Re: UT99 Server Query
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:
That's probably all
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
You do not have the required permissions to view the files attached to this post.
-
- Godlike
- Posts: 3350
- Joined: Thu Aug 04, 2011 9:26 pm
- Personal rank: Chaos Evangelist
- Location: Kernow, UK
Re: UT99 Server Query
333networks now has a JSON API, so feel free to make a wrapper for a query tool
http://333networks.com/json
http://333networks.com/json
UT99.org House Rules
ChaosUT https://chaoticdreams.org
Your Unreal resources: https://yourunreal.wordpress.com
The UT99/UnReal Directory: https://forumdirectory.freeforums.org
Find me on Steam and GoG
ChaosUT https://chaoticdreams.org
Your Unreal resources: https://yourunreal.wordpress.com
The UT99/UnReal Directory: https://forumdirectory.freeforums.org
Find me on Steam and GoG