Skip to content

Commit

Permalink
Support ASE Protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
BattlefieldDuck committed Jan 16, 2024
1 parent 29f419a commit bd8cc03
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 0 deletions.
123 changes: 123 additions & 0 deletions OpenGSQ/Protocols/ASE.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;

namespace OpenGSQ.Protocols
{
/// <summary>
/// All-Seeing Eye Protocol
/// </summary>
public class ASE : ProtocolBase
{
/// <inheritdoc/>
public override string FullName => "All-Seeing Eye Protocol";

private readonly byte[] _request = Encoding.ASCII.GetBytes("s");
private readonly byte[] _response = Encoding.ASCII.GetBytes("EYE1");

/// <summary>
/// Initializes a new instance of the <see cref="ASE"/> class.
/// </summary>
/// <param name="host">The host to connect to.</param>
/// <param name="port">The port to connect to.</param>
/// <param name="timeout">The timeout for the connection.</param>
public ASE(string host, int port, int timeout = 5000) : base(host, port, timeout)
{
}

/// <summary>
/// Gets the status of the server.
/// </summary>
/// <returns>A dictionary containing the server status.</returns>
public Dictionary<string, object> GetStatus()
{
using var udpClient = new UdpClient();
byte[] response = udpClient.Communicate(this, _request);
byte[] header = response[..4];

if (!header.SequenceEqual(_response))
{
throw new InvalidPacketException($"Packet header mismatch. Received: {BitConverter.ToString(header)}. Expected: {BitConverter.ToString(_response)}.");
}

using var br = new BinaryReader(new MemoryStream(response[4..]), Encoding.UTF8);

var result = new Dictionary<string, object>
{
["gamename"] = ReadString(br),
["gameport"] = ReadString(br),
["hostname"] = ReadString(br),
["gametype"] = ReadString(br),
["map"] = ReadString(br),
["version"] = ReadString(br),
["password"] = ReadString(br),
["numplayers"] = ReadString(br),
["maxplayers"] = ReadString(br),
["rules"] = ParseRules(br),
["players"] = ParsePlayers(br)
};

return result;
}

private Dictionary<string, string> ParseRules(BinaryReader br)
{
var rules = new Dictionary<string, string>();

while (!br.IsEnd())
{
string key = ReadString(br);

if (string.IsNullOrEmpty(key))
{
break;
}

rules[key] = ReadString(br);
}

return rules;
}

private List<Dictionary<string, string>> ParsePlayers(BinaryReader br)
{
var players = new List<Dictionary<string, string>>();
var keys = new Dictionary<int, string>
{
[1] = "name",
[2] = "team",
[4] = "skin",
[8] = "score",
[16] = "ping",
[32] = "time"
};

while (!br.IsEnd())
{
byte flags = br.ReadByte();
var player = new Dictionary<string, string>();

foreach (var key in keys)
{
if ((flags & key.Key) == key.Key)
{
player[key.Value] = ReadString(br);
}
}

players.Add(player);
}

return players;
}

private string ReadString(BinaryReader br)
{
int length = br.ReadByte();
return Encoding.UTF8.GetString(br.ReadBytes(length - 1));
}
}
}
23 changes: 23 additions & 0 deletions OpenGSQTests/Protocols/ASETests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenGSQTests;

namespace OpenGSQ.Protocols.Tests
{
[TestClass()]
public class ASETests : TestBase
{
// mtasa
public ASE ase = new("79.137.97.3", 22126);

public ASETests() : base(nameof(ASETests))
{
_EnableSave = false;
}

[TestMethod()]
public void GetStatusTest()
{
SaveResult(nameof(GetStatusTest), ase.GetStatus());
}
}
}
54 changes: 54 additions & 0 deletions OpenGSQTests/Results/ASETests/GetStatusTest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"gamename": "mta",
"gameport": "22003",
"hostname": "MTA Türkiye ✖ GÜL GAMİNG FREEROAM ✖ [Roleplay/Askeri/Drift/Drop/Turkey/Tr/Gül Gaming]",
"gametype": "BEDAVA - VIP",
"map": "None",
"version": "1.6",
"password": "0",
"numplayers": "5",
"maxplayers": "120",
"rules": {},
"players": [
{
"name": "SAMETNEXX",
"team": "",
"skin": "",
"score": "",
"ping": "56",
"time": ""
},
{
"name": "Gidikla_Beni",
"team": "",
"skin": "",
"score": "",
"ping": "93",
"time": ""
},
{
"name": "anil",
"team": "",
"skin": "",
"score": "",
"ping": "53",
"time": ""
},
{
"name": "AFFETMEM",
"team": "",
"skin": "",
"score": "",
"ping": "66",
"time": ""
},
{
"name": "dyperpro31",
"team": "",
"skin": "",
"score": "",
"ping": "62",
"time": ""
}
]
}

0 comments on commit bd8cc03

Please sign in to comment.