1
1
mirror of https://github.com/CyberL1/MyMcRealms.git synced 2024-12-25 05:48:23 -05:00

feat: live player list

This commit is contained in:
CyberL1 2024-06-22 07:33:39 +02:00
parent 6bad1e41eb
commit 9fd092c730
4 changed files with 200 additions and 0 deletions

View File

@ -0,0 +1,60 @@
using Microsoft.AspNetCore.Mvc;
using MyMcRealms.Attributes;
using MyMcRealms.Helpers;
using MyMcRealms.MyMcAPI;
using MyMcRealms.Responses;
using Newtonsoft.Json;
namespace MyMcRealms.Controllers
{
[Route("[controller]")]
[ApiController]
[RequireMinecraftCookie]
public class ActivitiesController : ControllerBase
{
[HttpGet("liveplayerlist")]
public async Task<ActionResult<LivePlayerListsResponse>> GetLivePlayerList()
{
string cookie = Request.Headers.Cookie;
string playerUUID = cookie.Split(";")[0].Split(":")[2];
List<LivePlayerList> lists = [];
var allServers = await new Wrapper(Environment.GetEnvironmentVariable("MYMC_API_KEY")).GetAllServers();
foreach (var world in allServers.Servers)
{
var query = new MinecraftServerQuery().Query(world.Connect);
if (query == null) continue;
List<object> players = [];
if (query.Players.Sample == null) continue;
foreach (var player in query.Players.Sample)
{
players.Add(new
{
playerId = player.Id.Replace("-", ""),
});
}
LivePlayerList list = new()
{
ServerId = allServers.Servers.IndexOf(world),
PlayerList = JsonConvert.SerializeObject(players),
};
lists.Add(list);
};
LivePlayerListsResponse response = new()
{
Lists = lists
};
return Ok(response);
}
}
}

View File

@ -0,0 +1,98 @@
using MyMcRealms.Responses;
using Newtonsoft.Json;
using System.Net.Sockets;
using System.Text;
namespace MyMcRealms.Helpers
{
public class MinecraftServerQuery
{
public MinecraftServerQueryRepsonse? Query(string address)
{
string server = address.Split(':')[0];
int port = address.Contains(':') ? int.Parse(address.Split(':')[1]) : 25565;
try
{
using (TcpClient client = new())
{
client.Connect(server, port);
using (NetworkStream stream = client.GetStream())
using (BinaryWriter writer = new(stream))
using (BinaryReader reader = new(stream))
{
// Send Handshake packet (https://wiki.vg/Protocol#Handshake)
byte[] handshakePacket = CreateHandshakePacket(server, port);
writer.Write((byte)handshakePacket.Length); // Packet length
writer.Write(handshakePacket); // Packet data
// Send Status Request packet (https://wiki.vg/Protocol#Request)
writer.Write((byte)0x01); // Packet length
writer.Write((byte)0x00); // Packet ID (Request)
// Read the response length
int length = ReadVarInt(reader);
// Read the response packet ID
int packetId = ReadVarInt(reader);
if (packetId != 0x00) throw new Exception("Invalid packet ID");
// Read the JSON length
int jsonLength = ReadVarInt(reader);
// Read the JSON response
byte[] jsonData = reader.ReadBytes(jsonLength);
string json = Encoding.UTF8.GetString(jsonData);
return JsonConvert.DeserializeObject<MinecraftServerQueryRepsonse>(json);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
return null;
}
}
private static byte[] CreateHandshakePacket(string server, int port)
{
using (MemoryStream ms = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(ms))
{
WriteVarInt(writer, 0x00); // Packet ID (Handshake)
WriteVarInt(writer, 754); // Protocol version (754 for Minecraft 1.16.5)
WriteVarInt(writer, server.Length); // Server address length
writer.Write(Encoding.UTF8.GetBytes(server)); // Server address
writer.Write((ushort)port); // Server port
WriteVarInt(writer, 1); // Next state (1 for status)
return ms.ToArray();
}
}
}
private static int ReadVarInt(BinaryReader reader)
{
int value = 0;
int size = 0;
int b;
while (((b = reader.ReadByte()) & 0x80) == 0x80)
{
value |= (b & 0x7F) << (size++ * 7);
if (size > 5) throw new Exception("VarInt is too big");
}
return value | (b << (size * 7));
}
private static void WriteVarInt(BinaryWriter writer, int value)
{
while ((value & 0xFFFFFF80) != 0)
{
writer.Write((byte)((value & 0x7F) | 0x80));
value >>= 7;
}
writer.Write((byte)(value & 0x7F));
}
}
}

View File

@ -0,0 +1,13 @@
namespace MyMcRealms.Responses
{
public class LivePlayerListsResponse
{
public List<LivePlayerList> Lists { get; set; } = [];
}
public class LivePlayerList
{
public int ServerId { get; set; }
public string PlayerList { get; set; } = null!;
}
}

View File

@ -0,0 +1,29 @@
namespace MyMcRealms.Responses
{
public class MinecraftServerQueryRepsonse
{
public MinecraftServerQueryVersionObject Version { get; set; } = null!;
public bool EnforcesSecureChat { get; set; }
public string Description { get; set; } = null!;
public MinecraftServerQueryPlayersObject Players { get; set; } = null!;
}
public class MinecraftServerQueryVersionObject
{
public string Name { get; set; } = null!;
public string Protocol { get; set; } = null!;
}
public class MinecraftServerQueryPlayersObject
{
public int Max { get; set; }
public int Online { get; set; }
public List<MinecraftServerQueryPlayersSampleObject> Sample { get; set; } = null!;
}
public class MinecraftServerQueryPlayersSampleObject
{
public string Id { get; set; } = null!;
public string Name { get; set; } = null!;
}
}