~furry/mamoru-server

8483090667bc85971f5f642d15917bde7462cd86 — nora 2 months ago fbe157e
reformat & cleanup
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;