Her er lidt til CS. Det dur til både 1.6 og Source.
Det er lavet for en lille evighed siden , så jeg har ikke ret meget forklaring, men du kan da kigge på det :)
Jeg bruger det på
www.clan35.dk, hvor du kan se det.
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Collections;
namespace clan35
{
public class c35Reader : BinaryReader
{
public c35Reader( Stream s ) : base ( s)
{
}
public string ReadZString()
{
string s = "";
char c = ReadChar();
while (c != (char)0)
{
s += c;
c = ReadChar();
}
return s;
}
}
public struct Player : IComparable
{
public byte playerNum;
public string name;
public int kills;
public TimeSpan time;
public int CompareTo(object p)
{
if (((Player)p).kills == kills)
return 0;
else
if (((Player)p).kills > kills)
return -1;
else
return 1;
}
}
public class Players : System.Collections.CollectionBase
{
public void Add(Player p)
{
if (List.Count == 0)
{
List.Add(p);
return;
}
if (p.kills > ((Player)List[0]).kills)
{
List.Insert(0, p);
return;
}
if (p.kills < ((Player)List[List.Count-1]).kills)
{
List.Add(p);
return;
}
int i = 0;
while (p.kills < ((Player)List[i]).kills)
i++;
List.Insert(i,p);
}
public Player this[int index]
{
get
{
return (Player)List[index];
}
set
{
List[index] = value;
}
}
}
public class PlayersEnumerator: IEnumerator
{
private int position = -1;
private Players p;
public PlayersEnumerator(Players p)
{
this.p = p;
}
public bool MoveNext()
{
if (position < p.Count - 1)
{
position++;
return true;
}
else
{
return false;
}
}
public void Reset()
{
position = -1;
}
public Player Current // non-IEnumerator version: type-safe
{
get
{
return p[position];
}
}
object IEnumerator.Current // IEnumerator version: returns object
{
get
{
return p[position];
}
}
}
class TimerWorker
{
private int MS;
public TimerWorker(int aMS)
{
MS = aMS;
}
public void Wait()
{
System.Threading.Thread.Sleep(MS);
}
}
class ServerInfoWorker
{
public string serverIP;
public int port;
public Players players = null;
public Hashtable rules = null;
public bool sourceEngine = false;
public string errorText;
public string serverName = "";
public string mapName = "";
public string gameDir = "";
public string gameName = "";
public byte noOfPlayers = 0;
public byte maxNoOfPlayers = 0;
public short gameAppId = 0;
public byte noOfBots = 0;
public byte protocolVersion = 0;
public char serverType = ' ';
public char operatingSystem = ' ';
public bool passwordProtected = false;
public bool runningAMod = false;
public string modInfoWebsite = "";
public string gameVersion = "";
public bool secureVAC = false;
public string modFTPDownloadSite = "";
public string modHLServerVersion = "";
public Int16 modVersion = 0;
public Int16 modDownloadSize = 0;
public bool serverSideOnlyMOD = false;
public bool clientSideDLLRequired = false;
public ServerInfoWorker(string aServerIP, int aPort)
{
serverIP = aServerIP;
port = aPort;
}
public void WaitFor (int delayMS)
{
System.Threading.Thread.Sleep(delayMS);
}
private Byte[] CommandHeader(string aCommand)
{
Byte[] res = new Byte[aCommand.Length + 5];
for (int i = 0; i < 4; i++)
res[i] = 255;
for (int i = 4; i < aCommand.Length + 5; i++)
res[i] = 0;
Encoding.ASCII.GetBytes(aCommand).CopyTo(res, 4);
return res;
}
private Byte[] CommandHeader(string aCommand, int aChallengeCode)
{
Byte[] res = new Byte[aCommand.Length + 9];
for (int i = 0; i < 4; i++)
res[i] = 255;
for (int i = 4; i < aCommand.Length + 5; i++)
res[i] = 0;
Encoding.ASCII.GetBytes(aCommand).CopyTo(res, 4);
byte [] challengCode = BitConverter.GetBytes(aChallengeCode);
challengCode.CopyTo(res, 4 + aCommand.Length);
return res;
}
private string ReadString(ref string aSource)
{
string[] s = aSource.Split(((char)0).ToString().ToCharArray());
string res = "";
try
{
aSource = s[1];
}
catch
{
aSource = "";
}
try
{
res = s[0];
}
catch
{
}
return res;
}
private byte ReadByte(ref string aSource)
{
byte res = 0;
try
{
res = (byte)aSource[0];
aSource = aSource.Substring(1);
}
catch
{
}
return res;
}
private bool ReadBool(ref string aSource)
{
byte res = 0;
try
{
res = (byte)aSource[0];
aSource = aSource.Substring(1);
}
catch
{
}
return res != 0;
}
private Int32 ReadInt32(ref string aSource)
{
Int32 res = 0;
try
{
res = (Int32)((byte)aSource[3]);
res = res << 8;
res += (byte)aSource[2];
res = res << 8;
res += (byte)aSource[1];
res = res << 8;
res += (byte)aSource[0];
aSource = aSource.Substring(4);
}
catch
{
}
return res;
}
private Int16 ReadInt16(ref string aSource)
{
Int16 res = 0;
try
{
res = (Int16)((byte)aSource[1]);
res = (Int16)(res << 8);
res += (byte)aSource[0];
aSource = aSource.Substring(2);
}
catch
{
}
return res;
}
private char ReadChar(ref string aSource)
{
char res = ' ';
try
{
res = aSource[0];
aSource = aSource.Substring(1);
}
catch
{
}
return res;
}
public void GetServerInfo()
{
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
s.Bind(new IPEndPoint(IPAddress.Any, 0));
s.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReceiveTimeout, 2000);
try
{
EndPoint serverEndPoint;
Byte[] receiveBytes;
int len;
MemoryStream ms;
c35Reader br;
s.SendTo(CommandHeader("TSource Engine Query"), new IPEndPoint(IPAddress.Parse(serverIP), port));
serverEndPoint = new IPEndPoint(0,0);
receiveBytes = new Byte[16000];
len = s.ReceiveFrom(receiveBytes, ref serverEndPoint);
ms = new MemoryStream(len);
br = new c35Reader(ms);
ms.Write ( receiveBytes,0,len );
ms.Seek(0,0);
br.ReadInt32();
char srvType = br.ReadChar();
if (srvType == 'I')
{
sourceEngine = true;
br.ReadByte(); // network version
serverName = br.ReadZString(); // server name
mapName = br.ReadZString(); // map name
gameDir = br.ReadZString(); // game dir
gameName = br.ReadZString(); // game name
gameAppId = br.ReadInt16(); // launcher application ID
noOfPlayers = br.ReadByte(); // # of players
maxNoOfPlayers = br.ReadByte(); // max # of players
noOfBots = br.ReadByte(); // bots
serverType = br.ReadChar(); // dedicated
operatingSystem = br.ReadChar(); // OS
passwordProtected = br.ReadBoolean(); // passwordprotected
secureVAC = br.ReadBoolean(); // secure
gameVersion = br.ReadZString(); // game version
}
else
{
sourceEngine = false;
br.ReadZString(); // Server IP:port
serverName = br.ReadZString(); // server name
mapName = br.ReadZString(); // map name
gameDir = br.ReadZString(); // game dir
gameName = br.ReadZString(); // game name
noOfPlayers = br.ReadByte(); // # of players
maxNoOfPlayers = br.ReadByte(); // max # of players
protocolVersion = br.ReadByte(); // protocol version
serverType = br.ReadChar(); // server type
operatingSystem = br.ReadChar(); // OS
passwordProtected = br.ReadBoolean(); // passwordprotected
runningAMod = br.ReadBoolean(); // running a mod
if (runningAMod)
{
modInfoWebsite = br.ReadZString(); // MODInfoWebsite
modFTPDownloadSite = br.ReadZString(); // MODFTPDownloadSite
modHLServerVersion = br.ReadZString(); // MODHLServerVersion
modVersion = br.ReadInt16(); // MODVersion
modDownloadSize = br.ReadInt16(); // MOD download size
serverSideOnlyMOD = br.ReadBoolean(); // ServerSideOnlyMOD
clientSideDLLRequired = br.ReadBoolean(); // ClientSideDLLRequired
}
}
s.SendTo(CommandHeader("U", -1), new IPEndPoint(IPAddress.Parse(serverIP), port));
serverEndPoint = new IPEndPoint(0,0);
receiveBytes = new Byte[16000];
len = s.ReceiveFrom(receiveBytes, ref serverEndPoint);
ms = new MemoryStream(len);
br = new c35Reader(ms);
ms.Write ( receiveBytes,0,len );
ms.Seek(0,0);
br.ReadInt32();
br.ReadByte();
int ChallengeCode = -1;
if (len > 6)
{
ChallengeCode = br.ReadInt32();
s.SendTo(CommandHeader("U", ChallengeCode), new IPEndPoint(IPAddress.Parse(serverIP), port));
}
else
{
s.SendTo(CommandHeader("U"), new IPEndPoint(IPAddress.Parse(serverIP), port));
}
serverEndPoint = new IPEndPoint(0,0);
receiveBytes = new Byte[16000];
len = s.ReceiveFrom(receiveBytes, ref serverEndPoint);
ms = new MemoryStream(len);
br = new c35Reader(ms);
ms.Write ( receiveBytes,0,len );
ms.Seek(0,0);
br.ReadInt32();
br.ReadByte();
byte b = br.ReadByte();
players = new Players();
for (int i = 0; i < b; i++)
{
try
{
Player p = new Player();
p.playerNum = br.ReadByte();
p.name = br.ReadZString();
p.kills = br.ReadInt32();
Single f = br.ReadSingle();
int H, M, S;
H = (int)f;
M = H % 3600;
H = H / 3600;
S = M % 60;
M = M / 60;
p.time = new TimeSpan(H, M, S);
players.Add(p);
}
catch {}
}
if (ChallengeCode > 0)
{
s.SendTo(CommandHeader("V", ChallengeCode), new IPEndPoint(IPAddress.Parse(serverIP), port));
}
else
{
s.SendTo(CommandHeader("V"), new IPEndPoint(IPAddress.Parse(serverIP), port));
}
serverEndPoint = new IPEndPoint(0,0);
receiveBytes = new Byte[16000];
len = s.ReceiveFrom(receiveBytes, ref serverEndPoint);
// char [] cb = new char[len];
// for (int ii = 0 ; ii < len; ii++)
// cb[ii] = (char)receiveBytes[ii];
ms = new MemoryStream(len);
ms.Write ( receiveBytes,0,len );
if (sourceEngine)
ms.Seek(7,0);
else
ms.Seek(16,0);
br = new c35Reader(ms);
rules = new Hashtable();
while (ms.Position < ms.Length-1)
{
string s1 = br.ReadZString();
string s2 = br.ReadZString();
rules.Add(s1, s2);
}
}
catch (Exception ex )
{
errorText = ex.ToString();
errorText += " ";
}
finally
{
try
{
s.Shutdown(SocketShutdown.Both);
}
catch{}
try
{
s.Close();
}
catch{}
}
}
}
public class ServerInfo
{
public string serverIP;
public int port;
public Players players = null;
public Hashtable rules = null;
public string errorText;
public string serverName = "";
public string mapName = "";
public string gameDir = "";
public string gameName = "";
public byte noOfPlayers = 0;
public byte maxNoOfPlayers = 0;
public byte protocolVersion = 0;
public char serverType = ' ';
public char operatingSystem = ' ';
public bool passwordProtected = false;
public bool runningAMod = false;
public string modInfoWebsite = "";
public string modFTPDownloadSite = "";
public string modHLServerVersion = "";
public Int16 modVersion = 0;
public Int16 modDownloadSize = 0;
public bool serverSideOnlyMOD = false;
public bool clientSideDLLRequired = false;
TimerWorker tw;
ServerInfoWorker siw;
AutoResetEvent asyncOpsAreDone;
public string GetServerInfo(string aServerName, int aPort)
{
asyncOpsAreDone = new AutoResetEvent(false);
tw = new TimerWorker(2100);
siw = new ServerInfoWorker(aServerName, aPort);
Thread InfoThread = new Thread(new ThreadStart(ExecuteInfo));
InfoThread.Start();
Thread TimerThread = new Thread(new ThreadStart(ExecuteTimer));
TimerThread.Start();
// ThreadPool.QueueUserWorkItem(new WaitCallback(ExecuteInfo));
// ThreadPool.QueueUserWorkItem(new WaitCallback(ExecuteTimer));
asyncOpsAreDone.WaitOne();
players = siw.players;
rules = siw.rules;
errorText = siw.errorText;
serverName = siw.serverName;
mapName = siw.mapName;
gameDir = siw.gameDir;
gameName = siw.gameName;
noOfPlayers = siw.noOfPlayers;
maxNoOfPlayers = siw.maxNoOfPlayers;
protocolVersion = siw.protocolVersion;
serverType = siw.serverType;
operatingSystem = siw.operatingSystem;
passwordProtected = siw.passwordProtected;
runningAMod = siw.runningAMod;
modInfoWebsite = siw.modInfoWebsite;
modFTPDownloadSite = siw.modFTPDownloadSite;
modHLServerVersion = siw.modHLServerVersion;
modVersion = siw.modVersion;
modDownloadSize = siw.modDownloadSize;
serverSideOnlyMOD = siw.serverSideOnlyMOD;
clientSideDLLRequired = siw.clientSideDLLRequired;
string rs = "Server name : " + siw.serverName + "\r\n"+
"Map name : " + siw.mapName + "\r\n"+
"# of players : " + siw.noOfPlayers.ToString() + " / " +
siw.maxNoOfPlayers.ToString() + "\r\n"+
"Password protected : " + siw.passwordProtected.ToString() + "\r\n"+ "\r\n";
if (players != null)
{
foreach (Player p in players)
rs += p.name + " - " + p.kills.ToString() + " - " + p.time.ToString() + "\r\n";
rs += "\r\n";
}
if (rules != null)
{
foreach (String ks in rules.Keys)
{
rs += ks + " : " + rules[ks].ToString() + "\r\n";
}
}
asyncOpsAreDone.Close();
return rs;
}
void ExecuteInfo()
{
siw.GetServerInfo();
if (asyncOpsAreDone.Handle.ToInt32() != -1)
asyncOpsAreDone.Set();
}
void ExecuteTimer()
{
tw.Wait();
if (asyncOpsAreDone.Handle.ToInt32() != -1)
asyncOpsAreDone.Set();
}
}
}