2022-01-26 11:32:16 -05:00
|
|
|
|
using System;
|
2015-03-08 17:20:10 -04:00
|
|
|
|
using System.Collections.Generic;
|
2022-01-26 11:32:16 -05:00
|
|
|
|
using System.Diagnostics;
|
2017-06-01 13:42:28 -04:00
|
|
|
|
using System.Linq;
|
2018-06-02 00:48:10 -04:00
|
|
|
|
using System.Security.Cryptography;
|
2018-05-05 16:36:26 -04:00
|
|
|
|
using System.Text.RegularExpressions;
|
2017-11-25 20:29:58 -05:00
|
|
|
|
using System.Threading.Tasks;
|
2021-03-22 12:09:25 -04:00
|
|
|
|
using Data.Abstractions;
|
|
|
|
|
using Data.Models;
|
2022-01-26 11:32:16 -05:00
|
|
|
|
using Microsoft.EntityFrameworkCore;
|
2020-11-11 18:31:26 -05:00
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
using Serilog.Context;
|
2022-01-26 11:32:16 -05:00
|
|
|
|
using SharedLibraryCore.Configuration;
|
|
|
|
|
using SharedLibraryCore.Database.Models;
|
|
|
|
|
using SharedLibraryCore.Helpers;
|
|
|
|
|
using SharedLibraryCore.Interfaces;
|
2021-03-22 12:09:25 -04:00
|
|
|
|
using static Data.Models.Client.EFClient;
|
2017-11-25 20:29:58 -05:00
|
|
|
|
|
2018-04-08 02:44:42 -04:00
|
|
|
|
namespace SharedLibraryCore.Commands
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Quits IW4MAdmin
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class QuitCommand : Command
|
2017-05-26 18:49:27 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public QuitCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "quit";
|
|
|
|
|
Description = _translationLookup["COMMANDS_QUIT_DESC"];
|
|
|
|
|
Alias = "q";
|
|
|
|
|
Permission = Permission.Owner;
|
|
|
|
|
RequiresTarget = false;
|
|
|
|
|
}
|
2017-05-26 18:49:27 -04:00
|
|
|
|
|
2022-03-24 12:34:32 -04:00
|
|
|
|
public override async Task ExecuteAsync(GameEvent E)
|
2017-05-26 18:49:27 -04:00
|
|
|
|
{
|
2022-03-24 12:34:32 -04:00
|
|
|
|
await E.Owner.Manager.Stop();
|
2019-05-08 21:34:17 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Restarts IW4MAdmin
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class RestartCommand : Command
|
2019-05-08 21:34:17 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public RestartCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "restart";
|
|
|
|
|
Description = _translationLookup["COMMANDS_RESTART_DESC"];
|
|
|
|
|
Alias = "res";
|
|
|
|
|
Permission = Permission.Owner;
|
|
|
|
|
RequiresTarget = false;
|
|
|
|
|
}
|
2019-05-08 21:34:17 -04:00
|
|
|
|
|
|
|
|
|
public override Task ExecuteAsync(GameEvent E)
|
|
|
|
|
{
|
|
|
|
|
E.Owner.Manager.Restart();
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_RESTART_SUCCESS"]);
|
2019-05-08 21:34:17 -04:00
|
|
|
|
return Task.CompletedTask;
|
2017-05-26 18:49:27 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Claims ownership of the server
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class OwnerCommand : Command
|
2017-08-17 19:28:08 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public OwnerCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "owner";
|
|
|
|
|
Description = _translationLookup["COMMANDS_OWNER_DESC"];
|
|
|
|
|
Alias = "iamgod";
|
|
|
|
|
Permission = Permission.User;
|
|
|
|
|
RequiresTarget = false;
|
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
|
2018-04-13 02:32:30 -04:00
|
|
|
|
public override async Task ExecuteAsync(GameEvent E)
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2020-05-16 12:54:01 -04:00
|
|
|
|
// they're trying to set the console's permission level... sigh...
|
|
|
|
|
if (E.Origin.Level == Permission.Console)
|
|
|
|
|
{
|
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_OWNER_IDIOT"]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-26 11:32:16 -05:00
|
|
|
|
if (await E.Owner.Manager.GetClientService().GetOwnerCount() == 0 &&
|
|
|
|
|
!E.Origin.SetLevel(Permission.Owner, Utilities.IW4MAdminClient(E.Owner)).Failed)
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_OWNER_SUCCESS"]);
|
2015-03-08 17:20:10 -04:00
|
|
|
|
}
|
|
|
|
|
else
|
2018-09-29 15:52:22 -04:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_OWNER_FAIL"]);
|
2018-09-29 15:52:22 -04:00
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Warns given client for reason
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class WarnCommand : Command
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2020-11-18 19:48:24 -05:00
|
|
|
|
private readonly ApplicationConfiguration _appConfig;
|
2022-01-26 11:32:16 -05:00
|
|
|
|
|
|
|
|
|
public WarnCommand(ApplicationConfiguration appConfig, CommandConfiguration config,
|
|
|
|
|
ITranslationLookup translationLookup) : base(config, translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "warn";
|
|
|
|
|
Description = _translationLookup["COMMANDS_WARN_DESC"];
|
|
|
|
|
Alias = "w";
|
|
|
|
|
Permission = Permission.Trusted;
|
|
|
|
|
RequiresTarget = true;
|
|
|
|
|
Arguments = new[]
|
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2017-11-15 16:04:13 -05:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_PLAYER"],
|
|
|
|
|
Required = true
|
|
|
|
|
},
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_REASON"],
|
|
|
|
|
Required = true
|
|
|
|
|
}
|
|
|
|
|
};
|
2020-11-18 19:48:24 -05:00
|
|
|
|
_appConfig = appConfig;
|
2020-01-26 19:06:50 -05:00
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
|
2020-11-18 19:48:24 -05:00
|
|
|
|
public override Task ExecuteAsync(GameEvent gameEvent)
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2020-11-18 19:48:24 -05:00
|
|
|
|
var reason = gameEvent.Data.FindRuleForReason(_appConfig, gameEvent.Owner);
|
|
|
|
|
if (gameEvent.Target.Warn(reason, gameEvent.Origin).Failed)
|
2018-09-02 22:25:09 -04:00
|
|
|
|
{
|
2020-11-18 19:48:24 -05:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["COMMANDS_WARN_FAIL"].FormatExt(gameEvent.Target.Name));
|
2018-09-02 22:25:09 -04:00
|
|
|
|
}
|
2018-09-29 22:49:12 -04:00
|
|
|
|
|
|
|
|
|
return Task.CompletedTask;
|
2015-03-08 17:20:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Clears all warnings for given client
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class WarnClearCommand : Command
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public WarnClearCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "warnclear";
|
|
|
|
|
Description = _translationLookup["COMMANDS_WARNCLEAR_DESC"];
|
|
|
|
|
Alias = "wc";
|
|
|
|
|
Permission = Permission.Trusted;
|
|
|
|
|
RequiresTarget = true;
|
|
|
|
|
Arguments = new[]
|
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2017-11-15 16:04:13 -05:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_PLAYER"],
|
|
|
|
|
Required = true
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
|
2018-09-29 22:49:12 -04:00
|
|
|
|
public override Task ExecuteAsync(GameEvent E)
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2018-09-29 22:49:12 -04:00
|
|
|
|
if (!E.Target.WarnClear(E.Origin).Failed)
|
2018-09-29 15:52:22 -04:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Owner.Broadcast(_translationLookup["COMMANDS_WARNCLEAR_SUCCESS"].FormatExt(E.Target.Name));
|
2018-09-29 15:52:22 -04:00
|
|
|
|
}
|
2018-09-29 22:49:12 -04:00
|
|
|
|
|
|
|
|
|
return Task.CompletedTask;
|
2015-03-08 17:20:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Kicks client for given reason
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class KickCommand : Command
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2020-11-18 19:48:24 -05:00
|
|
|
|
private readonly ApplicationConfiguration _appConfig;
|
2022-01-26 11:32:16 -05:00
|
|
|
|
|
|
|
|
|
public KickCommand(ApplicationConfiguration appConfig, CommandConfiguration config,
|
|
|
|
|
ITranslationLookup translationLookup) : base(config, translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "kick";
|
|
|
|
|
Description = _translationLookup["COMMANDS_KICK_DESC"];
|
|
|
|
|
Alias = "k";
|
|
|
|
|
Permission = Permission.Moderator;
|
|
|
|
|
RequiresTarget = true;
|
|
|
|
|
Arguments = new[]
|
2017-11-15 16:04:13 -05:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2017-11-15 16:04:13 -05:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_PLAYER"],
|
2017-11-15 16:04:13 -05:00
|
|
|
|
Required = true
|
|
|
|
|
},
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2017-11-15 16:04:13 -05:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_REASON"],
|
2018-04-24 18:01:27 -04:00
|
|
|
|
Required = true
|
2017-11-15 16:04:13 -05:00
|
|
|
|
}
|
2020-01-26 19:06:50 -05:00
|
|
|
|
};
|
2020-11-18 19:48:24 -05:00
|
|
|
|
_appConfig = appConfig;
|
2020-01-26 19:06:50 -05:00
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
|
2020-11-18 19:48:24 -05:00
|
|
|
|
public override async Task ExecuteAsync(GameEvent gameEvent)
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2020-11-18 19:48:24 -05:00
|
|
|
|
var reason = gameEvent.Data.FindRuleForReason(_appConfig, gameEvent.Owner);
|
2022-01-26 11:32:16 -05:00
|
|
|
|
switch ((await gameEvent.Target.Kick(reason, gameEvent.Origin).WaitAsync(Utilities.DefaultCommandTimeout,
|
|
|
|
|
gameEvent.Owner.Manager.CancellationToken)).FailReason)
|
2019-05-08 21:34:17 -04:00
|
|
|
|
{
|
|
|
|
|
case GameEvent.EventFailReason.None:
|
2020-11-18 19:48:24 -05:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["COMMANDS_KICK_SUCCESS"].FormatExt(gameEvent.Target.Name));
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
|
|
|
|
case GameEvent.EventFailReason.Exception:
|
2020-11-18 19:48:24 -05:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]);
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2020-11-18 19:48:24 -05:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["COMMANDS_KICK_FAIL"].FormatExt(gameEvent.Target.Name));
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Temporarily bans a client
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class TempBanCommand : Command
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
private static readonly string TempBanRegex = @"([0-9]+\w+)\ (.+)";
|
2020-11-18 19:48:24 -05:00
|
|
|
|
private readonly ApplicationConfiguration _appConfig;
|
2022-01-26 11:32:16 -05:00
|
|
|
|
|
|
|
|
|
public TempBanCommand(ApplicationConfiguration appConfig, CommandConfiguration config,
|
|
|
|
|
ITranslationLookup translationLookup) : base(config, translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "tempban";
|
|
|
|
|
Description = _translationLookup["COMMANDS_TEMPBAN_DESC"];
|
|
|
|
|
Alias = "tb";
|
|
|
|
|
Permission = Permission.Administrator;
|
|
|
|
|
RequiresTarget = true;
|
|
|
|
|
Arguments = new[]
|
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2017-11-15 16:04:13 -05:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_PLAYER"],
|
|
|
|
|
Required = true
|
|
|
|
|
},
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_DURATION"],
|
2022-01-26 11:32:16 -05:00
|
|
|
|
Required = true
|
2020-01-26 19:06:50 -05:00
|
|
|
|
},
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_REASON"],
|
|
|
|
|
Required = true
|
|
|
|
|
}
|
|
|
|
|
};
|
2020-11-18 19:48:24 -05:00
|
|
|
|
_appConfig = appConfig;
|
2020-01-26 19:06:50 -05:00
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
|
2020-11-18 19:48:24 -05:00
|
|
|
|
public override async Task ExecuteAsync(GameEvent gameEvent)
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2020-11-18 19:48:24 -05:00
|
|
|
|
var match = Regex.Match(gameEvent.Data, TempBanRegex);
|
2018-10-02 13:39:08 -04:00
|
|
|
|
if (match.Success)
|
|
|
|
|
{
|
2020-11-18 19:48:24 -05:00
|
|
|
|
var tempbanReason = match.Groups[2].ToString().FindRuleForReason(_appConfig, gameEvent.Owner);
|
2018-10-02 13:39:08 -04:00
|
|
|
|
var length = match.Groups[1].ToString().ParseTimespan();
|
|
|
|
|
|
2020-11-18 19:48:24 -05:00
|
|
|
|
if (length > gameEvent.Owner.Manager.GetApplicationSettings().Configuration().MaximumTempBanTime)
|
2018-10-15 20:51:04 -04:00
|
|
|
|
{
|
2020-11-18 19:48:24 -05:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["COMMANDS_TEMPBAN_FAIL_TOOLONG"]);
|
2018-10-15 20:51:04 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
switch ((await gameEvent.Target.TempBan(tempbanReason, length, gameEvent.Origin)
|
|
|
|
|
.WaitAsync(Utilities.DefaultCommandTimeout, gameEvent.Owner.Manager.CancellationToken))
|
|
|
|
|
.FailReason)
|
2019-05-08 21:34:17 -04:00
|
|
|
|
{
|
|
|
|
|
case GameEvent.EventFailReason.None:
|
2022-01-26 11:32:16 -05:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["COMMANDS_TEMPBAN_SUCCESS"]
|
|
|
|
|
.FormatExt(gameEvent.Target, length.HumanizeForCurrentCulture()));
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
|
|
|
|
case GameEvent.EventFailReason.Exception:
|
2020-11-18 19:48:24 -05:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]);
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2022-01-26 11:32:16 -05:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["COMMANDS_TEMPBAN_FAIL"]
|
|
|
|
|
.FormatExt(gameEvent.Target.Name));
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
|
|
|
|
}
|
2018-10-15 20:51:04 -04:00
|
|
|
|
}
|
2018-10-02 13:39:08 -04:00
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Permanently bans a client
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class BanCommand : Command
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2020-11-18 19:48:24 -05:00
|
|
|
|
private readonly ApplicationConfiguration _appConfig;
|
2022-01-26 11:32:16 -05:00
|
|
|
|
|
|
|
|
|
public BanCommand(ApplicationConfiguration appConfig, CommandConfiguration config,
|
|
|
|
|
ITranslationLookup translationLookup) : base(config, translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "ban";
|
|
|
|
|
Description = _translationLookup["COMMANDS_BAN_DESC"];
|
|
|
|
|
Alias = "b";
|
|
|
|
|
Permission = Permission.SeniorAdmin;
|
|
|
|
|
RequiresTarget = true;
|
|
|
|
|
Arguments = new[]
|
2017-11-15 16:04:13 -05:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2017-11-15 16:04:13 -05:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_PLAYER"],
|
2017-11-15 16:04:13 -05:00
|
|
|
|
Required = true
|
|
|
|
|
},
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2017-11-15 16:04:13 -05:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_REASON"],
|
2017-11-16 18:09:19 -05:00
|
|
|
|
Required = true
|
2017-11-15 16:04:13 -05:00
|
|
|
|
}
|
2020-01-26 19:06:50 -05:00
|
|
|
|
};
|
2020-11-18 19:48:24 -05:00
|
|
|
|
_appConfig = appConfig;
|
2020-01-26 19:06:50 -05:00
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
|
2020-11-18 19:48:24 -05:00
|
|
|
|
public override async Task ExecuteAsync(GameEvent gameEvent)
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2020-11-18 19:48:24 -05:00
|
|
|
|
var reason = gameEvent.Data.FindRuleForReason(_appConfig, gameEvent.Owner);
|
2022-01-26 11:32:16 -05:00
|
|
|
|
switch ((await gameEvent.Target.Ban(reason, gameEvent.Origin, false)
|
|
|
|
|
.WaitAsync(Utilities.DefaultCommandTimeout, gameEvent.Owner.Manager.CancellationToken))
|
|
|
|
|
.FailReason)
|
2019-05-08 21:34:17 -04:00
|
|
|
|
{
|
|
|
|
|
case GameEvent.EventFailReason.None:
|
2020-11-18 19:48:24 -05:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["COMMANDS_BAN_SUCCESS"].FormatExt(gameEvent.Target.Name));
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
|
|
|
|
case GameEvent.EventFailReason.Exception:
|
2020-11-18 19:48:24 -05:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]);
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2020-11-18 19:48:24 -05:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["COMMANDS_BAN_FAIL"].FormatExt(gameEvent.Target.Name));
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Unbans a banned client
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class UnbanCommand : Command
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public UnbanCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "unban";
|
|
|
|
|
Description = _translationLookup["COMMANDS_UNBAN_DESC"];
|
|
|
|
|
Alias = "ub";
|
|
|
|
|
Permission = Permission.SeniorAdmin;
|
|
|
|
|
RequiresTarget = true;
|
|
|
|
|
Arguments = new[]
|
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2017-11-15 16:04:13 -05:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_CLIENTID"],
|
2022-01-26 11:32:16 -05:00
|
|
|
|
Required = true
|
2020-01-26 19:06:50 -05:00
|
|
|
|
},
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_REASON"],
|
2022-01-26 11:32:16 -05:00
|
|
|
|
Required = true
|
2020-01-26 19:06:50 -05:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
|
2022-02-22 18:09:50 -05:00
|
|
|
|
public override async Task ExecuteAsync(GameEvent gameEvent)
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2019-05-08 21:34:17 -04:00
|
|
|
|
// todo: don't do the lookup here
|
2022-02-22 18:09:50 -05:00
|
|
|
|
var penalties = await gameEvent.Owner.Manager.GetPenaltyService().GetActivePenaltiesAsync(gameEvent.Target.AliasLinkId,
|
|
|
|
|
gameEvent.Target.CurrentAliasId, gameEvent.Target.NetworkId, gameEvent.Target.CurrentAlias.IPAddress);
|
|
|
|
|
|
2022-01-28 16:33:21 -05:00
|
|
|
|
if (penalties
|
|
|
|
|
.FirstOrDefault(p =>
|
|
|
|
|
p.Type == EFPenalty.PenaltyType.Ban || p.Type == EFPenalty.PenaltyType.TempBan) != null)
|
2018-02-17 01:13:38 -05:00
|
|
|
|
{
|
2022-02-22 18:09:50 -05:00
|
|
|
|
switch ((await gameEvent.Target.Unban(gameEvent.Data, gameEvent.Origin)
|
|
|
|
|
.WaitAsync(Utilities.DefaultCommandTimeout, gameEvent.Owner.Manager.CancellationToken)).FailReason)
|
2019-05-08 21:34:17 -04:00
|
|
|
|
{
|
|
|
|
|
case GameEvent.EventFailReason.None:
|
2022-02-22 18:09:50 -05:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["COMMANDS_UNBAN_SUCCESS"].FormatExt(gameEvent.Target));
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2022-02-22 18:09:50 -05:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]);
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
|
|
|
|
}
|
2018-02-17 01:13:38 -05:00
|
|
|
|
}
|
2019-05-08 21:34:17 -04:00
|
|
|
|
|
2018-02-17 01:13:38 -05:00
|
|
|
|
else
|
|
|
|
|
{
|
2022-02-22 18:09:50 -05:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["COMMANDS_UNBAN_FAIL"].FormatExt(gameEvent.Target));
|
2018-02-17 01:13:38 -05:00
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Fast restarts the map
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class FastRestartCommand : Command
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public FastRestartCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "fastrestart";
|
|
|
|
|
Description = _translationLookup["COMMANDS_FASTRESTART_DESC"];
|
|
|
|
|
Alias = "fr";
|
|
|
|
|
Permission = Permission.Moderator;
|
|
|
|
|
RequiresTarget = false;
|
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
|
2018-04-13 02:32:30 -04:00
|
|
|
|
public override async Task ExecuteAsync(GameEvent E)
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2018-02-15 23:01:28 -05:00
|
|
|
|
await E.Owner.ExecuteCommandAsync("fast_restart");
|
|
|
|
|
|
2022-01-26 11:32:16 -05:00
|
|
|
|
var _ = !E.Origin.Masked
|
|
|
|
|
? E.Owner.Broadcast(
|
|
|
|
|
$"(Color::Accent){E.Origin.Name} (Color::White){_translationLookup["COMMANDS_FASTRESTART_UNMASKED"]}")
|
|
|
|
|
: E.Owner.Broadcast(_translationLookup["COMMANDS_FASTRESTART_MASKED"]);
|
2015-03-08 17:20:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Cycles to the next map in rotation
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class MapRotateCommand : Command
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public MapRotateCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "maprotate";
|
|
|
|
|
Description = _translationLookup["COMMANDS_MAPROTATE_DESC"];
|
|
|
|
|
Alias = "mr";
|
|
|
|
|
Permission = Permission.Administrator;
|
|
|
|
|
RequiresTarget = false;
|
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
|
2018-04-13 02:32:30 -04:00
|
|
|
|
public override async Task ExecuteAsync(GameEvent E)
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
_ = !E.Origin.Masked
|
|
|
|
|
? E.Owner.Broadcast(
|
|
|
|
|
$"{_translationLookup["COMMANDS_MAPROTATE"]} [(Color::Accent){E.Origin.Name}(Color::White)]",
|
|
|
|
|
E.Origin)
|
|
|
|
|
: E.Owner.Broadcast(_translationLookup["COMMANDS_MAPROTATE"], E.Origin);
|
2018-09-29 15:52:22 -04:00
|
|
|
|
|
2020-10-17 11:47:56 -04:00
|
|
|
|
await Task.Delay(E.Owner.Manager.GetApplicationSettings().Configuration().MapChangeDelaySeconds * 1000);
|
2017-05-26 18:49:27 -04:00
|
|
|
|
await E.Owner.ExecuteCommandAsync("map_rotate");
|
2015-03-08 17:20:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Sets the level of given client
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class SetLevelCommand : Command
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public SetLevelCommand(CommandConfiguration config, ITranslationLookup translationLookup,
|
|
|
|
|
ILogger<SetLevelCommand> logger) : base(config, translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "setlevel";
|
|
|
|
|
Description = _translationLookup["COMMANDS_SETLEVEL_DESC"];
|
|
|
|
|
Alias = "sl";
|
|
|
|
|
Permission = Permission.Moderator;
|
|
|
|
|
RequiresTarget = true;
|
|
|
|
|
Arguments = new[]
|
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
|
|
|
|
{
|
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_PLAYER"],
|
|
|
|
|
Required = true
|
|
|
|
|
},
|
|
|
|
|
new CommandArgument
|
|
|
|
|
{
|
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_LEVEL"],
|
|
|
|
|
Required = true
|
|
|
|
|
}
|
2020-01-26 19:06:50 -05:00
|
|
|
|
};
|
2020-05-16 12:54:01 -04:00
|
|
|
|
this.logger = logger;
|
2020-01-26 19:06:50 -05:00
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
|
2020-05-16 12:54:01 -04:00
|
|
|
|
public override async Task ExecuteAsync(GameEvent gameEvent)
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
var oldPerm = gameEvent.Target.Level;
|
|
|
|
|
var newPerm = Utilities.MatchPermission(gameEvent.Data);
|
|
|
|
|
var allowMultiOwner = gameEvent.Owner.Manager.GetApplicationSettings().Configuration().EnableMultipleOwners;
|
|
|
|
|
var steppedPrivileges =
|
|
|
|
|
gameEvent.Owner.Manager.GetApplicationSettings().Configuration().EnableSteppedHierarchy;
|
2020-05-16 12:54:01 -04:00
|
|
|
|
var targetClient = gameEvent.Target;
|
|
|
|
|
|
|
|
|
|
// pre setup logic
|
2022-01-26 11:32:16 -05:00
|
|
|
|
var canPromoteSteppedPriv = gameEvent.Origin.Level > newPerm || gameEvent.Origin.Level == Permission.Owner;
|
|
|
|
|
var hasOwner = await gameEvent.Owner.Manager.GetClientService().GetOwnerCount() > 0;
|
2020-05-16 12:54:01 -04:00
|
|
|
|
|
|
|
|
|
// trying to set self
|
|
|
|
|
if (gameEvent.Target == gameEvent.Origin)
|
|
|
|
|
{
|
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_SELF"]);
|
|
|
|
|
}
|
2019-03-24 22:34:20 -04:00
|
|
|
|
|
2020-05-16 12:54:01 -04:00
|
|
|
|
// origin permission not high enough
|
|
|
|
|
else if (gameEvent.Origin.Level < gameEvent.Target.Level)
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_PERMISSION"]
|
|
|
|
|
.FormatExt(gameEvent.Target.Name));
|
2015-03-08 17:20:10 -04:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-16 12:54:01 -04:00
|
|
|
|
// trying to set owner without enabling multiple owners
|
|
|
|
|
else if (newPerm == Permission.Owner && !allowMultiOwner && hasOwner)
|
2017-06-19 13:58:01 -04:00
|
|
|
|
{
|
2019-03-24 22:34:20 -04:00
|
|
|
|
// only one owner is allowed
|
2020-05-16 12:54:01 -04:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_OWNER"]);
|
2017-06-19 13:58:01 -04:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-16 12:54:01 -04:00
|
|
|
|
// trying to set level when only owner is allowed to
|
|
|
|
|
else if (gameEvent.Origin.Level < Permission.Owner && !steppedPrivileges)
|
2018-03-24 17:35:54 -04:00
|
|
|
|
{
|
2019-03-24 22:34:20 -04:00
|
|
|
|
// only the owner is allowed to set levels
|
2022-01-26 11:32:16 -05:00
|
|
|
|
gameEvent.Origin.Tell(
|
|
|
|
|
$"{_translationLookup["COMMANDS_SETLEVEL_STEPPEDDISABLED"]} (Color::White){gameEvent.Target.Name}");
|
2018-03-24 17:35:54 -04:00
|
|
|
|
}
|
2022-01-26 11:32:16 -05:00
|
|
|
|
|
2020-12-16 14:11:30 -05:00
|
|
|
|
else if (gameEvent.Target.Level == Permission.Flagged)
|
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_FLAGGED"]
|
|
|
|
|
.FormatExt(gameEvent.Target.Name + "(Color::White)"));
|
2020-12-16 14:11:30 -05:00
|
|
|
|
}
|
2018-03-24 17:35:54 -04:00
|
|
|
|
|
2020-05-16 12:54:01 -04:00
|
|
|
|
// stepped privilege is enabled, but the new level is too high
|
|
|
|
|
else if (steppedPrivileges && !canPromoteSteppedPriv)
|
2018-03-24 17:35:54 -04:00
|
|
|
|
{
|
2019-03-24 22:34:20 -04:00
|
|
|
|
// can't promote a client to higher than your current perms
|
2019-08-08 16:58:23 -04:00
|
|
|
|
// or your peer
|
2021-11-23 18:26:33 -05:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_LEVELTOOHIGH_V2"]
|
|
|
|
|
.FormatExt(gameEvent.Target.Name, (gameEvent.Origin.Level - 1).ToLocalizedLevelName()));
|
2018-03-24 17:35:54 -04:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-16 12:54:01 -04:00
|
|
|
|
// valid
|
2019-08-08 16:58:23 -04:00
|
|
|
|
else if (newPerm > Permission.Banned)
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
targetClient = targetClient.ClientNumber < 0
|
|
|
|
|
? gameEvent.Owner.Manager.GetActiveClients()
|
|
|
|
|
.FirstOrDefault(c => c.ClientId == targetClient?.ClientId) ?? targetClient
|
|
|
|
|
: targetClient;
|
2017-06-12 13:50:00 -04:00
|
|
|
|
|
2022-01-26 11:32:16 -05:00
|
|
|
|
logger.LogDebug("Beginning set level of client {origin} to {newPermission}",
|
|
|
|
|
gameEvent.Origin.ToString(), newPerm);
|
2018-10-15 20:51:04 -04:00
|
|
|
|
|
2022-01-26 11:32:16 -05:00
|
|
|
|
var result = await targetClient.SetLevel(newPerm, gameEvent.Origin)
|
|
|
|
|
.WaitAsync(Utilities.DefaultCommandTimeout, gameEvent.Owner.Manager.CancellationToken);
|
2020-05-16 12:54:01 -04:00
|
|
|
|
|
|
|
|
|
if (result.Failed)
|
|
|
|
|
{
|
2020-12-16 14:11:30 -05:00
|
|
|
|
// user is the same level
|
|
|
|
|
if (result.FailReason == GameEvent.EventFailReason.Invalid)
|
|
|
|
|
{
|
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_INVALID"]
|
2021-11-23 18:26:33 -05:00
|
|
|
|
.FormatExt(gameEvent.Target.Name + "(Color::White)", newPerm.ToString()));
|
2020-12-16 14:11:30 -05:00
|
|
|
|
return;
|
|
|
|
|
}
|
2022-01-26 11:32:16 -05:00
|
|
|
|
|
2020-11-11 18:31:26 -05:00
|
|
|
|
using (LogContext.PushProperty("Server", gameEvent.Origin.CurrentServer?.ToString()))
|
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
logger.LogWarning("Failed to set level of client {origin} {reason}",
|
|
|
|
|
gameEvent.Origin.ToString(),
|
2020-12-16 14:11:30 -05:00
|
|
|
|
result.FailReason);
|
2020-11-11 18:31:26 -05:00
|
|
|
|
}
|
2022-01-26 11:32:16 -05:00
|
|
|
|
|
2020-05-16 12:54:01 -04:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]);
|
|
|
|
|
return;
|
2018-02-24 00:56:03 -05:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-16 12:54:01 -04:00
|
|
|
|
// inform the client that they were promoted
|
|
|
|
|
// we don't really want to tell them if they're demoted haha
|
|
|
|
|
if (targetClient.IsIngame && newPerm > oldPerm)
|
2018-02-24 00:56:03 -05:00
|
|
|
|
{
|
2020-05-16 12:54:01 -04:00
|
|
|
|
targetClient.Tell(_translationLookup["COMMANDS_SETLEVEL_SUCCESS_TARGET"].FormatExt(newPerm));
|
2018-02-24 00:56:03 -05:00
|
|
|
|
}
|
2017-06-19 13:58:01 -04:00
|
|
|
|
|
2019-03-24 22:34:20 -04:00
|
|
|
|
// inform the origin that the client has been updated
|
2022-01-26 11:32:16 -05:00
|
|
|
|
_ = newPerm < oldPerm
|
|
|
|
|
? gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_DEMOTE_SUCCESS"]
|
|
|
|
|
.FormatExt(targetClient.Name))
|
|
|
|
|
: gameEvent.Origin.Tell(
|
|
|
|
|
_translationLookup["COMMANDS_SETLEVEL_SUCCESS"].FormatExt(targetClient.Name));
|
2015-03-08 17:20:10 -04:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-16 12:54:01 -04:00
|
|
|
|
// all other tests failed so it's invalid group
|
2015-03-08 17:20:10 -04:00
|
|
|
|
else
|
2018-09-29 15:52:22 -04:00
|
|
|
|
{
|
2020-05-16 12:54:01 -04:00
|
|
|
|
gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_FAIL"]);
|
2018-09-29 15:52:22 -04:00
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Prints the amount of memory IW4MAdmin is using
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class MemoryUsageCommand : Command
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public MemoryUsageCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "usage";
|
|
|
|
|
Description = _translationLookup["COMMANDS_USAGE_DESC"];
|
|
|
|
|
Alias = "us";
|
|
|
|
|
Permission = Permission.Moderator;
|
|
|
|
|
RequiresTarget = false;
|
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
|
2018-09-29 15:52:22 -04:00
|
|
|
|
public override Task ExecuteAsync(GameEvent E)
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_USAGE_TEXT"]
|
|
|
|
|
.FormatExt(Math.Round(Process.GetCurrentProcess().PrivateMemorySize64 / 2048f / 1200f, 1)));
|
2018-09-29 15:52:22 -04:00
|
|
|
|
return Task.CompletedTask;
|
2015-03-08 17:20:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Prints out how long IW4MAdmin has been running
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class UptimeCommand : Command
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public UptimeCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "uptime";
|
|
|
|
|
Description = _translationLookup["COMMANDS_UPTIME_DESC"];
|
|
|
|
|
Alias = "up";
|
|
|
|
|
Permission = Permission.Moderator;
|
|
|
|
|
RequiresTarget = false;
|
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
|
2018-09-29 15:52:22 -04:00
|
|
|
|
public override Task ExecuteAsync(GameEvent E)
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
var uptime = DateTime.Now - Process.GetCurrentProcess().StartTime;
|
2020-01-26 19:06:50 -05:00
|
|
|
|
var loc = _translationLookup;
|
2021-01-08 20:21:23 -05:00
|
|
|
|
E.Origin.Tell(loc["COMMANDS_UPTIME_TEXT"].FormatExt(uptime.HumanizeForCurrentCulture(4)));
|
2018-09-29 15:52:22 -04:00
|
|
|
|
return Task.CompletedTask;
|
2015-03-08 17:20:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Attempts to load the specified map
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class LoadMapCommand : Command
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public LoadMapCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "map";
|
|
|
|
|
Description = _translationLookup["COMMANDS_MAP_DESC"];
|
|
|
|
|
Alias = "m";
|
|
|
|
|
Permission = Permission.Administrator;
|
|
|
|
|
RequiresTarget = false;
|
|
|
|
|
Arguments = new[]
|
2017-11-15 16:04:13 -05:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
|
|
|
|
{
|
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_MAP"],
|
|
|
|
|
Required = true
|
|
|
|
|
}
|
2020-01-26 19:06:50 -05:00
|
|
|
|
};
|
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
|
2018-04-13 02:32:30 -04:00
|
|
|
|
public override async Task ExecuteAsync(GameEvent E)
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
var newMap = E.Data.Trim();
|
|
|
|
|
var delay = E.Owner.Manager.GetApplicationSettings().Configuration().MapChangeDelaySeconds * 1000;
|
2020-10-17 11:47:56 -04:00
|
|
|
|
|
2022-01-26 11:32:16 -05:00
|
|
|
|
var foundMap = E.Owner.Maps.FirstOrDefault(_map =>
|
|
|
|
|
_map.Name.Equals(newMap, StringComparison.InvariantCultureIgnoreCase) ||
|
|
|
|
|
_map.Alias.Equals(newMap, StringComparison.InvariantCultureIgnoreCase));
|
2020-10-17 11:47:56 -04:00
|
|
|
|
|
2022-01-26 11:32:16 -05:00
|
|
|
|
_ = foundMap == null
|
|
|
|
|
? E.Owner.Broadcast(_translationLookup["COMMANDS_MAP_UKN"].FormatExt(newMap))
|
|
|
|
|
: E.Owner.Broadcast(_translationLookup["COMMANDS_MAP_SUCCESS"].FormatExt(foundMap.Alias));
|
2015-03-08 17:20:10 -04:00
|
|
|
|
|
2020-10-17 11:47:56 -04:00
|
|
|
|
await Task.Delay(delay);
|
2020-11-03 21:04:11 -05:00
|
|
|
|
await E.Owner.LoadMap(foundMap?.Name ?? newMap);
|
2015-03-08 17:20:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Lists server and global rules
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class ListRulesCommands : Command
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public ListRulesCommands(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "rules";
|
|
|
|
|
Description = _translationLookup["COMMANDS_RULES_DESC"];
|
|
|
|
|
Alias = "r";
|
|
|
|
|
Permission = Permission.User;
|
|
|
|
|
RequiresTarget = false;
|
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
|
2022-03-23 12:38:09 -04:00
|
|
|
|
public override async Task ExecuteAsync(GameEvent gameEvent)
|
2015-03-08 17:20:10 -04:00
|
|
|
|
{
|
2022-03-23 12:38:09 -04:00
|
|
|
|
if (gameEvent.Owner.Manager.GetApplicationSettings().Configuration().GlobalRules?.Length < 1 &&
|
|
|
|
|
gameEvent.Owner.ServerConfig.Rules?.Length < 1)
|
2017-05-31 01:31:56 -04:00
|
|
|
|
{
|
2022-03-23 12:38:09 -04:00
|
|
|
|
var _ = gameEvent.Message.IsBroadcastCommand(_config.BroadcastCommandPrefix)
|
|
|
|
|
? gameEvent.Owner.Broadcast(_translationLookup["COMMANDS_RULES_NONE"])
|
|
|
|
|
: gameEvent.Origin.Tell(_translationLookup["COMMANDS_RULES_NONE"]);
|
2017-05-31 01:31:56 -04:00
|
|
|
|
}
|
|
|
|
|
|
2015-03-08 17:20:10 -04:00
|
|
|
|
else
|
|
|
|
|
{
|
2018-03-18 22:25:11 -04:00
|
|
|
|
var rules = new List<string>();
|
2022-03-23 12:38:09 -04:00
|
|
|
|
rules.AddRange(gameEvent.Owner.Manager.GetApplicationSettings().Configuration().GlobalRules);
|
|
|
|
|
if (gameEvent.Owner.ServerConfig.Rules != null)
|
2018-11-05 22:01:29 -05:00
|
|
|
|
{
|
2022-03-23 12:38:09 -04:00
|
|
|
|
rules.AddRange(gameEvent.Owner.ServerConfig.Rules);
|
2018-11-05 22:01:29 -05:00
|
|
|
|
}
|
2018-03-18 22:25:11 -04:00
|
|
|
|
|
2022-03-23 12:38:09 -04:00
|
|
|
|
var ruleFormat = rules.Select(r => $"- {r}");
|
|
|
|
|
if (gameEvent.Message.IsBroadcastCommand(_config.BroadcastCommandPrefix))
|
2021-01-24 12:47:19 -05:00
|
|
|
|
{
|
2022-03-24 12:34:32 -04:00
|
|
|
|
await gameEvent.Owner.BroadcastAsync(ruleFormat, token: gameEvent.Owner.Manager.CancellationToken);
|
2021-01-24 12:47:19 -05:00
|
|
|
|
}
|
|
|
|
|
else
|
2017-05-31 01:31:56 -04:00
|
|
|
|
{
|
2022-03-23 12:38:09 -04:00
|
|
|
|
await gameEvent.Origin.TellAsync(ruleFormat, gameEvent.Owner.Manager.CancellationToken);
|
2017-05-31 01:31:56 -04:00
|
|
|
|
}
|
2015-03-08 17:20:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-03-09 16:11:09 -04:00
|
|
|
|
|
2015-03-09 21:28:37 -04:00
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Flag given client for specified reason
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class FlagClientCommand : Command
|
2015-03-23 23:01:05 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public FlagClientCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "flag";
|
|
|
|
|
Description = _translationLookup["COMMANDS_FLAG_DESC"];
|
|
|
|
|
Alias = "fp";
|
|
|
|
|
Permission = Permission.Moderator;
|
|
|
|
|
RequiresTarget = true;
|
|
|
|
|
Arguments = new[]
|
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2017-11-15 16:04:13 -05:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_PLAYER"],
|
|
|
|
|
Required = true
|
|
|
|
|
},
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_REASON"],
|
|
|
|
|
Required = true
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
2015-03-23 23:01:05 -04:00
|
|
|
|
|
2019-05-08 21:34:17 -04:00
|
|
|
|
public override async Task ExecuteAsync(GameEvent E)
|
2015-03-23 23:01:05 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
switch ((await E.Target.Flag(E.Data, E.Origin)
|
|
|
|
|
.WaitAsync(Utilities.DefaultCommandTimeout, E.Owner.Manager.CancellationToken)).FailReason)
|
2015-03-23 23:01:05 -04:00
|
|
|
|
{
|
2019-05-08 21:34:17 -04:00
|
|
|
|
case GameEvent.EventFailReason.Permission:
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_FLAG_FAIL"].FormatExt(E.Target.Name));
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
|
|
|
|
case GameEvent.EventFailReason.Invalid:
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell($"{_translationLookup["COMMANDS_FLAG_ALREADYFLAGGED"]}");
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
|
|
|
|
case GameEvent.EventFailReason.None:
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_FLAG_SUCCESS"].FormatExt(E.Target.Name));
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]);
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
2015-03-23 23:01:05 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Unflag given client for specified reason
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class UnflagClientCommand : Command
|
2018-05-08 00:58:46 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public UnflagClientCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "unflag";
|
|
|
|
|
Description = _translationLookup["COMMANDS_UNFLAG_DESC"];
|
|
|
|
|
Alias = "uf";
|
|
|
|
|
Permission = Permission.Moderator;
|
|
|
|
|
RequiresTarget = true;
|
|
|
|
|
Arguments = new[]
|
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2018-05-08 00:58:46 -04:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_PLAYER"],
|
|
|
|
|
Required = true
|
|
|
|
|
},
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_REASON"],
|
|
|
|
|
Required = true
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
2018-05-08 00:58:46 -04:00
|
|
|
|
|
2019-05-08 21:34:17 -04:00
|
|
|
|
public override async Task ExecuteAsync(GameEvent E)
|
2018-05-08 00:58:46 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
switch ((await E.Target.Unflag(E.Data, E.Origin)
|
|
|
|
|
.WaitAsync(Utilities.DefaultCommandTimeout, E.Owner.Manager.CancellationToken)).FailReason)
|
2018-05-08 00:58:46 -04:00
|
|
|
|
{
|
2019-05-08 21:34:17 -04:00
|
|
|
|
case GameEvent.EventFailReason.None:
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_FLAG_UNFLAG"].FormatExt(E.Target.Name));
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
|
|
|
|
case GameEvent.EventFailReason.Permission:
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_UNFLAG_FAIL"].FormatExt(E.Target.Name));
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
|
|
|
|
case GameEvent.EventFailReason.Invalid:
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_UNFLAG_NOTFLAGGED"]);
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]);
|
2019-05-08 21:34:17 -04:00
|
|
|
|
break;
|
2018-05-08 00:58:46 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Masks client from announcements and online admin list
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class MaskCommand : Command
|
2015-04-10 00:02:12 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public MaskCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "mask";
|
|
|
|
|
Description = _translationLookup["COMMANDS_MASK_DESC"];
|
2022-02-18 11:04:48 -05:00
|
|
|
|
Alias = "ma";
|
2022-01-26 11:32:16 -05:00
|
|
|
|
Permission = Permission.Moderator;
|
2020-01-26 19:06:50 -05:00
|
|
|
|
RequiresTarget = false;
|
|
|
|
|
}
|
2015-04-10 00:02:12 -04:00
|
|
|
|
|
2018-04-13 02:32:30 -04:00
|
|
|
|
public override async Task ExecuteAsync(GameEvent E)
|
2015-04-10 00:02:12 -04:00
|
|
|
|
{
|
|
|
|
|
if (E.Origin.Masked)
|
|
|
|
|
{
|
|
|
|
|
E.Origin.Masked = false;
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_MASK_OFF"]);
|
2015-04-10 00:02:12 -04:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
E.Origin.Masked = true;
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_MASK_ON"]);
|
2015-04-10 00:02:12 -04:00
|
|
|
|
}
|
2017-06-19 13:58:01 -04:00
|
|
|
|
|
2017-11-25 20:29:58 -05:00
|
|
|
|
await E.Owner.Manager.GetClientService().Update(E.Origin);
|
2015-04-10 00:02:12 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Lists ban information for given client
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class ListBanInfoCommand : Command
|
2015-04-10 00:02:12 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public ListBanInfoCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "baninfo";
|
|
|
|
|
Description = _translationLookup["COMMANDS_BANINFO_DESC"];
|
|
|
|
|
Alias = "bi";
|
|
|
|
|
Permission = Permission.Moderator;
|
|
|
|
|
RequiresTarget = true;
|
|
|
|
|
Arguments = new[]
|
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2017-11-15 16:04:13 -05:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_PLAYER"],
|
|
|
|
|
Required = true
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
2015-04-10 00:02:12 -04:00
|
|
|
|
|
2018-04-13 02:32:30 -04:00
|
|
|
|
public override async Task ExecuteAsync(GameEvent E)
|
2015-04-10 00:02:12 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
var existingPenalties = await E.Owner.Manager.GetPenaltyService()
|
2022-02-22 18:09:50 -05:00
|
|
|
|
.GetActivePenaltiesAsync(E.Target.AliasLinkId, E.Target.CurrentAliasId, E.Target.NetworkId, E.Target.IPAddress);
|
2019-05-29 17:55:35 -04:00
|
|
|
|
var penalty = existingPenalties.FirstOrDefault(b => b.Type > EFPenalty.PenaltyType.Kick);
|
2017-11-25 20:29:58 -05:00
|
|
|
|
|
|
|
|
|
if (penalty == null)
|
2015-04-10 00:02:12 -04:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_BANINFO_NONE"]);
|
2015-04-10 00:02:12 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-29 17:55:35 -04:00
|
|
|
|
if (penalty.Type == EFPenalty.PenaltyType.Ban)
|
2019-04-09 16:02:49 -04:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_BANINFO_SUCCESS"].FormatExt(E.Target.Name, penalty.Offense));
|
2019-04-09 16:02:49 -04:00
|
|
|
|
}
|
2018-04-22 16:04:18 -04:00
|
|
|
|
|
2019-04-09 16:02:49 -04:00
|
|
|
|
else
|
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
var remainingTime = (penalty.Expires.Value - DateTime.UtcNow).HumanizeForCurrentCulture();
|
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_BANINFO_TB_SUCCESS"]
|
|
|
|
|
.FormatExt(E.Target.Name, penalty.Offense, remainingTime));
|
2019-04-09 16:02:49 -04:00
|
|
|
|
}
|
2015-04-10 00:02:12 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Executes RCon command
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class ExecuteRConCommand : Command
|
2015-04-10 00:02:12 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public ExecuteRConCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "rcon";
|
|
|
|
|
Description = _translationLookup["COMMANDS_RCON_DESC"];
|
|
|
|
|
Alias = "rcon";
|
|
|
|
|
Permission = Permission.Owner;
|
|
|
|
|
RequiresTarget = false;
|
|
|
|
|
Arguments = new[]
|
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2017-11-15 16:04:13 -05:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_COMMANDS"],
|
|
|
|
|
Required = true
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
2015-04-10 00:02:12 -04:00
|
|
|
|
|
2018-04-13 02:32:30 -04:00
|
|
|
|
public override async Task ExecuteAsync(GameEvent E)
|
2015-04-10 00:02:12 -04:00
|
|
|
|
{
|
2021-06-07 17:58:36 -04:00
|
|
|
|
var response = await E.Owner.ExecuteCommandAsync(E.Data.Trim());
|
|
|
|
|
foreach (var item in response)
|
|
|
|
|
E.Origin.Tell(item);
|
2018-11-05 22:01:29 -05:00
|
|
|
|
|
2021-06-07 17:58:36 -04:00
|
|
|
|
if (response.Length == 0)
|
2018-11-05 22:01:29 -05:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_RCON_SUCCESS"]);
|
2018-11-05 22:01:29 -05:00
|
|
|
|
}
|
2015-04-10 00:02:12 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
2017-06-12 17:47:31 -04:00
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Lists external IP
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class ListExternalIPCommand : Command
|
2017-08-17 19:28:08 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public ListExternalIPCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "getexternalip";
|
|
|
|
|
Description = _translationLookup["COMMANDS_IP_DESC"];
|
|
|
|
|
Alias = "ip";
|
|
|
|
|
Permission = Permission.User;
|
|
|
|
|
RequiresTarget = false;
|
|
|
|
|
}
|
2017-08-17 19:28:08 -04:00
|
|
|
|
|
2018-09-29 15:52:22 -04:00
|
|
|
|
public override Task ExecuteAsync(GameEvent E)
|
2017-08-17 19:28:08 -04:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_IP_SUCCESS"].FormatExt(E.Origin.IPAddressString));
|
2018-09-29 15:52:22 -04:00
|
|
|
|
return Task.CompletedTask;
|
2017-08-17 19:28:08 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-02-10 01:26:38 -05:00
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Prunes inactive privileged clients
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class PruneAdminsCommand : Command
|
2018-02-10 01:26:38 -05:00
|
|
|
|
{
|
2020-11-27 22:52:52 -05:00
|
|
|
|
private readonly IDatabaseContextFactory _contextFactory;
|
2022-01-26 11:32:16 -05:00
|
|
|
|
|
|
|
|
|
public PruneAdminsCommand(CommandConfiguration config, ITranslationLookup translationLookup,
|
2020-11-27 22:52:52 -05:00
|
|
|
|
IDatabaseContextFactory contextFactory) : base(config, translationLookup)
|
2018-02-10 01:26:38 -05:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Name = "prune";
|
|
|
|
|
Description = _translationLookup["COMMANDS_PRUNE_DESC"];
|
|
|
|
|
Alias = "pa";
|
|
|
|
|
Permission = Permission.Owner;
|
|
|
|
|
RequiresTarget = false;
|
2021-06-03 11:52:27 -04:00
|
|
|
|
_contextFactory = contextFactory;
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Arguments = new[]
|
2018-02-10 01:26:38 -05:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_INACTIVE"],
|
|
|
|
|
Required = false
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
2018-03-06 02:22:19 -05:00
|
|
|
|
|
2018-04-13 02:32:30 -04:00
|
|
|
|
public override async Task ExecuteAsync(GameEvent E)
|
2018-02-10 01:26:38 -05:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
var inactiveDays = 30;
|
2018-02-10 01:26:38 -05:00
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (E.Data.Length > 0)
|
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
inactiveDays = int.Parse(E.Data);
|
2018-02-10 01:26:38 -05:00
|
|
|
|
if (inactiveDays < 1)
|
2018-11-05 22:01:29 -05:00
|
|
|
|
{
|
2018-02-10 01:26:38 -05:00
|
|
|
|
throw new FormatException();
|
2018-11-05 22:01:29 -05:00
|
|
|
|
}
|
2018-02-10 01:26:38 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
catch (FormatException)
|
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_PRUNE_FAIL"]);
|
2018-02-10 01:26:38 -05:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<EFClient> inactiveUsers = null;
|
2018-09-29 15:52:22 -04:00
|
|
|
|
// todo: make an event for this
|
2018-02-10 01:26:38 -05:00
|
|
|
|
// update user roles
|
2020-11-27 22:52:52 -05:00
|
|
|
|
await using var context = _contextFactory.CreateContext();
|
|
|
|
|
var lastActive = DateTime.UtcNow.AddDays(-inactiveDays);
|
|
|
|
|
inactiveUsers = await context.Clients
|
|
|
|
|
.Where(c => c.Level > Permission.Flagged && c.Level <= Permission.Moderator)
|
|
|
|
|
.Where(c => c.LastConnection < lastActive)
|
2021-03-22 12:09:25 -04:00
|
|
|
|
.Select(c => c.ToPartialClient())
|
2020-11-27 22:52:52 -05:00
|
|
|
|
.ToListAsync();
|
|
|
|
|
inactiveUsers.ForEach(c => c.SetLevel(Permission.User, E.Origin));
|
|
|
|
|
await context.SaveChangesAsync();
|
2022-01-26 11:32:16 -05:00
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_PRUNE_SUCCESS"].FormatExt(inactiveUsers.Count));
|
2018-03-06 02:22:19 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Sets login password
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class SetPasswordCommand : Command
|
2018-04-04 15:38:34 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public SetPasswordCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "setpassword";
|
|
|
|
|
Description = _translationLookup["COMMANDS_SETPASSWORD_DESC"];
|
|
|
|
|
Alias = "sp";
|
|
|
|
|
Permission = Permission.Moderator;
|
|
|
|
|
RequiresTarget = false;
|
2020-04-26 22:12:49 -04:00
|
|
|
|
AllowImpersonation = true;
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Arguments = new[]
|
2018-04-04 15:38:34 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2018-04-04 15:38:34 -04:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_PASSWORD"],
|
2018-04-04 15:38:34 -04:00
|
|
|
|
Required = true
|
|
|
|
|
}
|
2020-01-26 19:06:50 -05:00
|
|
|
|
};
|
|
|
|
|
}
|
2018-04-04 15:38:34 -04:00
|
|
|
|
|
2018-04-13 02:32:30 -04:00
|
|
|
|
public override async Task ExecuteAsync(GameEvent E)
|
2018-04-04 15:38:34 -04:00
|
|
|
|
{
|
2018-04-05 00:38:45 -04:00
|
|
|
|
if (E.Data.Length < 5)
|
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_PASSWORD_FAIL"]);
|
2018-04-05 00:38:45 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-26 11:32:16 -05:00
|
|
|
|
var hashedPassword = Hashing.Hash(E.Data);
|
2018-04-04 15:38:34 -04:00
|
|
|
|
|
|
|
|
|
E.Origin.Password = hashedPassword[0];
|
|
|
|
|
E.Origin.PasswordSalt = hashedPassword[1];
|
|
|
|
|
|
|
|
|
|
await E.Owner.Manager.GetClientService().Update(E.Origin);
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_PASSWORD_SUCCESS"]);
|
2018-04-04 15:38:34 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Gets the ping of a client
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class GetClientPingCommand : Command
|
2018-03-06 02:22:19 -05:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public GetClientPingCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2018-03-06 02:22:19 -05:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Name = "ping";
|
|
|
|
|
Description = _translationLookup["COMMANDS_PING_DESC"];
|
|
|
|
|
Alias = "pi";
|
|
|
|
|
Permission = Permission.User;
|
|
|
|
|
RequiresTarget = false;
|
|
|
|
|
Arguments = new[]
|
2018-05-05 16:36:26 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2018-03-06 02:22:19 -05:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_PLAYER"],
|
|
|
|
|
Required = false
|
2018-03-06 02:22:19 -05:00
|
|
|
|
}
|
2020-01-26 19:06:50 -05:00
|
|
|
|
};
|
2018-02-10 01:26:38 -05:00
|
|
|
|
}
|
2018-04-14 00:51:38 -04:00
|
|
|
|
|
2018-09-29 15:52:22 -04:00
|
|
|
|
public override Task ExecuteAsync(GameEvent E)
|
2018-04-14 00:51:38 -04:00
|
|
|
|
{
|
2019-04-08 21:31:32 -04:00
|
|
|
|
if (E.Target == null)
|
|
|
|
|
{
|
|
|
|
|
E.Target = E.Owner.GetClientByName(E.Data).FirstOrDefault();
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-09 16:02:49 -04:00
|
|
|
|
if (E.Target == null)
|
2018-04-14 00:51:38 -04:00
|
|
|
|
{
|
2021-11-23 18:26:33 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_PING_SELF_V2"].FormatExt(E.Origin.Ping));
|
2018-04-14 00:51:38 -04:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-11-23 18:26:33 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_PING_TARGET_V2"].FormatExt(E.Target.Name, E.Target.Ping));
|
2018-04-14 00:51:38 -04:00
|
|
|
|
}
|
2018-09-29 15:52:22 -04:00
|
|
|
|
|
|
|
|
|
return Task.CompletedTask;
|
2018-04-14 00:51:38 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-06-02 00:48:10 -04:00
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Sets the email for gravatar in webfront
|
2020-01-26 19:06:50 -05:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class SetGravatarCommand : Command
|
2018-06-02 00:48:10 -04:00
|
|
|
|
{
|
2022-03-23 09:43:57 -04:00
|
|
|
|
private readonly IMetaServiceV2 _metaService;
|
2020-08-17 22:21:11 -04:00
|
|
|
|
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public SetGravatarCommand(CommandConfiguration config, ITranslationLookup translationLookup,
|
2022-03-23 09:43:57 -04:00
|
|
|
|
IMetaServiceV2 metaService) : base(config, translationLookup)
|
2018-06-02 00:48:10 -04:00
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
Name = "setgravatar";
|
|
|
|
|
Description = _translationLookup["COMMANDS_GRAVATAR_DESC"];
|
|
|
|
|
Alias = "sg";
|
|
|
|
|
Permission = Permission.User;
|
|
|
|
|
RequiresTarget = false;
|
|
|
|
|
Arguments = new[]
|
2018-06-02 00:48:10 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
new CommandArgument
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = _translationLookup["COMMANDS_ARGS_GRAVATAR"],
|
|
|
|
|
Required = true
|
|
|
|
|
}
|
|
|
|
|
};
|
2020-08-17 22:21:11 -04:00
|
|
|
|
|
|
|
|
|
_metaService = metaService;
|
2020-01-26 19:06:50 -05:00
|
|
|
|
}
|
2018-06-02 00:48:10 -04:00
|
|
|
|
|
|
|
|
|
public override async Task ExecuteAsync(GameEvent E)
|
|
|
|
|
{
|
2019-04-09 16:02:49 -04:00
|
|
|
|
using (var md5 = MD5.Create())
|
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
var gravatarEmail = string.Concat(md5
|
|
|
|
|
.ComputeHash(E.Data.ToLower().Select(d => Convert.ToByte(d)).ToArray())
|
|
|
|
|
.Select(h => h.ToString("x2")));
|
2022-03-23 09:43:57 -04:00
|
|
|
|
await _metaService.SetPersistentMeta("GravatarEmail", gravatarEmail, E.Origin.ClientId,
|
|
|
|
|
E.Owner.Manager.CancellationToken);
|
2018-06-02 00:48:10 -04:00
|
|
|
|
}
|
2019-04-09 16:02:49 -04:00
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(_translationLookup["COMMANDS_GRAVATAR_SUCCESS_NEW"]);
|
2018-06-02 00:48:10 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-06-02 22:21:01 -04:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
2022-01-26 11:32:16 -05:00
|
|
|
|
/// Retrieves the next map in rotation
|
2018-06-02 22:21:01 -04:00
|
|
|
|
/// </summary>
|
2020-01-26 19:06:50 -05:00
|
|
|
|
public class NextMapCommand : Command
|
2018-06-02 22:21:01 -04:00
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
public NextMapCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config,
|
|
|
|
|
translationLookup)
|
2020-01-26 19:06:50 -05:00
|
|
|
|
{
|
|
|
|
|
Name = "nextmap";
|
|
|
|
|
Description = _translationLookup["COMMANDS_NEXTMAP_DESC"];
|
|
|
|
|
Alias = "nm";
|
2022-01-26 11:32:16 -05:00
|
|
|
|
Permission = Permission.User;
|
2020-01-26 19:06:50 -05:00
|
|
|
|
RequiresTarget = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static async Task<string> GetNextMap(Server s, ITranslationLookup lookup)
|
2018-06-02 22:21:01 -04:00
|
|
|
|
{
|
2022-02-28 21:44:30 -05:00
|
|
|
|
var mapRotation = (await s.GetDvarAsync<string>("sv_mapRotation", token: s.Manager.CancellationToken)).Value?.ToLower() ?? "";
|
2022-01-26 11:32:16 -05:00
|
|
|
|
var regexMatches = Regex.Matches(mapRotation,
|
|
|
|
|
@"((?:gametype|exec) +(?:([a-z]{1,4})(?:.cfg)?))? *map ([a-z|_|\d]+)", RegexOptions.IgnoreCase)
|
|
|
|
|
.ToList();
|
2018-06-05 17:31:36 -04:00
|
|
|
|
|
2018-06-02 22:21:01 -04:00
|
|
|
|
// find the current map in the rotation
|
|
|
|
|
var currentMap = regexMatches.Where(m => m.Groups[3].ToString() == s.CurrentMap.Name);
|
|
|
|
|
var lastMap = regexMatches.LastOrDefault();
|
|
|
|
|
Map nextMap = null;
|
|
|
|
|
|
2018-06-05 17:31:36 -04:00
|
|
|
|
// no maprotation at all
|
|
|
|
|
if (regexMatches.Count() == 0)
|
|
|
|
|
{
|
2022-01-26 11:32:16 -05:00
|
|
|
|
return lookup["COMMANDS_NEXTMAP_SUCCESS"]
|
|
|
|
|
.FormatExt(s.CurrentMap.Alias, Utilities.GetLocalizedGametype(s.Gametype));
|
2018-06-05 17:31:36 -04:00
|
|
|
|
}
|
|
|
|
|
|
2018-06-02 22:21:01 -04:00
|
|
|
|
// the current map is not in rotation
|
|
|
|
|
if (currentMap.Count() == 0)
|
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
return lookup["COMMANDS_NEXTMAP_NOT_IN_ROTATION"];
|
2018-06-02 22:21:01 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// there's duplicate maps in rotation
|
2022-01-26 11:32:16 -05:00
|
|
|
|
|
|
|
|
|
if (currentMap.Count() > 1)
|
2018-06-02 22:21:01 -04:00
|
|
|
|
{
|
|
|
|
|
// gametype has been manually specified
|
|
|
|
|
var duplicateMaps = currentMap.Where(m => !string.IsNullOrEmpty(m.Groups[1].ToString()));
|
|
|
|
|
|
|
|
|
|
// more than one instance of map in rotation
|
|
|
|
|
if (duplicateMaps.Count() > 0)
|
|
|
|
|
{
|
|
|
|
|
currentMap = duplicateMaps.Where(m => m.Groups[2].ToString() == s.Gametype);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// else we just have to assume it's the first one
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if the current map is the last map, the next map is the first map
|
2022-01-26 11:32:16 -05:00
|
|
|
|
var nextMapMatch = currentMap.First().Index != lastMap.Index
|
|
|
|
|
? regexMatches[regexMatches.IndexOf(currentMap.First()) + 1]
|
|
|
|
|
: regexMatches.First();
|
2018-10-03 22:20:49 -04:00
|
|
|
|
|
2022-01-26 11:32:16 -05:00
|
|
|
|
var nextMapName = nextMapMatch.Groups[3].ToString();
|
2019-04-16 12:32:42 -04:00
|
|
|
|
|
2022-01-26 11:32:16 -05:00
|
|
|
|
nextMap = s.Maps.FirstOrDefault(m => m.Name == nextMapMatch.Groups[3].ToString()) ??
|
|
|
|
|
new Map { Alias = nextMapName, Name = nextMapName };
|
|
|
|
|
var nextGametype = nextMapMatch.Groups[2].ToString().Length == 0
|
|
|
|
|
? Utilities.GetLocalizedGametype(s.Gametype)
|
|
|
|
|
: Utilities.GetLocalizedGametype(nextMapMatch.Groups[2].ToString());
|
2018-06-02 22:21:01 -04:00
|
|
|
|
|
2020-01-26 19:06:50 -05:00
|
|
|
|
return lookup["COMMANDS_NEXTMAP_SUCCESS"].FormatExt(nextMap.Alias, nextGametype);
|
2018-06-02 22:21:01 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task ExecuteAsync(GameEvent E)
|
|
|
|
|
{
|
2020-01-26 19:06:50 -05:00
|
|
|
|
E.Origin.Tell(await GetNextMap(E.Owner, _translationLookup));
|
2018-06-02 22:21:01 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-28 16:33:21 -05:00
|
|
|
|
}
|