diff --git a/Admin/Application.csproj b/Admin/Application.csproj
index 599b29c85..a07385ce5 100644
--- a/Admin/Application.csproj
+++ b/Admin/Application.csproj
@@ -122,7 +122,6 @@
-
@@ -135,6 +134,7 @@
Settings.settings
+
diff --git a/Admin/Kayak.cs b/Admin/Kayak.cs
index 82d7cedac..1a62ccbc8 100644
--- a/Admin/Kayak.cs
+++ b/Admin/Kayak.cs
@@ -18,20 +18,20 @@ namespace IW4MAdmin
if (e.GetType() == typeof(NullReferenceException))
return;
- Manager.GetInstance().Logger.WriteWarning("Web service has encountered an error - " + e.Message);
- Manager.GetInstance().Logger.WriteDebug($"Stack Trace: {e.StackTrace}");
+ ApplicationManager.GetInstance().Logger.WriteWarning("Web service has encountered an error - " + e.Message);
+ ApplicationManager.GetInstance().Logger.WriteDebug($"Stack Trace: {e.StackTrace}");
if (e.InnerException != null)
{
- Manager.GetInstance().Logger.WriteDebug($"Inner Exception: {e.InnerException.Message}");
- Manager.GetInstance().Logger.WriteDebug($"Inner Stack Trace: {e.InnerException.StackTrace}");
+ ApplicationManager.GetInstance().Logger.WriteDebug($"Inner Exception: {e.InnerException.Message}");
+ ApplicationManager.GetInstance().Logger.WriteDebug($"Inner Stack Trace: {e.InnerException.StackTrace}");
}
}
public void OnStop(IScheduler scheduler)
{
- Manager.GetInstance().Logger.WriteInfo("Web service has been stopped...");
+ ApplicationManager.GetInstance().Logger.WriteInfo("Web service has been stopped...");
}
}
diff --git a/Admin/Main.cs b/Admin/Main.cs
index 379dbcca9..b0d0b61f3 100644
--- a/Admin/Main.cs
+++ b/Admin/Main.cs
@@ -11,7 +11,7 @@ namespace IW4MAdmin
class Program
{
static public double Version { get; private set; }
- static private Manager ServerManager;
+ static private ApplicationManager ServerManager;
static void Main(string[] args)
{
@@ -33,7 +33,7 @@ namespace IW4MAdmin
{
CheckDirectories();
- ServerManager = Manager.GetInstance();
+ ServerManager = ApplicationManager.GetInstance();
ServerManager.Init();
Task.Run(() =>
diff --git a/Admin/Manager.cs b/Admin/Manager.cs
index f74847ad7..b7773ded2 100644
--- a/Admin/Manager.cs
+++ b/Admin/Manager.cs
@@ -2,39 +2,44 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
-using SharedLibrary;
using System.IO;
using System.Threading.Tasks;
+using SharedLibrary;
+using SharedLibrary.Interfaces;
+using SharedLibrary.Commands;
+using SharedLibrary.Helpers;
+
namespace IW4MAdmin
{
- class Manager : SharedLibrary.Interfaces.IManager
+ class ApplicationManager : IManager
{
- static Manager Instance;
public List Servers { get; private set; }
- List TaskStatuses;
+ public ILogger Logger { get; private set; }
+ public bool Running { get; private set; }
+
+ static ApplicationManager Instance;
+ List TaskStatuses;
Database ClientDatabase;
Database AliasesDatabase;
- SharedLibrary.Interfaces.IPenaltyList ClientPenalties;
+ IPenaltyList ClientPenalties;
List Commands;
- List MessageTokens;
+ List MessageTokens;
Kayak.IScheduler webServiceTask;
Thread WebThread;
- public SharedLibrary.Interfaces.ILogger Logger { get; private set; }
- public bool Running { get; private set; }
#if FTP_LOG
const int UPDATE_FREQUENCY = 15000;
#else
const int UPDATE_FREQUENCY = 300;
#endif
- private Manager()
+ private ApplicationManager()
{
Logger = new Logger("Logs/IW4MAdmin.log");
Servers = new List();
Commands = new List();
- TaskStatuses = new List();
- MessageTokens = new List();
+ TaskStatuses = new List();
+ MessageTokens = new List();
ClientDatabase = new ClientsDB("Database/clients.rm");
AliasesDatabase = new AliasesDB("Database/aliases.rm");
@@ -51,40 +56,23 @@ namespace IW4MAdmin
return Commands;
}
- public static Manager GetInstance()
+ public static ApplicationManager GetInstance()
{
- return Instance ?? (Instance = new Manager());
+ return Instance ?? (Instance = new ApplicationManager());
}
public void Init()
{
- SharedLibrary.WebService.Init();
- SharedLibrary.Plugins.PluginImporter.Load(this);
-
- foreach (var Plugin in SharedLibrary.Plugins.PluginImporter.ActivePlugins)
- {
- try
- {
- Plugin.OnLoadAsync();
- }
-
- catch (Exception e)
- {
- Logger.WriteError($"An error occured loading plugin {Plugin.Name}");
- Logger.WriteDebug($"Exception: {e.Message}");
- Logger.WriteDebug($"Stack Trace: {e.StackTrace}");
- }
- }
-
+ #region CONFIG
var Configs = Directory.EnumerateFiles("config/servers").Where(x => x.Contains(".cfg"));
if (Configs.Count() == 0)
- ServerConfig.Generate();
+ ServerConfigurationGenerator.Generate();
foreach (var file in Configs)
{
- var Conf = ServerConfig.Read(file);
- var ServerInstance = new IW4MServer(this, Conf.IP, Conf.Port, Conf.Password);
+ var Conf = ServerConfiguration.Read(file);
+ var ServerInstance = new IW4MServer(this, Conf);
Task.Run(async () =>
{
@@ -111,7 +99,68 @@ namespace IW4MAdmin
});
}
+ #endregion
+ #region PLUGINS
+ SharedLibrary.Plugins.PluginImporter.Load(this);
+
+ foreach (var Plugin in SharedLibrary.Plugins.PluginImporter.ActivePlugins)
+ {
+ try
+ {
+ Plugin.OnLoadAsync();
+ }
+
+ catch (Exception e)
+ {
+ Logger.WriteError($"An error occured loading plugin {Plugin.Name}");
+ Logger.WriteDebug($"Exception: {e.Message}");
+ Logger.WriteDebug($"Stack Trace: {e.StackTrace}");
+ }
+ }
+ #endregion
+
+ #region COMMANDS
+ if ((ClientDatabase as ClientsDB).GetOwner() != null)
+ Commands.Add(new COwner("owner", "claim ownership of the server", "owner", Player.Permission.User, 0, false));
+
+ Commands.Add(new CQuit("quit", "quit IW4MAdmin", "q", Player.Permission.Owner, 0, false));
+ Commands.Add(new CKick("kick", "kick a player by name. syntax: !kick .", "k", Player.Permission.Trusted, 2, true));
+ Commands.Add(new CSay("say", "broadcast message to all players. syntax: !say .", "s", Player.Permission.Moderator, 1, false));
+ Commands.Add(new CTempBan("tempban", "temporarily ban a player for 1 hour. syntax: !tempban .", "tb", Player.Permission.Moderator, 2, true));
+ Commands.Add(new CBan("ban", "permanently ban a player from the server. syntax: !ban ", "b", Player.Permission.SeniorAdmin, 2, true));
+ Commands.Add(new CWhoAmI("whoami", "give information about yourself. syntax: !whoami.", "who", Player.Permission.User, 0, false));
+ Commands.Add(new CList("list", "list active clients syntax: !list.", "l", Player.Permission.Moderator, 0, false));
+ Commands.Add(new CHelp("help", "list all available commands. syntax: !help.", "h", Player.Permission.User, 0, false));
+ Commands.Add(new CFastRestart("fastrestart", "fast restart current map. syntax: !fastrestart.", "fr", Player.Permission.Moderator, 0, false));
+ Commands.Add(new CMapRotate("maprotate", "cycle to the next map in rotation. syntax: !maprotate.", "mr", Player.Permission.Administrator, 0, false));
+ Commands.Add(new CSetLevel("setlevel", "set player to specified administration level. syntax: !setlevel .", "sl", Player.Permission.Owner, 2, true));
+ Commands.Add(new CUsage("usage", "get current application memory usage. syntax: !usage.", "us", Player.Permission.Moderator, 0, false));
+ Commands.Add(new CUptime("uptime", "get current application running time. syntax: !uptime.", "up", Player.Permission.Moderator, 0, false));
+ Commands.Add(new Cwarn("warn", "warn player for infringing rules syntax: !warn .", "w", Player.Permission.Trusted, 2, true));
+ Commands.Add(new CWarnClear("warnclear", "remove all warning for a player syntax: !warnclear .", "wc", Player.Permission.Trusted, 1, true));
+ Commands.Add(new CUnban("unban", "unban player by database id. syntax: !unban @.", "ub", Player.Permission.SeniorAdmin, 1, true));
+ Commands.Add(new CListAdmins("admins", "list currently connected admins. syntax: !admins.", "a", Player.Permission.User, 0, false));
+ Commands.Add(new CLoadMap("map", "change to specified map. syntax: !map", "m", Player.Permission.Administrator, 1, false));
+ Commands.Add(new CFindPlayer("find", "find player in database. syntax: !find ", "f", Player.Permission.SeniorAdmin, 1, false));
+ Commands.Add(new CListRules("rules", "list server rules. syntax: !rules", "r", Player.Permission.User, 0, false));
+ Commands.Add(new CPrivateMessage("privatemessage", "send message to other player. syntax: !pm ", "pm", Player.Permission.User, 2, true));
+ Commands.Add(new CFlag("flag", "flag a suspicious player and announce to admins on join . syntax !flag :", "flag", Player.Permission.Moderator, 2, true));
+ Commands.Add(new CReport("report", "report a player for suspicious behaivor. syntax !report ", "rep", Player.Permission.User, 2, true));
+ Commands.Add(new CListReports("reports", "get most recent reports. syntax !reports", "reports", Player.Permission.Moderator, 0, false));
+ Commands.Add(new CMask("mask", "hide your online presence from online admin list. syntax: !mask", "mask", Player.Permission.Administrator, 0, false));
+ Commands.Add(new CListBanInfo("baninfo", "get information about a ban for a player. syntax: !baninfo ", "bi", Player.Permission.Moderator, 1, true));
+ Commands.Add(new CListAlias("alias", "get past aliases and ips of a player. syntax: !alias ", "known", Player.Permission.Moderator, 1, true));
+ Commands.Add(new CExecuteRCON("rcon", "send rcon command to server. syntax: !rcon ", "rcon", Player.Permission.Owner, 1, false));
+ Commands.Add(new CFindAllPlayers("findall", "find a player by their aliase(s). syntax: !findall ", "fa", Player.Permission.Moderator, 1, false));
+ Commands.Add(new CPlugins("plugins", "view all loaded plugins. syntax: !plugins", "p", Player.Permission.Administrator, 0, false));
+
+ foreach (Command C in SharedLibrary.Plugins.PluginImporter.ActiveCommands)
+ Commands.Add(C);
+ #endregion
+
+ #region WEBSERVICE
+ SharedLibrary.WebService.Init();
webServiceTask = WebService.GetScheduler();
WebThread = new Thread(webServiceTask.Start)
@@ -120,6 +169,7 @@ namespace IW4MAdmin
};
WebThread.Start();
+ #endregion
Running = true;
}
@@ -165,17 +215,17 @@ namespace IW4MAdmin
return AliasesDatabase as AliasesDB;
}
- public SharedLibrary.Interfaces.IPenaltyList GetClientPenalties()
+ public IPenaltyList GetClientPenalties()
{
return ClientPenalties;
}
- public SharedLibrary.Interfaces.ILogger GetLogger()
+ public ILogger GetLogger()
{
return Logger;
}
- public IList GetMessageTokens()
+ public IList GetMessageTokens()
{
return MessageTokens;
}
diff --git a/Admin/PenaltyList.cs b/Admin/PenaltyList.cs
index d6c969132..e40ad159a 100644
--- a/Admin/PenaltyList.cs
+++ b/Admin/PenaltyList.cs
@@ -15,22 +15,22 @@ namespace IW4MAdmin
public void AddPenalty(Penalty P)
{
- Manager.GetInstance().GetClientDatabase().AddBan(P);
+ ApplicationManager.GetInstance().GetClientDatabase().AddBan(P);
}
public void RemovePenalty(Penalty P)
{
- Manager.GetInstance().GetClientDatabase().RemoveBan(P.OffenderID);
+ ApplicationManager.GetInstance().GetClientDatabase().RemoveBan(P.OffenderID);
}
public List FindPenalties(Player P)
{
- return Manager.GetInstance().GetClientDatabase().GetClientPenalties(P);
+ return ApplicationManager.GetInstance().GetClientDatabase().GetClientPenalties(P);
}
public List AsChronoList(int offset, int count)
{
- return Manager.GetInstance().GetClientDatabase().GetPenaltiesChronologically(offset, count);
+ return ApplicationManager.GetInstance().GetClientDatabase().GetPenaltiesChronologically(offset, count);
}
}
}
diff --git a/Admin/Server.cs b/Admin/Server.cs
index 65a484e57..3ac34efc3 100644
--- a/Admin/Server.cs
+++ b/Admin/Server.cs
@@ -3,18 +3,17 @@ using System.Collections.Generic;
using System.Threading;
using System.IO;
using System.Linq;
+using System.Threading.Tasks;
+
using SharedLibrary;
using SharedLibrary.Network;
-using System.Threading.Tasks;
+using SharedLibrary.Interfaces;
namespace IW4MAdmin
{
public class IW4MServer : Server
{
- public IW4MServer(SharedLibrary.Interfaces.IManager mgr, string address, int port, string password) : base(mgr, address, port, password)
- {
- InitializeCommands();
- }
+ public IW4MServer(IManager mgr, ServerConfiguration cfg) : base(mgr, cfg) { }
private void GetAliases(List returnAliases, Aliases currentAlias)
{
@@ -76,7 +75,6 @@ namespace IW4MAdmin
Manager.GetAliasesDatabase().AddPlayerAliases(new Aliases(NewPlayer.DatabaseID, NewPlayer.Name, NewPlayer.IP));
}
-
List Admins = Manager.GetClientDatabase().GetAdmins();
if (Admins.Find(x => x.Name == P.Name) != null)
{
@@ -108,9 +106,7 @@ namespace IW4MAdmin
// and ips
if (NewPlayer.Alias.IPS.Find(i => i.Equals(P.IP)) == null || P.IP == null || P.IP == String.Empty)
- {
NewPlayer.Alias.IPS.Add(P.IP);
- }
NewPlayer.SetIP(P.IP);
@@ -127,7 +123,7 @@ namespace IW4MAdmin
return true;
}
- List newPlayerAliases = GetPlayerAliases(NewPlayer);
+ var newPlayerAliases = GetPlayerAliases(NewPlayer);
foreach (Player aP in newPlayerAliases) // lets check their aliases
{
@@ -209,21 +205,7 @@ namespace IW4MAdmin
return null;
}
- else
- {
- Player P = null;
- try
- {
- P = Players[pID];
- return P;
- }
- catch (Exception)
- {
- Logger.WriteError("Client index is invalid - " + pID);
- Logger.WriteDebug(L.ToString());
- return null;
- }
- }
+ return Players[pID];
}
//Check ban list for every banned player and return ban if match is found
@@ -272,7 +254,6 @@ namespace IW4MAdmin
int cNum = -1;
int.TryParse(Args[0], out cNum);
-
if (Args[0] == String.Empty)
return C;
@@ -296,9 +277,10 @@ namespace IW4MAdmin
E.Target = Players[cNum];
}
- E.Target = GetClientByName(E.Data.Trim());
+ if (E.Target == null) // Find active player including quotes (multiple words)
+ E.Target = GetClientByName(E.Data.Trim());
- if (E.Target == null)
+ if (E.Target == null) // Find active player as single word
E.Target = GetClientByName(Args[0]);
if (E.Target == null && C.RequiresTarget)
@@ -312,17 +294,13 @@ namespace IW4MAdmin
public override async Task ExecuteEvent(Event E)
{
- await ProcessEvent(E);
+ await ProcessEvent(E);
- foreach (SharedLibrary.Interfaces.IPlugin P in SharedLibrary.Plugins.PluginImporter.ActivePlugins)
+ foreach (IPlugin P in SharedLibrary.Plugins.PluginImporter.ActivePlugins)
{
try
{
-#if DEBUG
await P.OnEventAsync(E, this);
-#else
- P.OnEventAsync(E, this);
-#endif
}
catch (Exception Except)
@@ -381,19 +359,13 @@ namespace IW4MAdmin
Logger.WriteError($"{e.Message} {IP}:{Port}, reducing polling rate");
}
- lastMessage = DateTime.Now - start;
+ LastMessage = DateTime.Now - start;
lastCount = DateTime.Now;
if ((DateTime.Now - tickTime).TotalMilliseconds >= 1000)
{
- // We don't want to await here, just in case user plugins are really slow :c
foreach (var Plugin in SharedLibrary.Plugins.PluginImporter.ActivePlugins)
-#if !DEBUG
- Plugin.OnTickAsync(this);
-#else
await Plugin.OnTickAsync(this);
-#endif
-
tickTime = DateTime.Now;
}
@@ -405,24 +377,24 @@ namespace IW4MAdmin
playerCountStart = DateTime.Now;
}
- if (lastMessage.TotalSeconds > messageTime && messages.Count > 0 && Players.Count > 0)
+ if (LastMessage.TotalSeconds > MessageTime && BroadcastMessages.Count > 0 && Players.Count > 0)
{
- await Broadcast(Utilities.ProcessMessageToken(Manager.GetMessageTokens(), messages[nextMessage]));
- if (nextMessage == (messages.Count - 1))
- nextMessage = 0;
+ await Broadcast(Utilities.ProcessMessageToken(Manager.GetMessageTokens(), BroadcastMessages[NextMessage]));
+ if (NextMessage == (BroadcastMessages.Count - 1))
+ NextMessage = 0;
else
- nextMessage++;
+ NextMessage++;
start = DateTime.Now;
}
//logFile = new IFile();
- if (l_size != logFile.Length())
+ if (l_size != LogFile.Length())
{
// this should be the longest running task
- await Task.FromResult(lines = logFile.Tail(12));
+ await Task.FromResult(lines = LogFile.Tail(12));
if (lines != oldLines)
{
- l_size = logFile.Length();
+ l_size = LogFile.Length();
int end;
if (lines.Length == oldLines.Length)
end = lines.Length - 1;
@@ -459,7 +431,7 @@ namespace IW4MAdmin
}
}
oldLines = lines;
- l_size = logFile.Length();
+ l_size = LogFile.Length();
}
#if DEBUG == false
catch (SharedLibrary.Exceptions.NetworkException)
@@ -501,7 +473,7 @@ namespace IW4MAdmin
}
this.Hostname = hostname.Value.StripColors();
- this.CurrentMap = maps.Find(m => m.Name == mapname.Value) ?? new Map(mapname.Value, mapname.Value);
+ this.CurrentMap = Maps.Find(m => m.Name == mapname.Value) ?? new Map(mapname.Value, mapname.Value);
this.MaxClients = maxplayers.Value;
this.FSGame = game.Value;
@@ -531,7 +503,7 @@ namespace IW4MAdmin
#endif
}
else
- logFile = new IFile(logPath);
+ LogFile = new IFile(logPath);
Logger.WriteInfo("Log file is " + logPath);
await ExecuteEvent(new Event(Event.GType.Start, "Server started", null, null, this));
@@ -543,26 +515,15 @@ namespace IW4MAdmin
//Process any server event
override protected async Task ProcessEvent(Event E)
{
- //todo: move
- while (ChatHistory.Count > Math.Ceiling((double)ClientNum / 2))
- ChatHistory.RemoveAt(0);
if (E.Type == Event.GType.Connect)
{
ChatHistory.Add(new Chat(E.Origin.Name, "CONNECTED", DateTime.Now));
- return;
}
if (E.Type == Event.GType.Disconnect)
{
ChatHistory.Add(new Chat(E.Origin.Name, "DISCONNECTED", DateTime.Now));
-
- // the last client hasn't fully disconnected yet
- // so there will still be at least 1 client left
- if (ClientNum < 2)
- ChatHistory.Clear();
-
- return;
}
if (E.Type == Event.GType.Kill)
@@ -574,6 +535,15 @@ namespace IW4MAdmin
await ExecuteEvent(new Event(Event.GType.Death, "suicide", E.Target, null, this));
}
+ //todo: move
+ while (ChatHistory.Count > Math.Ceiling((double)ClientNum / 2))
+ ChatHistory.RemoveAt(0);
+
+ // the last client hasn't fully disconnected yet
+ // so there will still be at least 1 client left
+ if (ClientNum < 2)
+ ChatHistory.Clear();
+
if (E.Type == Event.GType.Say)
{
if (E.Data.Length < 2) // ITS A LIE!
@@ -643,7 +613,7 @@ namespace IW4MAdmin
FSGame = (await this.GetDvarAsync("fs_game")).Value.StripColors();
string mapname = this.GetDvarAsync("mapname").Result.Value;
- CurrentMap = maps.Find(m => m.Name == mapname) ?? new Map(mapname, mapname);
+ CurrentMap = Maps.Find(m => m.Name == mapname) ?? new Map(mapname, mapname);
return;
}
@@ -779,9 +749,9 @@ namespace IW4MAdmin
catch (Exception E)
{
Logger.WriteError("Unable to reload configs! - " + E.Message);
- messages = new List();
- maps = new List
diff --git a/SharedLibrary/Utilities.cs b/SharedLibrary/Utilities.cs
index ebd518f7c..2287e33ae 100644
--- a/SharedLibrary/Utilities.cs
+++ b/SharedLibrary/Utilities.cs
@@ -72,11 +72,9 @@ namespace SharedLibrary
{
String lookingFor = str.ToLower();
- for (Player.Permission Perm = Player.Permission.User; Perm < Player.Permission.Owner; Perm++)
- {
+ for (Player.Permission Perm = Player.Permission.User; Perm < Player.Permission.Console; Perm++)
if (lookingFor.Contains(Perm.ToString().ToLower()))
return Perm;
- }
return Player.Permission.Banned;
}