mirror of
https://github.com/CyberL1/Minecraft-Realms-Emulator.git
synced 2024-11-21 13:48:21 -05:00
feat: online player list
This commit is contained in:
parent
483bafcbf2
commit
f9f07756ac
98
Minecraft-Realms-Emulator/Helpers/MinecraftServerQuery.cs
Normal file
98
Minecraft-Realms-Emulator/Helpers/MinecraftServerQuery.cs
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
using Minecraft_Realms_Emulator.Responses;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Minecraft_Realms_Emulator.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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
Minecraft-Realms-Emulator/Modes/External/ActivitiesController.cs
vendored
Normal file
23
Minecraft-Realms-Emulator/Modes/External/ActivitiesController.cs
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Minecraft_Realms_Emulator.Attributes;
|
||||||
|
using Minecraft_Realms_Emulator.Responses;
|
||||||
|
|
||||||
|
namespace Minecraft_Realms_Emulator.Modes.External
|
||||||
|
{
|
||||||
|
[Route("modes/external/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
[RequireMinecraftCookie]
|
||||||
|
public class ActivitiesController : ControllerBase
|
||||||
|
{
|
||||||
|
[HttpGet("liveplayerlist")]
|
||||||
|
public ActionResult<LivePlayerListsResponse> GetLivePlayerList()
|
||||||
|
{
|
||||||
|
LivePlayerListsResponse response = new()
|
||||||
|
{
|
||||||
|
Lists = []
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Minecraft_Realms_Emulator.Attributes;
|
||||||
|
using Minecraft_Realms_Emulator.Data;
|
||||||
|
using Minecraft_Realms_Emulator.Enums;
|
||||||
|
using Minecraft_Realms_Emulator.Helpers;
|
||||||
|
using Minecraft_Realms_Emulator.Responses;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Minecraft_Realms_Emulator.Modes.Realms
|
||||||
|
{
|
||||||
|
[Route("modes/realms/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
[RequireMinecraftCookie]
|
||||||
|
public class ActivitiesController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly DataContext _context;
|
||||||
|
|
||||||
|
public ActivitiesController(DataContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("liveplayerlist")]
|
||||||
|
public ActionResult<LivePlayerListsResponse> GetLivePlayerList()
|
||||||
|
{
|
||||||
|
string cookie = Request.Headers.Cookie;
|
||||||
|
string playerUUID = cookie.Split(";")[0].Split(":")[2];
|
||||||
|
|
||||||
|
List<LivePlayerList> lists = [];
|
||||||
|
|
||||||
|
var worlds = _context.Worlds.Where(w => w.State == nameof(StateEnum.OPEN) && w.OwnerUUID == playerUUID || w.State == nameof(StateEnum.OPEN) && w.Players.Any(p => p.Uuid == playerUUID && p.Accepted)).ToList();
|
||||||
|
|
||||||
|
foreach (var world in worlds)
|
||||||
|
{
|
||||||
|
var connection = _context.Connections.Where(c => c.World.Id == world.Id).FirstOrDefault();
|
||||||
|
var query = new MinecraftServerQuery().Query(connection.Address);
|
||||||
|
|
||||||
|
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 = world.Id,
|
||||||
|
PlayerList = JsonConvert.SerializeObject(players),
|
||||||
|
};
|
||||||
|
|
||||||
|
lists.Add(list);
|
||||||
|
};
|
||||||
|
|
||||||
|
LivePlayerListsResponse response = new()
|
||||||
|
{
|
||||||
|
Lists = lists
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
namespace Minecraft_Realms_Emulator.Responses
|
||||||
|
{
|
||||||
|
public class LivePlayerListsResponse
|
||||||
|
{
|
||||||
|
public List<LivePlayerList> Lists { get; set; } = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LivePlayerList
|
||||||
|
{
|
||||||
|
public int ServerId { get; set; }
|
||||||
|
public string PlayerList { get; set; } = null!;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
namespace Minecraft_Realms_Emulator.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!;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user