Created
June 10, 2022 21:55
-
-
Save Bakterio/57c83f6cc205ae43c33ff6b3ae10dbea to your computer and use it in GitHub Desktop.
Class to comunicate witch sa-mp server and get some useful informations.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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