From 00626ab12f49fe18ea099aa8e656904587310243 Mon Sep 17 00:00:00 2001 From: Sanae Date: Tue, 1 Mar 2022 15:08:53 -0600 Subject: [PATCH] Add scenario merging and run reformatting on solution --- Server/Client.cs | 8 +++++-- Server/CommandHandler.cs | 3 ++- Server/FlipOptions.cs | 2 +- Server/Program.cs | 50 +++++++++++++++++++++++++++++++--------- Server/Server.cs | 34 +++++++++++++++++---------- Server/Server.csproj | 4 ++-- Server/Settings.cs | 11 +++++++-- Shared/Shared.csproj | 4 ++-- TestClient/Program.cs | 6 ++--- 9 files changed, 86 insertions(+), 36 deletions(-) diff --git a/Server/Client.cs b/Server/Client.cs index cb80ecc..521e2e4 100644 --- a/Server/Client.cs +++ b/Server/Client.cs @@ -25,15 +25,19 @@ public class Client : IDisposable { Socket = socket; Logger = new Logger(socket.RemoteEndPoint?.ToString() ?? "Unknown User???"); } - + public void Dispose() { if (Socket?.Connected is true) Socket.Disconnect(false); } + public delegate IPacket PacketTransformerDel(Client? sender, IPacket packet); + + public event PacketTransformerDel? PacketTransformer; + public async Task Send(T packet, Client? sender = null) where T : struct, IPacket { IMemoryOwner memory = MemoryPool.Shared.RentZero(Constants.MaxPacketSize); - + packet = (T) (PacketTransformer?.Invoke(sender, packet) ?? packet); PacketHeader header = new PacketHeader { Id = sender?.Id ?? Guid.Empty, Type = Constants.PacketMap[typeof(T)].Type diff --git a/Server/CommandHandler.cs b/Server/CommandHandler.cs index 90a3ff7..86d24cb 100644 --- a/Server/CommandHandler.cs +++ b/Server/CommandHandler.cs @@ -19,7 +19,8 @@ public static class CommandHandler { if (args.Length == 0) return "No command entered, see help command for valid commands"; string commandName = args[0]; return Handlers.TryGetValue(commandName, out Handler? handler) ? handler(args[1..]) : $"Invalid command {args[0]}, see help command for valid commands"; - } catch (Exception e) { + } + catch (Exception e) { return $"An error occured while trying to process your command: {e}"; } } diff --git a/Server/FlipOptions.cs b/Server/FlipOptions.cs index bf0107d..30a375b 100644 --- a/Server/FlipOptions.cs +++ b/Server/FlipOptions.cs @@ -1,4 +1,4 @@ -namespace Server; +namespace Server; public enum FlipOptions { Both, diff --git a/Server/Program.cs b/Server/Program.cs index e6ecb16..5414048 100644 --- a/Server/Program.cs +++ b/Server/Program.cs @@ -15,6 +15,15 @@ Logger consoleLogger = new Logger("Console"); server.ClientJoined += async (c, type) => { c.Metadata["shineSync"] = new ConcurrentBag(); c.Metadata["loadedSave"] = false; + c.Metadata["scenario"] = 0; + c.PacketTransformer += (sender, packet) => { + if (Settings.Instance.Scenario.MergeEnabled && packet is PlayerPacket playerPacket) { + playerPacket.ScenarioNum = (int) c.Metadata["scenario"]; + return playerPacket; + } + + return packet; + }; }; async Task ClientSyncShineBag(Client client) { @@ -23,7 +32,8 @@ async Task ClientSyncShineBag(Client client) { await client.Send(new ShinePacket { ShineId = shine }); - } catch { + } + catch { // errors that can happen when sending will crash the server :) } } @@ -39,8 +49,14 @@ timer.Elapsed += (_, _) => { SyncShineBag(); }; timer.Start(); bool flipEnabled = Settings.Instance.Flip.EnabledOnStart; -float MarioSize(bool is2d) => is2d ? 180 : 160; +float MarioSize(bool is2d) { + return is2d ? 180 : 160; +} + server.PacketHandler = (c, p) => { + { + if (p is PlayerPacket playerPacket) c.Metadata["scenario"] = playerPacket.ScenarioNum; + } switch (p) { case CostumePacket: ClientSyncShineBag(c); @@ -77,12 +93,25 @@ server.PacketHandler = (c, p) => { return true; }; -// -// CommandHandler.RegisterCommand("scenario", args => { -// const string optionUsage = "Valid options: split <" -// if (args.Length < 1) -// return -// }); + +CommandHandler.RegisterCommand("scenario", args => { + const string optionUsage = "Valid options: merge "; + if (args.Length < 1) + return optionUsage; + switch (args[0]) { + case "merge" when args.Length == 2: { + if (bool.TryParse(args[1], out bool result)) { + Settings.Instance.Scenario.MergeEnabled = result; + Settings.SaveSettings(); + return result ? "Enabled scenario merge" : "Disabled scenario merge"; + } + + return optionUsage; + } + default: + return optionUsage; + } +}); CommandHandler.RegisterCommand("list", _ => $"List: {string.Join(", ", server.Clients.Select(x => $"{x.Name} ({x.Id})"))}"); @@ -142,9 +171,8 @@ CommandHandler.RegisterCommand("shine", args => { return $"Shines: {string.Join(", ", shineBag)}"; case "clear" when args.Length == 1: shineBag.Clear(); - foreach (ConcurrentBag playerBag in server.Clients.Select(serverClient => (ConcurrentBag) serverClient.Metadata["shineSync"])) { - playerBag.Clear(); - } + foreach (ConcurrentBag playerBag in server.Clients.Select(serverClient => (ConcurrentBag) serverClient.Metadata["shineSync"])) playerBag.Clear(); + return "Cleared shine bags"; default: return optionUsage; diff --git a/Server/Server.cs b/Server/Server.cs index e64bd63..3785f18 100644 --- a/Server/Server.cs +++ b/Server/Server.cs @@ -38,22 +38,28 @@ public class Server { } Task.Run(() => HandleSocket(socket)); - } catch { + } + catch { // super ignore this } } - } catch (OperationCanceledException) { + } + catch (OperationCanceledException) { // ignore the exception, it's just for closing the server } + Logger.Info("Server closing"); try { serverSocket.Shutdown(SocketShutdown.Both); - } catch (Exception) { + } + catch (Exception) { // ignore - } finally { + } + finally { serverSocket.Close(); } + Logger.Info("Server closed"); } @@ -66,11 +72,11 @@ public class Server { // broadcast packets to all clients public delegate void PacketReplacer(Client from, Client to, T value); // replacer must send + public async Task BroadcastReplace(T packet, Client sender, PacketReplacer packetReplacer) where T : struct, IPacket { - foreach (Client client in Clients.Where(client => sender.Id != client.Id)) { - packetReplacer(sender, client, packet); - } + foreach (Client client in Clients.Where(client => sender.Id != client.Id)) packetReplacer(sender, client, packet); } + public async Task Broadcast(T packet, Client sender) where T : struct, IPacket { IMemoryOwner memory = memoryPool.RentZero(Constants.MaxPacketSize); @@ -107,7 +113,7 @@ public class Server { private async void HandleSocket(Socket socket) { - Client client = new Client(socket) { Server = this }; + Client client = new Client(socket) {Server = this}; IMemoryOwner memory = null!; bool first = true; try { @@ -205,7 +211,9 @@ public class Server { }); Logger.Info($"Client {client.Name} ({client.Id}/{socket.RemoteEndPoint}) connected."); - } else if (header.Id != client.Id && client.Id != Guid.Empty) throw new Exception($"Client {client.Name} sent packet with invalid client id {header.Id} instead of {client.Id}"); + } else if (header.Id != client.Id && client.Id != Guid.Empty) { + throw new Exception($"Client {client.Name} sent packet with invalid client id {header.Id} instead of {client.Id}"); + } if (header.Type == PacketType.Costume) { CostumePacket costumePacket = new CostumePacket { @@ -223,14 +231,16 @@ public class Server { memory.Dispose(); continue; } - } catch (Exception e){ + } + catch (Exception e) { client.Logger.Error($"Packet handler warning: {e}"); } Broadcast(memory, client); } - } catch (Exception e) { - if (e is SocketException { SocketErrorCode: SocketError.ConnectionReset }) { + } + catch (Exception e) { + if (e is SocketException {SocketErrorCode: SocketError.ConnectionReset}) { client.Logger.Info($"Client {socket.RemoteEndPoint} ({client.Id}) disconnected from the server"); } else { client.Logger.Error($"Exception on socket {socket.RemoteEndPoint} ({client.Id}) and disconnecting for: {e}"); diff --git a/Server/Server.csproj b/Server/Server.csproj index 994ae4d..b7af41b 100644 --- a/Server/Server.csproj +++ b/Server/Server.csproj @@ -8,11 +8,11 @@ - + - + diff --git a/Server/Settings.cs b/Server/Settings.cs index 1864d71..6738d62 100644 --- a/Server/Settings.cs +++ b/Server/Settings.cs @@ -20,7 +20,8 @@ public class Settings { try { Instance = JsonConvert.DeserializeObject(text, new StringEnumConverter(new CamelCaseNamingStrategy())) ?? Instance; Logger.Info("Loaded settings from settings.json"); - } catch (Exception e) { + } + catch (Exception e) { Logger.Warn($"Failed to load settings.json: {e}"); } } else { @@ -32,19 +33,25 @@ public class Settings { try { File.WriteAllText("settings.json", JsonConvert.SerializeObject(Instance, Formatting.Indented, new StringEnumConverter(new CamelCaseNamingStrategy()))); Logger.Info("Saved settings to settings.json"); - } catch (Exception e) { + } + catch (Exception e) { Logger.Error($"Failed to save settings.json {e}"); } } public ServerTable Server { get; set; } = new ServerTable(); public FlipTable Flip { get; set; } = new FlipTable(); + public ScenarioTable Scenario { get; set; } = new ScenarioTable(); public class ServerTable { public string Address { get; set; } = IPAddress.Any.ToString(); public ushort Port { get; set; } = 1027; } + public class ScenarioTable { + public bool MergeEnabled { get; set; } = false; + } + public class FlipTable { public List Players { get; set; } = new List(); public bool EnabledOnStart { get; set; } = true; diff --git a/Shared/Shared.csproj b/Shared/Shared.csproj index 727c233..6f7f07a 100644 --- a/Shared/Shared.csproj +++ b/Shared/Shared.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/TestClient/Program.cs b/TestClient/Program.cs index 8474be8..e3bc6a0 100644 --- a/TestClient/Program.cs +++ b/TestClient/Program.cs @@ -25,6 +25,7 @@ PacketType[] reboundPackets = { }; string lastCapture = ""; + async Task S() { IMemoryOwner owner = MemoryPool.Shared.Rent(Constants.MaxPacketSize); while (true) { @@ -37,9 +38,7 @@ async Task S() { PlayerPacket playerPacket = new PlayerPacket(); playerPacket.Deserialize(owner.Memory.Span[Constants.HeaderSize..]); logger.Info(playerPacket.Hack); - if (playerPacket.Hack != lastCapture) { - logger.Info($"Changed to hack: {lastCapture = playerPacket.Hack}"); - } + if (playerPacket.Hack != lastCapture) logger.Info($"Changed to hack: {lastCapture = playerPacket.Hack}"); // cap.Position = playerPacket.Position + Vector3.UnitY * 500f; // cap.Rotation = Quaternion.CreateFromYawPitchRoll(0,0,0); // cap.CapAnim = "StayR"; @@ -55,6 +54,7 @@ async Task S() { // await stream.WriteAsync(owner.Memory[..Constants.MaxPacketSize]); // continue; } + if (reboundPackets.All(x => x != type)) continue; header.Id = ownId; MemoryMarshal.Write(owner.Memory.Span, ref header);