1
1
mirror of https://github.com/CyberL1/MyMcRealms.git synced 2025-07-01 02:29:41 -04:00

Compare commits

..

36 Commits

Author SHA1 Message Date
eb5f50be7b chore: update mod to 1.21.5 2025-05-20 22:30:25 +02:00
15af6a794a fix: display real hardcore property (not the difficulty one) 2024-12-21 13:12:16 +01:00
67d324971e fix: slots on <1.21.1 2024-12-13 22:25:10 +01:00
0e06049d6e fix: display motd on >1.21.1 2024-12-10 00:31:05 +01:00
8f94aa8bdd fix: replace "�" with "§" in realm settings 2024-11-29 12:52:36 +01:00
ef35843140 chore: remove unused code, fix a typo 2024-11-23 14:45:35 +01:00
2245a95d55 chore: fix a typo 2024-10-03 17:10:03 +02:00
617ab4c11a fix: motd cutting on newer version 2024-10-03 17:07:33 +02:00
88974eee33 fix: do not send non-accessible servers to the player 2024-10-02 20:22:02 +02:00
6a7322943a chore: update packages 2024-09-29 18:52:30 +02:00
29f3b9133f chore: remove unused checks 2024-09-22 18:57:09 +02:00
79c97c7415 fix: check if world's motd is longer than the limit first (idk some C# shenanigans) 2024-09-22 08:31:02 +02:00
9976c0bbb5 fix: cut world's motd to its limit 2024-09-21 13:16:01 +02:00
6e27e44746 fix: dashless world owner uuid 2024-09-21 12:48:52 +02:00
7f7444249c feat: also replace & 2024-09-16 12:42:05 +02:00
abcf7b87e2 fix: replace invalid character for use with color codes 2024-09-16 12:23:55 +02:00
368e2c0e1b Owner => Not claimed 2024-09-13 14:58:19 +02:00
10c85cec19 fix for real 2024-09-09 10:53:42 +02:00
44a86e2733 revert the fix as it broke newer versions lol 2024-09-08 21:43:20 +02:00
27f9435a6a fix: typo 2024-09-08 21:13:06 +02:00
49bb02f3cf remove second Console.WriteLine 2024-09-08 21:01:24 +02:00
0b4291e873 remove Console.WriteLine 2024-09-08 21:00:01 +02:00
ecd0b3e020 Merge branch 'main' of https://github.com/CyberL1/MyMcRealms 2024-09-08 20:59:30 +02:00
5a93396138 fix: close worlds on older versions if the world's version is incompatible 2024-09-08 20:59:06 +02:00
3972d0eb05 lmao 2024-08-30 08:54:41 +02:00
377f45d492 update deploy workflow 2024-08-30 08:26:12 +02:00
dbee1d819f chore: update packages 2024-08-30 08:21:00 +02:00
9fd092c730 feat: live player list 2024-06-22 07:33:39 +02:00
6bad1e41eb feat: send errors as json instead of text 2024-06-17 13:03:03 +02:00
a25b93ae9f chore: remove unused using 2024-06-13 10:21:47 +02:00
ae057c59bb chore: remove not needed package and update needed ones 2024-06-12 11:39:50 +02:00
87a5fce41d feat: send dummy world's slots list 2024-06-12 11:32:00 +02:00
5ca12b1530 fix: id -> wId 2024-05-22 07:40:30 +02:00
4a34048841 fix: /subscriptions 2024-05-22 07:00:26 +02:00
f48ded5ceb fix: realm owner checking 2024-05-22 06:56:14 +02:00
ead8d901f3 feat: realm owner checking 2024-05-21 22:43:39 +02:00
23 changed files with 539 additions and 66 deletions

View File

