mirror of
https://github.com/Sanae6/SmoOnlineServer.git
synced 2024-11-21 18:55:17 +00:00
Add scenario merging and run reformatting on solution
This commit is contained in:
parent
3d4356ccfc
commit
00626ab12f
9 changed files with 86 additions and 36 deletions
|
@ -31,9 +31,13 @@ public class Client : IDisposable {
|
|||
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
|
||||
|
|
|
@ -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}";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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}");
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue