sodoff-mmo/src/Server.cs
Hipposgrumm 65eeb7dd53 Added support for Red Alert and Disco Alert (#3)
Revamped entire room Alerts system.
Merged RoomWithAlert into Room (as part of the revamp).

This added support for Red Alert and Disco Alert.
This meant that I had to revamp the room alerts system to allow for multiple alerts per room.
Events hopefully shouldn't overlap each other in the same room.
An extra feature is that an alert will start for a player that has just entered the room (with a duration reduced based on when the alert initially started). I shoved this functionality's working into SetUserVariablesHandler on line 30. This feature doesn't seem to work when leaving a non-MMO rooms such as minigames (may be related to missed JL command).
2024-08-12 10:19:46 +00:00

89 lines
3.4 KiB
C#

using sodoffmmo.Core;
using sodoffmmo.Data;
using sodoffmmo.Management;
using System;
using System.Net;
using System.Net.Sockets;
namespace sodoffmmo;
public class Server {
readonly int port;
readonly IPAddress ipAddress;
readonly bool IPv6AndIPv4;
ModuleManager moduleManager = new();
public Server(IPAddress ipAdress, int port, bool IPv6AndIPv4) {
this.ipAddress = ipAdress;
this.port = port;
this.IPv6AndIPv4 = IPv6AndIPv4;
}
public async Task Run() {
moduleManager.RegisterModules();
ManagementCommandProcessor.Initialize();
using Socket listener = new(ipAddress.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp);
if (IPv6AndIPv4)
listener.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, 0);
listener.Bind(new IPEndPoint(ipAddress, port));
Room.GetOrAdd("LoungeInt").AddAlert(new Room.AlertInfo("3")); // FIXME use config for this
Room.GetOrAdd("Spaceport").AddAlert(new Room.AlertInfo("1", 20.0, 300, 300));
Room.GetOrAdd("Spaceport").AddAlert(new Room.AlertInfo("2", 120.0, 1800, 3600));
Room.GetOrAdd("Academy").AddAlert(new Room.AlertInfo("1", 20.0, 300, 300));
await Listen(listener);
}
private async Task Listen(Socket listener) {
Console.WriteLine($"MMO Server listening on port {port}");
listener.Listen(100);
while (true) {
Socket handler = await listener.AcceptAsync();
handler.SendTimeout = 200;
Console.WriteLine($"New connection from {((IPEndPoint)handler.RemoteEndPoint!).Address}");
_ = Task.Run(() => HandleClient(handler));
}
}
private async Task HandleClient(Socket handler) {
Client client = new(handler);
try {
while (client.Connected) {
await client.Receive();
List<NetworkObject> networkObjects = new();
while (client.TryGetNextPacket(out NetworkPacket packet))
networkObjects.Add(packet.GetObject());
await HandleObjects(networkObjects, client);
}
} finally {
try {
client.SetRoom(null);
} catch (Exception) { }
client.Disconnect();
Console.WriteLine("Socket disconnected IID: " + client.ClientID);
}
}
private async Task HandleObjects(List<NetworkObject> networkObjects, Client client) {
foreach (var obj in networkObjects) {
try {
short commandId = obj.Get<short>("a");
CommandHandler handler;
if (commandId != 13) {
if (commandId == 0 || commandId == 1)
Console.WriteLine($"System command: {commandId} IID: {client.ClientID}");
handler = moduleManager.GetCommandHandler(commandId);
} else
handler = moduleManager.GetCommandHandler(obj.Get<NetworkObject>("p").Get<string>("c"));
Task task = handler.Handle(client, obj.Get<NetworkObject>("p"));
if (!handler.RunInBackground)
await task;
} catch (Exception ex) {
Console.WriteLine($"Exception IID: {client.ClientID} - {ex}");
}
}
}
}