mirror of
https://github.com/CyberL1/MyMcRealms.git
synced 2025-07-01 10:29:42 -04:00
Compare commits
38 Commits
ebcadb33cf
...
main
Author | SHA1 | Date | |
---|---|---|---|
eb5f50be7b | |||
15af6a794a | |||
67d324971e | |||
0e06049d6e | |||
8f94aa8bdd | |||
ef35843140 | |||
2245a95d55 | |||
617ab4c11a | |||
88974eee33 | |||
6a7322943a | |||
29f3b9133f | |||
79c97c7415 | |||
9976c0bbb5 | |||
6e27e44746 | |||
7f7444249c | |||
abcf7b87e2 | |||
368e2c0e1b | |||
10c85cec19 | |||
44a86e2733 | |||
27f9435a6a | |||
49bb02f3cf | |||
0b4291e873 | |||
ecd0b3e020 | |||
5a93396138 | |||
3972d0eb05 | |||
377f45d492 | |||
dbee1d819f | |||
9fd092c730 | |||
6bad1e41eb | |||
a25b93ae9f | |||
ae057c59bb | |||
87a5fce41d | |||
5ca12b1530 | |||
4a34048841 | |||
f48ded5ceb | |||
ead8d901f3 | |||
f631b7519c | |||
42397e6f93 |
6
.github/workflows/deploy.yml
vendored
6
.github/workflows/deploy.yml
vendored
@ -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
8
Gamemode.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using System;
|
||||
|
||||
public enum Gamemode
|
||||
{
|
||||
survival,
|
||||
creative,
|
||||
adventure
|
||||
}
|
11
MyMcRealms/Attributes/CheckRealmOwnerAttribute.cs
Normal file
11
MyMcRealms/Attributes/CheckRealmOwnerAttribute.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
namespace MyMcRealms
|
||||
{
|
||||
public enum Compatility
|
||||
{
|
||||
COMPATIBLE,
|
||||
OTHER,
|
||||
OUTDATED
|
||||
}
|
||||
}
|
65
MyMcRealms/Controllers/ActivitiesController.cs
Normal file
65
MyMcRealms/Controllers/ActivitiesController.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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"));
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -8,8 +8,8 @@ namespace MyMcRealms.Controllers
|
||||
[RequireMinecraftCookie]
|
||||
public class TrialController : ControllerBase
|
||||
{
|
||||
[HttpGet(Name = "GetTrial")]
|
||||
public bool Get() {
|
||||
[HttpGet]
|
||||
public bool GetTrial() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -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,6 +91,10 @@ 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);
|
||||
}
|
||||
}
|
||||
@ -80,18 +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();
|
||||
|
||||
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";
|
||||
if (whitelist == null)
|
||||
{
|
||||
ErrorResponse errorResponse = new()
|
||||
{
|
||||
ErrorCode = 400,
|
||||
ErrorMsg = $"Cannot get data for world {wId}"
|
||||
};
|
||||
|
||||
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)
|
||||
@ -109,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,
|
||||
@ -128,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");
|
||||
|
||||
@ -177,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")]
|
||||
|
98
MyMcRealms/Helpers/MinercraftServerQuery.cs
Normal file
98
MyMcRealms/Helpers/MinercraftServerQuery.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
68
MyMcRealms/Middlewares/CheckRealmOwnerMiddleware.cs
Normal file
68
MyMcRealms/Middlewares/CheckRealmOwnerMiddleware.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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();
|
||||
|
8
MyMcRealms/Responses/ErrorResponse.cs
Normal file
8
MyMcRealms/Responses/ErrorResponse.cs
Normal 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;
|
||||
}
|
||||
}
|
13
MyMcRealms/Responses/LivePlayerListsResponse.cs
Normal file
13
MyMcRealms/Responses/LivePlayerListsResponse.cs
Normal 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!;
|
||||
}
|
||||
}
|
29
MyMcRealms/Responses/MinecraftSeerverQueryResponse.cs
Normal file
29
MyMcRealms/Responses/MinecraftSeerverQueryResponse.cs
Normal 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!;
|
||||
}
|
||||
}
|
14
MyMcRealms/Responses/SlotResponse.cs
Normal file
14
MyMcRealms/Responses/SlotResponse.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
7
MyMcRealms/Responses/SlotSettingsResponse.cs
Normal file
7
MyMcRealms/Responses/SlotSettingsResponse.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace MyMcRealms.Responses
|
||||
{
|
||||
public class SlotSettingsResponse
|
||||
{
|
||||
public bool Hardcore = false;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
Binary file not shown.
Reference in New Issue
Block a user