diff --git a/src/Attributes/ManagementCommandAttribute.cs b/src/Attributes/ManagementCommandAttribute.cs new file mode 100644 index 0000000..561ce2e --- /dev/null +++ b/src/Attributes/ManagementCommandAttribute.cs @@ -0,0 +1,14 @@ +using sodoffmmo.Management; + +namespace sodoffmmo.Attributes; + +[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +public class ManagementCommandAttribute : Attribute { + public string Name { get; set; } + public Role Role { get; set; } + + public ManagementCommandAttribute(string name, Role role) { + Name = name; + Role = role; + } +} diff --git a/src/CommandHandlers/ChatMessageHandler.cs b/src/CommandHandlers/ChatMessageHandler.cs index e20f690..8a3ceb6 100644 --- a/src/CommandHandlers/ChatMessageHandler.cs +++ b/src/CommandHandlers/ChatMessageHandler.cs @@ -1,21 +1,25 @@ using sodoffmmo.Attributes; using sodoffmmo.Core; using sodoffmmo.Data; +using sodoffmmo.Management; namespace sodoffmmo.CommandHandlers; [ExtensionCommandHandler("SCM")] class ChatMessageHandler : CommandHandler { public override Task Handle(Client client, NetworkObject receivedObject) { + string message = receivedObject.Get("p").Get("chm"); + if (ManagementCommandProcessor.ProcessCommand(message, client)) + return Task.CompletedTask; if (!Configuration.ServerConfiguration.EnableChat) { - ChatDisabled(client, receivedObject); + ChatDisabled(client); } else { - Chat(client, receivedObject); + Chat(client, message); } return Task.CompletedTask; } - public void ChatDisabled(Client client, NetworkObject receivedObject) { + public void ChatDisabled(Client client) { NetworkObject cmd = new(); NetworkObject data = new(); data.Add("arr", new string[] { "CMR", "-1", "-1", "1", "Unfortunately, chat has been disabled by server administrators", "", "1", "Server" }); @@ -26,10 +30,9 @@ class ChatMessageHandler : CommandHandler { client.Send(packet); } - public void Chat(Client client, NetworkObject receivedObject) { + public void Chat(Client client, string message) { if (client.PlayerData.DiplayName == "") return; - string message = receivedObject.Get("p").Get("chm"); NetworkObject cmd = new(); NetworkObject data = new(); diff --git a/src/Data/PlayerData.cs b/src/Data/PlayerData.cs index 4e830b8..de568c7 100644 --- a/src/Data/PlayerData.cs +++ b/src/Data/PlayerData.cs @@ -33,6 +33,9 @@ public class PlayerData { // animation bitfield (animations used by avatar, e.g. mounted, swim, ...) public int Mbf { get; set; } + public string DiplayName { get; set; } = ""; + public Role Role { get; set; } = Role.User; + public static readonly string[] SupportedVariables = { "A", // avatar data "FP", // raised pet data @@ -94,9 +97,6 @@ public class PlayerData { IsValid = true; } - public string DiplayName { get; set; } = ""; - public Role Role { get; set; } = Role.User; - public NetworkArray GetNetworkData(int clientID, out NetworkArray paramArr) { NetworkArray arr = new(); arr.Add(clientID); diff --git a/src/Management/AuthenticationInfo.cs b/src/Management/AuthenticationInfo.cs index 094ac97..266ebc1 100644 --- a/src/Management/AuthenticationInfo.cs +++ b/src/Management/AuthenticationInfo.cs @@ -16,5 +16,5 @@ public class AuthenticationInfo { [Serializable] public enum Role { - User, Admin, Moderator + User = 0, Moderator = 1, Admin = 2 } \ No newline at end of file diff --git a/src/Management/IManagementCommand.cs b/src/Management/IManagementCommand.cs new file mode 100644 index 0000000..3fcd8c3 --- /dev/null +++ b/src/Management/IManagementCommand.cs @@ -0,0 +1,11 @@ +using sodoffmmo.Core; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace sodoffmmo.Management; +public interface IManagementCommand { + public void Handle(Client client, string[] arguments); +} diff --git a/src/Management/ManagementCommandProcessor.cs b/src/Management/ManagementCommandProcessor.cs new file mode 100644 index 0000000..508db68 --- /dev/null +++ b/src/Management/ManagementCommandProcessor.cs @@ -0,0 +1,51 @@ +using sodoffmmo.Attributes; +using sodoffmmo.Core; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace sodoffmmo.Management; +public class ManagementCommandProcessor { + static Dictionary, Type> commands = new(); + static bool initialized = false; + + public static void Initialize() { + if (!Configuration.ServerConfiguration.Authentication) + return; + commands.Clear(); + var handlerTypes = Assembly.GetExecutingAssembly().GetTypes() + .Where(type => typeof(IManagementCommand).IsAssignableFrom(type)) + .Where(type => type.GetCustomAttribute() != null); + + foreach (var handlerType in handlerTypes) { + ManagementCommandAttribute attrib = (handlerType.GetCustomAttribute(typeof(ManagementCommandAttribute)) as ManagementCommandAttribute)!; + commands[new Tuple(attrib.Name, attrib.Role)] = handlerType; + } + initialized = true; + } + + public static bool ProcessCommand(string message, Client client) { + if (!Configuration.ServerConfiguration.Authentication || !initialized) + return false; + if (!message.StartsWith("//") && message.Length < 3) + return false; + + string[] parts = message.Split(' '); + string commandName = parts[0].Substring(2); + string[] arguments = parts.Skip(1).ToArray(); + + for (int i = (int)client.PlayerData.Role; i >= 0; --i) { + Role currentRole = (Role)i; + + if (commands.TryGetValue(new Tuple(commandName, currentRole), out Type? commandType)) { + IManagementCommand command = (IManagementCommand)Activator.CreateInstance(commandType)!; + command.Handle(client, arguments); + return true; + } + } + return false; + } +} diff --git a/src/Server.cs b/src/Server.cs index 911ee28..40965bb 100644 --- a/src/Server.cs +++ b/src/Server.cs @@ -1,5 +1,6 @@ using sodoffmmo.Core; using sodoffmmo.Data; +using sodoffmmo.Management; using System; using System.Net; using System.Net.Sockets; @@ -20,6 +21,7 @@ public class Server { public async Task Run() { moduleManager.RegisterModules(); + ManagementCommandProcessor.Initialize(); using Socket listener = new(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);