Skip to content

Instantly share code, notes, and snippets.

@Bakterio
Created June 10, 2022 21:55
Show Gist options
  • Select an option

  • Save Bakterio/57c83f6cc205ae43c33ff6b3ae10dbea to your computer and use it in GitHub Desktop.

Select an option

Save Bakterio/57c83f6cc205ae43c33ff6b3ae10dbea to your computer and use it in GitHub Desktop.
Class to comunicate witch sa-mp server and get some useful informations.
using System.Net;
using System.Net.Sockets;
class SampQuery
{
Socket qSocket;
IPAddress address;
int _port = 0;
string[] results;
int _count = 0;
DateTime[] timestamp = new DateTime[2];
public SampQuery(string IP, int port)
{
qSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
qSocket.SendTimeout = 5000;
qSocket.ReceiveTimeout = 5000;
try
{
address = Dns.GetHostAddresses(IP)[0];
}
catch
{
}
_port = port;
}
private bool Send(char opcode)
{
try
{
EndPoint endpoint = new IPEndPoint(address, _port);
using (MemoryStream stream = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write("SAMP".ToCharArray());
string[] SplitIP = address.ToString().Split('.');
writer.Write(Convert.ToByte(Convert.ToInt32(SplitIP[0])));
writer.Write(Convert.ToByte(Convert.ToInt32(SplitIP[1])));
writer.Write(Convert.ToByte(Convert.ToInt32(SplitIP[2])));
writer.Write(Convert.ToByte(Convert.ToInt32(SplitIP[3])));
writer.Write((ushort)_port);
writer.Write(opcode);
if (opcode == 'p')
writer.Write("8493".ToCharArray());
timestamp[0] = DateTime.Now;
}
if (qSocket.SendTo(stream.ToArray(), endpoint) > 0)
return true;
}
}
catch
{
return false;
}
return false;
}
private int Receive()
{
try
{
_count = 0;
EndPoint endpoint = new IPEndPoint(address, _port);
byte[] rBuffer = new byte[3402];
qSocket.ReceiveFrom(rBuffer, ref endpoint);
timestamp[1] = DateTime.Now;
using (MemoryStream stream = new MemoryStream(rBuffer))
{
using (BinaryReader reader = new BinaryReader(stream))
{
if (stream.Length <= 10)
return _count;
reader.ReadBytes(10);
switch (reader.ReadChar())
{
case 'i': // Information
{
results = new string[6];
results[_count++] = Convert.ToString(reader.ReadByte());
results[_count++] = Convert.ToString(reader.ReadInt16());
results[_count++] = Convert.ToString(reader.ReadInt16());
int hostnamelen = reader.ReadInt32();
results[_count++] = new string(reader.ReadChars(hostnamelen));
int gamemodelen = reader.ReadInt32();
results[_count++] = new string(reader.ReadChars(gamemodelen));
int languagelen = reader.ReadInt32();
results[_count++] = new string(reader.ReadChars(languagelen));
return _count;
}
case 'r': // Rules
{
int rulecount = reader.ReadInt16();
results = new string[rulecount * 2];
for (int i = 0; i < rulecount; i++)
{
int rulelen = reader.ReadByte();
results[_count++] = new string(reader.ReadChars(rulelen));
int valuelen = reader.ReadByte();
results[_count++] = new string(reader.ReadChars(valuelen));
}
return _count;
}
case 'c': // Client list
{
int playercount = reader.ReadInt16();
results = new string[playercount * 2];
for (int i = 0; i < playercount; i++)
{
int namelen = reader.ReadByte();
results[_count++] = new string(reader.ReadChars(namelen));
results[_count++] = Convert.ToString(reader.ReadInt32());
}
return _count;
}
case 'd': // Detailed player information
{
int playercount = reader.ReadInt16();
results = new string[playercount * 4];
for (int i = 0; i < playercount; i++)
{
results[_count++] = Convert.ToString(reader.ReadByte());
int namelen = reader.ReadByte();
results[_count++] = new string(reader.ReadChars(namelen));
results[_count++] = Convert.ToString(reader.ReadInt32());
results[_count++] = Convert.ToString(reader.ReadInt32());
}
return _count;
}
case 'p': // Ping
{
results = new string[1];
results[_count++] = timestamp[1].Subtract(timestamp[0]).Milliseconds.ToString();
return _count;
}
default:
return _count;
}
}
}
}
catch
{
return _count;
}
}
private string[] Store(int count)
{
string[] rString = new string[count];
for (int i = 0; i < count && i < _count; i++)
rString[i] = results[i];
_count = 0;
return rString;
}
private string[] Connect(char i)
{
Send(i);
return Store(Receive());
}
public Dictionary<string, int> Players()
{
var output = new Dictionary<string, int>();
string[] info = Connect('c');
for (int i = 0; i < info.Length-1; i+=2)
{
output.Add(info[i], Int32.Parse(info[i+1]));
}
return output;
}
/**
* <summary>
* Return server info in Dictionary.
* Dictionary keys: password, players, max_players, title, gamemode, language
* <example>
* <code>
* Query q = new Query("ip.example.cz", 7777);
* var info = q.ServerInfo();
* var title = info["title"]
* </code>
* </example>
* </summary>
* <returns>data ;)</returns>
*/
public Dictionary<string, string> ServerInfo()
{
var output = new Dictionary<string, string>();
string[] info = Connect('i');
string[] names = {"password", "players", "max_players", "title", "gamemode", "language"};
for (int i = 0; i < info.Length; i++)
{
output[names[i]] = info[i];
}
return output;
}
/**
* Dictionary keys: lagcomp, mapname, version, weather, weburl, worldtime
*/
public Dictionary<string, string> Rules()
{
var output = new Dictionary<string, string>();
string[] info = Connect('r');
for (int i = 0; i < info.Length-1; i+=2)
{
output.Add(info[i], info[i + 1]);
}
return output;
}
public int Ping()
{
return Convert.ToInt32(Connect('p')[0]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment