Merge remote-tracking branch 'origin/master'

Conflicts:
	README.md
This commit is contained in:
Robin C. Ladiges 2022-07-02 18:58:17 +02:00
commit 26e100ff72
No known key found for this signature in database
GPG Key ID: B494D3DF92661B99
3 changed files with 63 additions and 22 deletions

View File

@ -21,6 +21,16 @@ dotnet run --project Server/Server.csproj -c Release
``` ```
If you ran `dotnet build` instead of `dotnet run`, you can find the binary at `Server/bin/net6.0/Release/Server.exe` If you ran `dotnet build` instead of `dotnet run`, you can find the binary at `Server/bin/net6.0/Release/Server.exe`
## Running under systemd
If you have systemd, you can use the existing systemd serivce.
```shell
cp smo.serivce /etc/systemd/system/smo.service
# edit ExecStart to your path for the server executable and change WorkingDirectory to the server directory
chmod +x filepath to the server executable
systemctl enable --now smo.service
```
## Run docker image ## Run docker image
If you have [docker](https://docs.docker.com/) on your system, you can use the existing docker image. If you have [docker](https://docs.docker.com/) on your system, you can use the existing docker image.

View File

@ -16,9 +16,10 @@ DiscordBot bot = new DiscordBot();
await bot.Run(); await bot.Run();
server.ClientJoined += (c, _) => { server.ClientJoined += (c, _) => {
if (Settings.Instance.BanList.Enabled && (Settings.Instance.BanList.Players.Contains(c.Id) || if (Settings.Instance.BanList.Enabled
Settings.Instance.BanList.IpAddresses.Contains( && (Settings.Instance.BanList.Players.Contains(c.Id)
((IPEndPoint) c.Socket!.RemoteEndPoint!).Address.ToString()))) || Settings.Instance.BanList.IpAddresses.Contains(
((IPEndPoint) c.Socket!.RemoteEndPoint!).Address.ToString())))
throw new Exception($"Banned player attempted join: {c.Name}"); throw new Exception($"Banned player attempted join: {c.Name}");
c.Metadata["shineSync"] = new ConcurrentBag<int>(); c.Metadata["shineSync"] = new ConcurrentBag<int>();
c.Metadata["loadedSave"] = false; c.Metadata["loadedSave"] = false;
@ -125,8 +126,8 @@ server.PacketHandler = (c, p) => {
&& Settings.Instance.Flip.Pov is FlipOptions.Both or FlipOptions.Others && Settings.Instance.Flip.Pov is FlipOptions.Both or FlipOptions.Others
&& Settings.Instance.Flip.Players.Contains(c.Id): { && Settings.Instance.Flip.Players.Contains(c.Id): {
playerPacket.Position += Vector3.UnitY * MarioSize((bool) c.Metadata["2d"]); playerPacket.Position += Vector3.UnitY * MarioSize((bool) c.Metadata["2d"]);
playerPacket.Rotation *= Quaternion.CreateFromRotationMatrix(Matrix4x4.CreateRotationX(MathF.PI)) * playerPacket.Rotation *= Quaternion.CreateFromRotationMatrix(Matrix4x4.CreateRotationX(MathF.PI))
Quaternion.CreateFromRotationMatrix(Matrix4x4.CreateRotationY(MathF.PI)); * Quaternion.CreateFromRotationMatrix(Matrix4x4.CreateRotationY(MathF.PI));
server.Broadcast(playerPacket, c); server.Broadcast(playerPacket, c);
return false; return false;
} }
@ -136,8 +137,8 @@ server.PacketHandler = (c, p) => {
server.BroadcastReplace(playerPacket, c, (from, to, sp) => { server.BroadcastReplace(playerPacket, c, (from, to, sp) => {
if (Settings.Instance.Flip.Players.Contains(to.Id)) { if (Settings.Instance.Flip.Players.Contains(to.Id)) {
sp.Position += Vector3.UnitY * MarioSize((bool) c.Metadata["2d"]); sp.Position += Vector3.UnitY * MarioSize((bool) c.Metadata["2d"]);
sp.Rotation *= Quaternion.CreateFromRotationMatrix(Matrix4x4.CreateRotationX(MathF.PI)) * sp.Rotation *= Quaternion.CreateFromRotationMatrix(Matrix4x4.CreateRotationX(MathF.PI))
Quaternion.CreateFromRotationMatrix(Matrix4x4.CreateRotationY(MathF.PI)); * Quaternion.CreateFromRotationMatrix(Matrix4x4.CreateRotationY(MathF.PI));
} }
to.Send(sp, from); to.Send(sp, from);
@ -152,22 +153,28 @@ server.PacketHandler = (c, p) => {
CommandHandler.RegisterCommand("rejoin", args => { CommandHandler.RegisterCommand("rejoin", args => {
bool moreThanOne = false; bool moreThanOne = false;
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
foreach (Client user in server.Clients.Where(c => c.Connected && args.Any(x => c.Name.StartsWith(x) || Client[] clients = (args.Length == 1 && args[0] == "*"
(Guid.TryParse(x, out Guid result) && result == c.Id)))) { ? server.Clients.Where(c =>
c.Connected && args.Any(x => c.Name.StartsWith(x) || (Guid.TryParse(x, out Guid result) && result == c.Id)))
: server.Clients.Where(c => c.Connected)).ToArray();
foreach (Client user in clients) {
if (moreThanOne) builder.Append(", "); if (moreThanOne) builder.Append(", ");
builder.Append(user.Name); builder.Append(user.Name);
user.Dispose(); user.Dispose();
moreThanOne = true; moreThanOne = true;
} }
return moreThanOne ? $"Caused {builder} to rejoin" : "Usage: rejoin <usernames...>"; return clients.Length > 0 ? $"Caused {builder} to rejoin" : "Usage: rejoin <usernames...>";
}); });
CommandHandler.RegisterCommand("crash", args => { CommandHandler.RegisterCommand("crash", args => {
bool moreThanOne = false; bool moreThanOne = false;
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
foreach (Client user in server.Clients.Where(c => c.Connected && args.Any(x => c.Name.StartsWith(x) || Client[] clients = (args.Length == 1 && args[0] == "*"
(Guid.TryParse(x, out Guid result) && result == c.Id)))) { ? server.Clients.Where(c =>
c.Connected && args.Any(x => c.Name.StartsWith(x) || (Guid.TryParse(x, out Guid result) && result == c.Id)))
: server.Clients.Where(c => c.Connected)).ToArray();
foreach (Client user in clients) {
if (moreThanOne) builder.Append(", "); if (moreThanOne) builder.Append(", ");
moreThanOne = true; moreThanOne = true;
builder.Append(user.Name); builder.Append(user.Name);
@ -182,14 +189,18 @@ CommandHandler.RegisterCommand("crash", args => {
}); });
} }
return moreThanOne ? $"Crashed {builder}" : "Usage: crash <usernames...>"; return clients.Length > 0 ? $"Crashed {builder}" : "Usage: crash <usernames...>";
}); });
CommandHandler.RegisterCommand("ban", args => { CommandHandler.RegisterCommand("ban", args => {
bool moreThanOne = false; bool moreThanOne = false;
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
foreach (Client user in server.Clients.Where(c => c.Connected && args.Any(x => c.Name.StartsWith(x) ||
(Guid.TryParse(x, out Guid result) && result == c.Id)))) { Client[] clients = (args.Length == 1 && args[0] == "*"
? server.Clients.Where(c =>
c.Connected && args.Any(x => c.Name.StartsWith(x) || (Guid.TryParse(x, out Guid result) && result == c.Id)))
: server.Clients.Where(c => c.Connected)).ToArray();
foreach (Client user in clients) {
if (moreThanOne) builder.Append(", "); if (moreThanOne) builder.Append(", ");
moreThanOne = true; moreThanOne = true;
builder.Append(user.Name); builder.Append(user.Name);
@ -207,7 +218,7 @@ CommandHandler.RegisterCommand("ban", args => {
}); });
} }
if (moreThanOne) { if (clients.Length > 0) {
Settings.SaveSettings(); Settings.SaveSettings();
return $"Banned {builder}."; return $"Banned {builder}.";
} }
@ -228,16 +239,17 @@ CommandHandler.RegisterCommand("send", args => {
} }
if (!stage.Contains("Stage") && !stage.Contains("Zone")) { if (!stage.Contains("Stage") && !stage.Contains("Zone")) {
return "Invalid Stage Name!"; return "Invalid Stage Name! ```cap -> Cap Kingdom\ncascade -> Cascade Kingdom\nsand -> Sand Kingdom\nlake -> Lake Kingdom\nwooded -> Wooded Kingdom\ncloud -> Cloud Kingdom\nlost -> Lost Kingdom\nmetro -> Metro Kingdom\nsea -> Sea Kingdom\nsnow -> Snow Kingdom\nlunch -> Luncheon Kingdom\nruined -> Ruined Kingdom\nbowser -> Bowser's Kingdom\nmoon -> Moon Kingdom\nmush -> Mushroom Kingdom\ndark -> Dark Side\ndarker -> Darker Side```";
} }
if (!sbyte.TryParse(args[2], out sbyte scenario) || scenario < -1) if (!sbyte.TryParse(args[2], out sbyte scenario) || scenario < -1)
return $"Invalid scenario number {args[2]} (range: [-1 to 127])"; return $"Invalid scenario number {args[2]} (range: [-1 to 127])";
Client[] players = args[3] == "*" Client[] players = args[3] == "*"
? server.Clients.Where(c => c.Connected).ToArray() ? server.Clients.Where(c => c.Connected).ToArray()
: server.Clients.Where(c => c.Connected && args[3..].Any(x => c.Name.StartsWith(x) || : server.Clients.Where(c =>
(Guid.TryParse(x, out Guid result) && c.Connected
result == c.Id))).ToArray(); && args[3..].Any(x => c.Name.StartsWith(x) || (Guid.TryParse(x, out Guid result) && result == c.Id)))
.ToArray();
Parallel.ForEachAsync(players, async (c, _) => { Parallel.ForEachAsync(players, async (c, _) => {
await c.Send(new ChangeStagePacket { await c.Send(new ChangeStagePacket {
Stage = stage, Stage = stage,
@ -261,7 +273,7 @@ CommandHandler.RegisterCommand("sendall", args => {
} }
if (!stage.Contains("Stage") && !stage.Contains("Zone")) { if (!stage.Contains("Stage") && !stage.Contains("Zone")) {
return "Invalid Stage Name!"; return "Invalid Stage Name! ```cap -> Cap Kingdom\ncascade -> Cascade Kingdom\nsand -> Sand Kingdom\nlake -> Lake Kingdom\nwooded -> Wooded Kingdom\ncloud -> Cloud Kingdom\nlost -> Lost Kingdom\nmetro -> Metro Kingdom\nsea -> Sea Kingdom\nsnow -> Snow Kingdom\nlunch -> Luncheon Kingdom\nruined -> Ruined Kingdom\nbowser -> Bowser's Kingdom\nmoon -> Moon Kingdom\nmush -> Mushroom Kingdom\ndark -> Dark Side\ndarker -> Darker Side```";
} }
Client[] players = server.Clients.Where(c => c.Connected).ToArray(); Client[] players = server.Clients.Where(c => c.Connected).ToArray();
@ -445,7 +457,7 @@ CommandHandler.RegisterCommand("shine", args => {
case "clear" when args.Length == 1: case "clear" when args.Length == 1:
shineBag.Clear(); shineBag.Clear();
foreach (ConcurrentBag<int> playerBag in server.Clients.Select(serverClient => foreach (ConcurrentBag<int> playerBag in server.Clients.Select(serverClient =>
(ConcurrentBag<int>) serverClient.Metadata["shineSync"])) playerBag.Clear(); (ConcurrentBag<int>) serverClient.Metadata["shineSync"])) playerBag.Clear();
return "Cleared shine bags"; return "Cleared shine bags";
case "sync" when args.Length == 1: case "sync" when args.Length == 1:

19
smo.service Normal file
View File

@ -0,0 +1,19 @@
[Unit]
Description="Super Mario Odyssey Multiplayer Server"
After=network.target
StartLimitIntervalSec=0
[Service]
# Uncommnt User to run under a different user
# User=user
# change ExecStart to the path of the server file
ExecStart="/home/user/SMOServer/Server"
# change WorkingDirectory to the folder of your server
WorkingDirectory=/home/user/SMOServer/
# ensure the service restarts after crashing
Restart=always
# amount of time to wait before restarting the service
RestartSec=5
[Install]
WantedBy=multi-user.target