Add scenario merging and run reformatting on solution

This commit is contained in:
Sanae 2022-03-01 15:08:53 -06:00
parent 3d4356ccfc
commit 00626ab12f
9 changed files with 86 additions and 36 deletions

View File

@ -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>(T packet, Client? sender = null) where T : struct, IPacket {
IMemoryOwner<byte> memory = MemoryPool<byte>.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

View File

@ -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}";
}
}

View File

@ -1,4 +1,4 @@
namespace Server;
namespace Server;
public enum FlipOptions {
Both,

View File

@ -15,6 +15,15 @@ Logger consoleLogger = new Logger("Console");
server.ClientJoined += async (c, type) => {
c.Metadata["shineSync"] = new ConcurrentBag<int>();
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 <true/false>";
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<int> playerBag in server.Clients.Select(serverClient => (ConcurrentBag<int>) serverClient.Metadata["shineSync"])) {
playerBag.Clear();
}
foreach (ConcurrentBag<int> playerBag in server.Clients.Select(serverClient => (ConcurrentBag<int>) serverClient.Metadata["shineSync"])) playerBag.Clear();
return "Cleared shine bags";
default:
return optionUsage;

View File

@ -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<in T>(Client from, Client to, T value); // replacer must send
public async Task BroadcastReplace<T>(T packet, Client sender, PacketReplacer<T> 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>(T packet, Client sender) where T : struct, IPacket {
IMemoryOwner<byte> 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<byte> 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}");

View File

@ -8,11 +8,11 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\Shared.csproj" />
<ProjectReference Include="..\Shared\Shared.csproj"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1"/>
</ItemGroup>
</Project>

View File

@ -20,7 +20,8 @@ public class Settings {
try {
Instance = JsonConvert.DeserializeObject<Settings>(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<Guid> Players { get; set; } = new List<Guid>();
public bool EnabledOnStart { get; set; } = true;

View File

@ -8,8 +8,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ObjectDumper.NET" Version="3.3.13" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
<PackageReference Include="ObjectDumper.NET" Version="3.3.13"/>
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0"/>
</ItemGroup>
</Project>

View File

@ -25,6 +25,7 @@ PacketType[] reboundPackets = {
};
string lastCapture = "";
async Task S() {
IMemoryOwner<byte> owner = MemoryPool<byte>.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);