M Connections/ServerLogConnection.cs => Connections/ServerLogConnection.cs +1 -1
@@ 5,7 5,7 @@ namespace Mamoru.Connections;
public class ServerLogConnection : WebSocketBehavior {
public static string Path = "/serverlog";
-
+
protected override void OnMessage(MessageEventArgs e) {
Send(e.Data);
Log.Info(e.Data);
M Mamoru.cs => Mamoru.cs +3 -3
@@ 4,17 4,17 @@ using Mamoru.Managers;
namespace Mamoru;
public class Mamoru : Plugin<Config> {
- public static Mamoru Instance { get; } = new();
public ConfigManager ConfigManager = null!;
public RoutesManager RoutesManager = null!;
+ public static Mamoru Instance { get; } = new();
public override string Name => "Mamoru";
public override string Author => "furry";
public override void OnEnabled() {
ConfigManager = new ConfigManager();
- RoutesManager = new RoutesManager();
-
+ RoutesManager = new RoutesManager();
+
Log.Info("Mamoru was enabled.");
base.OnEnabled();
}
M Mamoru.csproj => Mamoru.csproj +3 -3
@@ 9,12 9,12 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="EXILED" Version="9.0.0-beta.4" />
+ <PackageReference Include="EXILED" Version="9.0.0-beta.4"/>
<PackageReference Include="WebSocketSharp" Version="1.0.3-rc11"/>
</ItemGroup>
<ItemGroup>
- <Folder Include="Models.EXILED\" />
- <Folder Include="Router\" />
+ <Folder Include="Models.EXILED\"/>
+ <Folder Include="Router\"/>
</ItemGroup>
</Project>
M Managers/ConfigManager.cs => Managers/ConfigManager.cs +3 -2
@@ 11,9 11,10 @@ public class ConfigManager {
.IgnoreUnmatchedProperties()
.Build();
- internal RemoteAdminConfig RemoteAdminConfig = null!;
internal GameplayConfig GameplayConfig = null!;
-
+
+ internal RemoteAdminConfig RemoteAdminConfig = null!;
+
public ConfigManager() {
LoadRAConfig();
LoadGameplayConfig();
M Managers/RoutesManager.cs => Managers/RoutesManager.cs +4 -4
@@ 16,8 16,8 @@ public class RoutesManager {
public RoutesManager() {
Log.Info("Setting up HTTP server...");
LoadRoutes();
-
- _router.Traverse((n) => Log.Info(n.Path));
+
+ _router.Traverse(n => Log.Info(n.Path));
Log.Info("Registering HandleRequest events...");
RegisterEvents();
@@ 49,7 49,7 @@ public class RoutesManager {
.GetTypes()
.Where(type => type.IsClass && type is { IsAbstract: false, Namespace: "Mamoru.Routes" })
.ToArray()
- .ForEach((type) => {
+ .ForEach(type => {
try {
var clazz = (AbstractRoute)Activator.CreateInstance(type);
_router.AddRoute(ref clazz, clazz.Path.Trim('/'));
@@ 59,7 59,7 @@ public class RoutesManager {
Log.Warn($"Failed to load http route {type.Name}");
}
});
-
+
_httpServer.AddWebSocketService<ServerLogConnection>(ServerLogConnection.Path);
}
M Models.DedicatedServer/GameplayConfig.cs => Models.DedicatedServer/GameplayConfig.cs +16 -15
@@ 1,4 1,5 @@
using YamlDotNet.Serialization;
+
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
namespace Mamoru.Models.DedicatedServer;
@@ 108,7 109,7 @@ public class GameplayConfig {
public bool AutoDeconBroadcastEnabled { get; set; }
public string AutoDeconBroadcastMessage { get; set; }
public ushort AutoDeconBroadcastTime { get; set; }
-
+
// Security & anticheat
public bool OnlineMode { get; set; }
public ushort AuthenticationTimeout { get; set; }
@@ 137,13 138,13 @@ public class GameplayConfig {
public ushort PreauthChallengeSecretLength { get; set; }
public bool EnforceSameIp { get; set; }
public bool NoEnforcementForLocalIpAddresses { get; set; }
-
+
// Rate limiting
public bool EnableIpRatelimit { get; set; }
public bool EnableUseridRatelimit { get; set; }
public ushort IpRatelimitWindow { get; set; }
public ushort UseridRatelimitWindow { get; set; }
-
+
// Item Category Limit
public string LimitCategoryGrenade { get; set; }
public string LimitCategoryKeycard { get; set; }
@@ 155,7 156,7 @@ public class GameplayConfig {
public string LimitAmmo44Cal { get; set; }
public string LimitAmmo762X39 { get; set; }
public string LimitAmmo9X19 { get; set; }
-
+
// Friendly Fire punishment
public ushort FfDetectorGlobalBroadcastSeconds { get; set; }
public ushort FfDetectorGlobalAdminchatSeconds { get; set; }
@@ 220,24 221,24 @@ public class GameplayConfig {
public bool FfDetectorExplosionAfterDisconnectingBroadcastEnable { get; set; }
public string FfDetectorExplosionAfterDisconnectingBroadcastMessage { get; set; }
public bool FfDetectorExplosionAfterDisconnectingWebhookReport { get; set; }
-
+
// custom white list see gameplay config doc
public bool CustomWhitelist { get; set; }
-
+
// use only if server restricts access
public bool ServerAccessRestriction { get; set; }
-
+
// transparently modded
public bool TransparentlyModdedServer { get; set; }
-
+
// non dedicated servers only
public List<ushort> PortQueue { get; set; }
-
+
public string GbanBanIp { get; set; }
-
+
public string BanNicknameMaxlength { get; set; }
public string BanNicknameTrimunicode { get; set; }
-
+
public string NicknameFilter { get; set; }
public string NicknameFilterReplacement { get; set; }
public bool BroadcastKicks { get; set; }
@@ 246,12 247,12 @@ public class GameplayConfig {
public bool BroadcastBans { get; set; }
public string BroadcastBanText { get; set; }
public ushort BroadcastBanDuration { get; set; }
-
+
public bool IdleModeEnabled { get; set; }
public ushort IdleModeTime { get; set; }
public ushort IdleModePreauthTime { get; set; }
public ushort IdleModeTickrate { get; set; }
-
+
public bool ReportSendUsingDiscordWebhook { get; set; }
public string ReportDiscordWebhookUrl { get; set; }
public string ReportUsername { get; set; }
@@ 260,10 261,10 @@ public class GameplayConfig {
public string ReportServerName { get; set; }
public string ReportHeader { get; set; }
public string ReportContent { get; set; }
-
+
public ushort RestartAfterRounds { get; set; }
public ushort FullRestartRejoinTime { get; set; }
-
+
public string GeoblockingMode { get; set; }
public bool GeoblockingIgnoreWhitelisted { get; set; }
public List<string> GeoblockingWhitelist { get; set; }
M Models.DedicatedServer/RemoteAdminConfig.cs => Models.DedicatedServer/RemoteAdminConfig.cs +1 -0
@@ 1,4 1,5 @@
using YamlDotNet.Serialization;
+
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
namespace Mamoru.Models.DedicatedServer;
M Models.Mamoru/Status.cs => Models.Mamoru/Status.cs +1 -1
@@ 5,4 5,4 @@ public record Status(
bool Webhooks,
string ExiledVersion,
string MamoruVersion
-);
+);<
\ No newline at end of file
M Routes/AbstractRoute.cs => Routes/AbstractRoute.cs +2 -1
@@ 6,7 6,7 @@ namespace Mamoru.Routes;
public abstract class AbstractRoute {
public abstract string Path { get; }
public virtual bool Cors => false;
-
+
public virtual void Connect(ref HttpListenerRequest req, ref HttpListenerResponse res, ref Context ctx) {
EmptyResponse.Create(ref res, HttpStatusCode.MethodNotAllowed);
}
@@ 32,6 32,7 @@ public abstract class AbstractRoute {
EmptyResponse.Create(ref res);
return;
}
+
EmptyResponse.Create(ref res, HttpStatusCode.MethodNotAllowed);
}
M Routes/StatusRoute.cs => Routes/StatusRoute.cs +3 -3
@@ 1,6 1,6 @@
using System.Reflection;
+using Exiled.Loader;
using Mamoru.Models.Mamoru;
-using Mamoru.Routes;
using Mamoru.Utils;
using WebSocketSharp.Net;
@@ 12,9 12,9 @@ public class StatusRoute : AbstractRoute {
public override void Get(ref HttpListenerRequest req, ref HttpListenerResponse res, ref Context ctx) {
var status = new Status(
- true,
true,
- Assembly.GetAssembly(typeof(Exiled.Loader.Loader)).GetName().Version.ToString(),
+ true,
+ Assembly.GetAssembly(typeof(Loader)).GetName().Version.ToString(),
Assembly.GetExecutingAssembly().GetName().Version.ToString()
);
YamlResponse.Create(ref res, status);
M Utils/Response.cs => Utils/Response.cs +1 -1
@@ 9,7 9,7 @@ public static class YamlResponse {
private static readonly ISerializer Serializer = new SerializerBuilder()
.WithNamingConvention(UnderscoredNamingConvention.Instance)
.Build();
-
+
public static void Create(ref HttpListenerResponse res, object value, HttpStatusCode statusCode = HttpStatusCode.OK) {
var serialized = Serializer.Serialize(value);
var data = Utf8.GetBytes(serialized);
M Utils/Router.cs => Utils/Router.cs +7 -8
@@ 1,4 1,3 @@
-using Exiled.API.Features;
using Mamoru.Routes;
namespace Mamoru.Utils;
@@ 6,8 5,8 @@ namespace Mamoru.Utils;
public record Context(Dictionary<string, string>? QueryParams, Dictionary<string, string>? RouteParams);
public class Node(string path, AbstractRoute? route = null) {
- public readonly string Path = path;
public readonly List<Node> Children = [];
+ public readonly string Path = path;
public readonly AbstractRoute? Route = route;
public void Add(Node child) {
@@ 19,17 18,18 @@ public class Node(string path, AbstractRoute? route = null) {
}
public Node? Find(string index) {
- return Children.FirstOrDefault((node) => node.Path == index);
+ return Children.FirstOrDefault(node => node.Path == index);
}
public void Traverse(Action<Node> action) {
action(this);
- Children.ForEach((node) => node.Traverse(action));
+ Children.ForEach(node => node.Traverse(action));
}
public void AddRoute(ref AbstractRoute route, string path, Node? parent = null) {
path = path.Trim('/');
parent ??= this;
+
var sep = path.IndexOf('/');
var seg = sep == -1 ? path : path.Substring(0, sep);
var curr = parent.Find(seg);
@@ 37,18 37,17 @@ public class Node(string path, AbstractRoute? route = null) {
parent.Add(n);
if (n.Route is not null) return;
-
+
AddRoute(ref route, path.Substring(sep + 1), curr ?? parent.Find(seg));
}
public AbstractRoute? MatchRoute(string path, Node? parent = null) {
path = path.Trim('/');
parent ??= this;
+
var sep = path.IndexOf('/');
var seg = sep == -1 ? path : path.Substring(0, sep);
- if (string.IsNullOrEmpty(seg)) {
- return MatchRoute(path.Substring(sep + 1), parent);
- }
+ if (string.IsNullOrEmpty(seg)) return MatchRoute(path.Substring(sep + 1), parent);
var curr = parent.Find(seg);
if (curr is null) return null;