@ -20,8 +20,8 @@ jobs:
sudo apt-get update
sudo apt-get install sshpass
- name: Stop the realms server for the deployment
run: sshpass -p '${{ secrets.VPS_PASSWORD }}' ssh -o StrictHostKeyChecking=no cyber@my-mc.link "pm2 stop 0"
run: sshpass -p '${{ secrets.VPS_PASSWORD }}' ssh -o StrictHostKeyChecking=no ${{ secrets.VPS_HOST }} -p ${{ secrets.VPS_PORT }} "pm2 stop 0"
- name: Deploy compiled binary and dll files to server
run: sshpass -p '${{ secrets.VPS_PASSWORD }}' scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -r MyMcRealms/bin/Release/net8.0/linux-arm64/publish/* cyber@my-mc.link:/home/cyber/MyMcRealms
run: sshpass -p '${{ secrets.VPS_PASSWORD }}' scp -P ${{ secrets.VPS_PORT }} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -r MyMcRealms/bin/Release/net8.0/linux-arm64/publish/* ${{ secrets.VPS_HOST }}:/home/cyber/MyMcRealms
- name: Start the realms server again
run: sshpass -p '${{ secrets.VPS_PASSWORD }}' ssh -o StrictHostKeyChecking=no cyber@my-mc.link "pm2 start 0"
run: sshpass -p '${{ secrets.VPS_PASSWORD }}' ssh -o StrictHostKeyChecking=no ${{ secrets.VPS_HOST }} -p ${{ secrets.VPS_PORT }} "pm2 start 0"

8
Gamemode.cs Normal file
View File

@ -0,0 +1,8 @@
using System;
public enum Gamemode
{
survival,
creative,
adventure
}

View File

@ -0,0 +1,11 @@
namespace MyMcRealms.Attributes
{
[AttributeUsage(AttributeTargets.Method)]
public class CheckRealmOwnerAttribute : Attribute
{
public bool IsRealmOwner(string playerUUID, string ownerUUID)
{
return playerUUID == ownerUUID;
}
}
}

View File

@ -1,9 +0,0 @@
namespace MyMcRealms
{
public enum Compatility
{
COMPATIBLE,
OTHER,
OUTDATED
}
}

View File

@ -0,0 +1,65 @@
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)
{
if (world.WhitelistEnable && !(world.Whitelist.Any(p => p.Uuid.Replace("-", "") == playerUUID) || world.Ops.Any(p => p.Uuid.Replace("-", "") == playerUUID)))
{
continue;
}
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

@ -2,6 +2,7 @@
using MyMcRealms.Responses;
using MyMcRealms.Attributes;
using MyMcRealms.Requests;
using Minecraft_Realms_Emulator.Responses;
namespace MyMcRealms.Controllers
{
@ -11,6 +12,7 @@ namespace MyMcRealms.Controllers
public class InvitesController : ControllerBase
{
[HttpPost("{wId}")]
[CheckRealmOwner]
public async Task<ActionResult<WorldResponse>> InvitePlayer(int wId, PlayerRequest body)
{
string cookie = Request.Headers.Cookie;
@ -21,7 +23,16 @@ namespace MyMcRealms.Controllers
var _api = new MyMcAPI.Wrapper(Environment.GetEnvironmentVariable("MYMC_API_KEY"));
var world = (await _api.GetAllServers()).Servers[wId];
if (world == null) return NotFound("World not found");
if (world == null)
{
ErrorResponse errorResponse = new()
{
ErrorCode = 404,
ErrorMsg = "World not found"
};
return NotFound(errorResponse);
}
var api = new MyMcAPI.Wrapper(world.OwnersToken);
var whitelist = await api.GetWhitelist();
@ -29,7 +40,16 @@ namespace MyMcRealms.Controllers
// Get player name
var playerInfo = await new HttpClient().GetFromJsonAsync<MinecraftPlayerResponse>($"https://api.mojang.com/users/profiles/minecraft/{body.Name}");
if (whitelist.Result.Any(p => p.Name == body.Name)) return BadRequest("Player already whitelisted");
if (whitelist.Result.Any(p => p.Name == body.Name))
{
ErrorResponse errorResponse = new()
{
ErrorCode = 400,
ErrorMsg = "Player already whitelisted"
};
return BadRequest(errorResponse);
}
api.ExecuteCommand($"whitelist add {body.Name}");
@ -88,12 +108,22 @@ namespace MyMcRealms.Controllers
}
[HttpDelete("{wId}/invite/{uuid}")]
[CheckRealmOwner]
public async Task<ActionResult<bool>> DeleteInvite(int wId, string uuid)
{
var _api = new MyMcAPI.Wrapper(Environment.GetEnvironmentVariable("MYMC_API_KEY"));
var world = (await _api.GetAllServers()).Servers[wId];
if (world == null) return NotFound("World not found");
if (world == null)
{
ErrorResponse errorResponse = new()
{
ErrorCode = 404,
ErrorMsg = "World not found"
};
return NotFound(errorResponse);
}
var api = new MyMcAPI.Wrapper(world.OwnersToken);
var whitelist = await api.GetWhitelist();
@ -103,7 +133,16 @@ namespace MyMcRealms.Controllers
// Get player name
var playerInfo = await new HttpClient().GetFromJsonAsync<MinecraftPlayerResponse>($"https://sessionserver.mojang.com/session/minecraft/profile/{uuid}");
if (!whitelist.Result.Any(p => p.Uuid.Replace("-", "") == uuid)) return BadRequest("Player not whitelisted");
if (!whitelist.Result.Any(p => p.Uuid.Replace("-", "") == uuid))
{
ErrorResponse errorResponse = new()
{
ErrorCode = 400,
ErrorMsg = "Player not whitelisted"
};
return BadRequest(errorResponse);
}
api.ExecuteCommand($"whitelist remove {player.Name}");
@ -113,7 +152,13 @@ namespace MyMcRealms.Controllers
[HttpDelete("{wId}")]
public ActionResult<string> LeaveRealms(int wId)
{
return BadRequest("You wish lmao");
ErrorResponse errorResponse = new()
{
ErrorCode = 400,
ErrorMsg = "You wish lmao"
};
return BadRequest(errorResponse);
}
}
}

View File

@ -18,7 +18,7 @@ namespace MyMcRealms.Controllers
[HttpGet("client/compatible")]
public string GetCompatible()
{
return Compatility.COMPATIBLE.ToString();
return "COMPATIBLE";
}
[HttpGet("v1/news")]
@ -26,7 +26,7 @@ namespace MyMcRealms.Controllers
{
var news = new NewsResponse
{
NewsLink = "https://github.com/CyberL1/Minecraft-Realms-Emulator",
NewsLink = "https://github.com/CyberL1/MyMcRealms",
};
return news;

View File

@ -10,6 +10,7 @@ namespace MyMcRealms.Controllers
public class OpsController : ControllerBase
{
[HttpPost("{wId}/{uuid}")]
[CheckRealmOwner]
public async Task<ActionResult<OpsResponse>> OpPlayer(int wId, string uuid)
{
var _api = new MyMcAPI.Wrapper(Environment.GetEnvironmentVariable("MYMC_API_KEY"));
@ -40,6 +41,7 @@ namespace MyMcRealms.Controllers
}
[HttpDelete("{wId}/{uuid}")]
[CheckRealmOwner]
public async Task<ActionResult<OpsResponse>> DeopPlayerAsync(int wId, string uuid)
{
var _api = new MyMcAPI.Wrapper(Environment.GetEnvironmentVariable("MYMC_API_KEY"));

View File

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc;
using Minecraft_Realms_Emulator.Responses;
using MyMcRealms.Attributes;
namespace Minecraft_Realms_Emulator.Controllers
@ -8,10 +9,17 @@ namespace Minecraft_Realms_Emulator.Controllers
[RequireMinecraftCookie]
public class SubscriptionsController : ControllerBase
{
[HttpGet("{id}")]
public ActionResult<string> GetSubscription(int id)
[HttpGet("{wId}")]
[CheckRealmOwner]
public ActionResult<string> GetSubscription(int wId)
{
return BadRequest("No subscription for you :(");
ErrorResponse errorResponse = new()
{
ErrorCode = 400,
ErrorMsg = "No subscription for you :("
};
return BadRequest(errorResponse);
}
}
}

View File

@ -8,8 +8,8 @@ namespace MyMcRealms.Controllers
[RequireMinecraftCookie]
public class TrialController : ControllerBase
{
[HttpGet(Name = "GetTrial")]
public bool Get() {
[HttpGet]
public bool GetTrial() {
return false;
}
}

View File

@ -1,7 +1,9 @@
using Microsoft.AspNetCore.Mvc;
using Minecraft_Realms_Emulator.Responses;
using MyMcRealms.Attributes;
using MyMcRealms.MyMcAPI.Responses;
using MyMcRealms.Responses;
using Newtonsoft.Json;
using Semver;
namespace MyMcRealms.Controllers
@ -38,13 +40,33 @@ namespace MyMcRealms.Controllers
bool isOlderVersion = SemVersion.Parse(gameVerision, SemVersionStyles.OptionalPatch).ComparePrecedenceTo(SemVersion.Parse("1.20.3", SemVersionStyles.OptionalPatch)) < 0;
bool isCompatibleOnOlderVersions = isOlderVersion && !isCompatible.StartsWith("NEEDS_");
bool isCompatibleOnOlderVersions = isOlderVersion && isCompatible == "COMPATIBLE";
bool isBanned = world.Banlist.Any(p => p.Name == playerName);
string worldOwnerName = world.Ops.ToArray().Length == 0 ? "Owner" : world.Ops[0].Name;
string worldOwnerUuid = world.Ops.ToArray().Length == 0 ? "069a79f444e94726a5befca90e38aaf5" : world.Ops[0].Uuid;
string worldOwnerName = world.Ops.ToArray().Length == 0 ? "Not claimed" : world.Ops[0].Name;
string worldOwnerUuid = world.Ops.ToArray().Length == 0 ? "069a79f444e94726a5befca90e38aaf5" : world.Ops[0].Uuid.Replace("-", "");
string worldName = world.Ops.ToArray().Length == 0 ? world.ServerName : $"{world.Ops[0].Name}'s server";
string worldState = isCompatibleOnOlderVersions || !isBanned ? "OPEN" : "CLOSED";
string worldState = !isBanned ? "OPEN" : "CLOSED";
if (isOlderVersion && !isCompatibleOnOlderVersions)
{
worldState = "CLOSED";
}
if (SemVersion.Parse(gameVerision, SemVersionStyles.OptionalPatch).ComparePrecedenceTo(SemVersion.Parse("1.19.4", SemVersionStyles.OptionalPatch)) < 0)
{
if (world.Motd.Length > 32)
{
world.Motd = world.Motd.Remove(32); // Pre 1.19.4 MOTD limit
}
}
else
{
if (world.Motd.Length > 52)
{
world.Motd = world.Motd.Remove(52); // Post 1.19.4 MOTD limit
}
}
WorldResponse response = new()
{
@ -52,7 +74,8 @@ namespace MyMcRealms.Controllers
Owner = worldOwnerName,
OwnerUUID = worldOwnerUuid,
Name = worldName,
Motd = world.Motd,
Motd = world.Motd.Replace("<22>", "§").Replace("&", "§"),
IsHardcore = world.Hardcore,
State = worldState,
WorldType = "NORMAL",
MaxPlayers = 10,
@ -68,11 +91,15 @@ namespace MyMcRealms.Controllers
ActiveVersion = world.GameVersion
};
if (world.Gamemode == "survival") response.GameMode = 0;
if (world.Gamemode == "creative") response.GameMode = 1;
if (world.Gamemode == "adventure") response.GameMode = 2;
allWorlds.Add(response);
}
}
ServersResponse servers = new()
ServersResponse servers = new()
{
Servers = allWorlds
};
@ -80,21 +107,31 @@ namespace MyMcRealms.Controllers
return Ok(servers);
}
[HttpGet("{id}")]
public async Task<ActionResult<WorldResponse>> GetWorldById(int id)
[HttpGet("{wId}")]
[CheckRealmOwner]
public async Task<ActionResult<WorldResponse>> GetWorldById(int wId)
{
var _api = new MyMcAPI.Wrapper(Environment.GetEnvironmentVariable("MYMC_API_KEY"));
var world = (await _api.GetAllServers()).Servers[id];
var world = (await _api.GetAllServers()).Servers[wId];
var api = new MyMcAPI.Wrapper(world.OwnersToken);
var whitelist = await api.GetWhitelist();
if (whitelist == null) return BadRequest($"Cannot get data for world {id}");
if (whitelist == null)
{
ErrorResponse errorResponse = new()
{
ErrorCode = 400,
ErrorMsg = $"Cannot get data for world {wId}"
};
string worldOwnerName = world.Ops.ToArray().Length == 0 ? "Owner" : world.Ops[0].Name;
string worldOwnerUuid = world.Ops.ToArray().Length == 0 ? "069a79f444e94726a5befca90e38aaf5" : world.Ops[0].Uuid;
string worldName = world.Ops.ToArray().Length == 0 ? world.ServerName : $"{world.Ops[0].Name}'s server";
return BadRequest(errorResponse);
}
string worldOwnerName = world.Ops[0].Name;
string worldOwnerUuid = world.Ops[0].Uuid;
string worldName = $"{world.Ops[0].Name}'s server";
List<PlayerResponse> whitelistedPlayers = [];
foreach (var player in whitelist.Result)
@ -112,13 +149,20 @@ namespace MyMcRealms.Controllers
whitelistedPlayers.Add(whitelistedPlayer);
}
string cookie = Request.Headers.Cookie;
string gameVerision = cookie.Split(";")[2].Split("=")[1];
int versionsCompared = SemVersion.Parse(gameVerision, SemVersionStyles.OptionalPatch).ComparePrecedenceTo(SemVersion.Parse(world.GameVersion, SemVersionStyles.OptionalPatch));
string isCompatible = versionsCompared == 0 ? "COMPATIBLE" : versionsCompared < 0 ? "NEEDS_DOWNGRADE" : "NEEDS_UPGRADE";
WorldResponse response = new()
{
Id = id,
Id = wId,
Owner = worldOwnerName,
OwnerUUID = worldOwnerUuid,
Name = worldName,
Motd = world.Motd,
Motd = world.Motd.Replace("<22>", "§"),
IsHardcore = world.Hardcore,
State = whitelist.Enabled ? "CLOSED" : "OPEN",
WorldType = "NORMAL",
MaxPlayers = 10,
@ -131,48 +175,99 @@ namespace MyMcRealms.Controllers
DaysLeft = 7,
Expired = false,
ExpiredTrial = false,
ActiveVersion = world.GameVersion
ActiveVersion = world.GameVersion,
Slots =
[
new()
{
SlotId = 1,
Options = JsonConvert.SerializeObject(new
{
slotName = "my-mc.link",
version = world.GameVersion,
compatibility = isCompatible,
})
}
]
};
if (world.Gamemode == "survival") response.GameMode = 0;
if (world.Gamemode == "creative") response.GameMode = 1;
if (world.Gamemode == "adventure") response.GameMode = 2;
return Ok(response);
}
[HttpPost("{wId}")]
[CheckRealmOwner]
public ActionResult<string> UpdateRealms(int wId)
{
return BadRequest("You can change the MOTD trough server.properties file");
ErrorResponse errorResponse = new()
{
ErrorCode = 400,
ErrorMsg = "You can change the MOTD trough server.properties file"
};
return BadRequest(errorResponse);
}
[HttpPost("{wId}/reset")]
public ActionResult<string> ChangeSlot(int id)
[CheckRealmOwner]
public ActionResult<string> ChangeSlot(int wId)
{
return BadRequest("lol nice try");
ErrorResponse errorResponse = new()
{
ErrorCode = 400,
ErrorMsg = "lol nice try"
};
return BadRequest(errorResponse);
}
[HttpPut("{id}/open")]
public async Task<ActionResult<bool>> Open(int id)
[HttpPut("{wId}/open")]
[CheckRealmOwner]
public async Task<ActionResult<bool>> Open(int wId)
{
var _api = new MyMcAPI.Wrapper(Environment.GetEnvironmentVariable("MYMC_API_KEY"));
var world = (await _api.GetAllServers()).Servers[id];
var world = (await _api.GetAllServers()).Servers[wId];
var api = new MyMcAPI.Wrapper(world.OwnersToken);
if (world == null) return NotFound("World not found");
if (world == null)
{
ErrorResponse errorResponse = new()
{
ErrorCode = 404,
ErrorMsg = "World not found"
};
return NotFound(errorResponse);
}
api.ExecuteCommand("whitelist off");
return Ok(true);
}
[HttpPut("{id}/close")]
public async Task<ActionResult<bool>> Close(int id)
[HttpPut("{wId}/close")]
[CheckRealmOwner]
public async Task<ActionResult<bool>> Close(int wId)
{
var _api = new MyMcAPI.Wrapper(Environment.GetEnvironmentVariable("MYMC_API_KEY"));
var world = (await _api.GetAllServers()).Servers[id];
var world = (await _api.GetAllServers()).Servers[wId];
var api = new MyMcAPI.Wrapper(world.OwnersToken);
if (world == null) return NotFound("World not found");
if (world == null)
{
ErrorResponse errorResponse = new()
{
ErrorCode = 404,
ErrorMsg = "World not found"
};
return NotFound(errorResponse);
}
api.ExecuteCommand("whitelist on");
@ -180,15 +275,29 @@ namespace MyMcRealms.Controllers
}
[HttpPost("{wId}/slot/{sId}")]
[CheckRealmOwner]
public ActionResult<string> UpdateSlot(int wId, int sId)
{
return BadRequest("no.");
ErrorResponse errorResponse = new()
{
ErrorCode = 400,
ErrorMsg = "no."
};
return BadRequest(errorResponse);
}
[HttpGet("{wId}/slot/{sId}/download")]
[CheckRealmOwner]
public ActionResult<string> GetBackups(int wId, int sId)
{
return BadRequest("Wouldn't it be nice if you could download your world to singleplayer? Well I think that too");
ErrorResponse errorResponse = new()
{
ErrorCode = 400,
ErrorMsg = "Wouldn't it be nice if you could download your world to singleplayer? Well I think that too"
};
return BadRequest(errorResponse);
}
[HttpGet("v1/{wId}/join/pc")]

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,68 @@
using Minecraft_Realms_Emulator.Responses;
using MyMcRealms.Attributes;
using MyMcRealms.MyMcAPI.Responses;
namespace Minecraft_Realms_Emulator.Middlewares
{
public class CheckRealmOwnerMiddleware(RequestDelegate next)
{
private readonly RequestDelegate _next = next;
public async Task Invoke(HttpContext httpContext)
{
var endpoint = httpContext.GetEndpoint();
var attribute = endpoint?.Metadata.GetMetadata<CheckRealmOwnerAttribute>();
if (attribute == null)
{
await _next(httpContext);
return;
}
string playerUUID = httpContext.Request.Headers.Cookie.ToString().Split(";")[0].Split(":")[2];
var servers = await new MyMcRealms.MyMcAPI.Wrapper(Environment.GetEnvironmentVariable("MYMC_API_KEY")).GetAllServers();
Server server = servers.Servers.Find(s => servers.Servers.IndexOf(s) == int.Parse(httpContext.Request.RouteValues["wId"].ToString()));
if (server == null)
{
ErrorResponse errorResponse = new()
{
ErrorCode = 404,
ErrorMsg = "World not found"
};
httpContext.Response.StatusCode = 404;
await httpContext.Response.WriteAsJsonAsync(errorResponse);
return;
}
if (server.Ops.Count == 0) {
ErrorResponse errorResponse = new()
{
ErrorCode = 403,
ErrorMsg = "This world isn't owned by anyone"
};
httpContext.Response.StatusCode = 403;
await httpContext.Response.WriteAsJsonAsync(errorResponse);
return;
}
if (!attribute.IsRealmOwner(playerUUID, server.Ops[0].Uuid.Replace("-", "")))
{
ErrorResponse errorResponse = new()
{
ErrorCode = 403,
ErrorMsg = "You don't own this world"
};
httpContext.Response.StatusCode = 403;
await httpContext.Response.WriteAsJsonAsync(errorResponse);
return;
}
await _next(httpContext);
}
}
}

View File

@ -18,6 +18,8 @@
public List<Whitelist> Whitelist { get; set; } = null!;
public bool WhitelistEnable { get; set; }
public string OwnersToken { get; set; } = string.Empty;
public string Gamemode { get; set; } = null!;
public bool Hardcore { get; set; }
}
public class Op

View File

@ -8,16 +8,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DotNetEnv" Version="3.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="DotNetEnv" Version="3.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.2" />
<PackageReference Include="Semver" Version="2.3.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.8.0" />
</ItemGroup>
</Project>

View File

@ -1,4 +1,5 @@
using Microsoft.Extensions.FileProviders;
using Minecraft_Realms_Emulator.Middlewares;
using MyMcRealms.Middlewares;
var builder = WebApplication.CreateBuilder(args);
@ -28,6 +29,7 @@ if (app.Environment.IsDevelopment())
}
app.UseMiddleware<MinecraftCookieMiddleware>();
app.UseMiddleware<CheckRealmOwnerMiddleware>();
app.MapControllers();
app.UseStaticFiles();

View File

@ -0,0 +1,8 @@
namespace Minecraft_Realms_Emulator.Responses
{
public class ErrorResponse
{
public int ErrorCode { get; set; }
public string ErrorMsg { get; set; } = string.Empty;
}
}

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!;
}
}

View File

@ -0,0 +1,14 @@
namespace MyMcRealms.Responses
{
public class SlotResponse
{
public int SlotId { get; set; }
public SlotSettingsResponse Settings { get; set; } = null!;
public string Options { get; set; } = null!;
public SlotResponse()
{
Settings = new SlotSettingsResponse();
}
}
}

View File

@ -0,0 +1,7 @@
namespace MyMcRealms.Responses
{
public class SlotSettingsResponse
{
public bool Hardcore = false;
}
}

View File

@ -1,15 +1,14 @@
using System.Text.Json;
namespace MyMcRealms.Responses
namespace MyMcRealms.Responses
{
public class WorldResponse
{
public int Id { get; set; }
// public Subscription? Subscription { get; set; }
public string? Owner { get; set; }
public string? OwnerUUID { get; set; }
public string? Name { get; set; }
public string? Motd { get; set; }
public int GameMode { get; set; }
public bool IsHardcore { get; set; }
public string State { get; set; } = "OPEN";
public string WorldType { get; set; } = "NORMAL";
public List<PlayerResponse> Players { get; set; } = [];
@ -18,7 +17,7 @@ namespace MyMcRealms.Responses
public int? MinigameId { get; set; }
public string? MinigameImage { get; set; }
public int ActiveSlot { get; set; } = 1;
public JsonDocument[] Slots { get; set; } = [];
public List<SlotResponse> Slots { get; set; } = [];
public bool Member { get; set; } = false;
public string RemoteSubscriptionId { get; set; } = Guid.NewGuid().ToString();
public int DaysLeft { get; set; } = 30;