fixed loader offset
some stat stuff still not working made seperate parsers
This commit is contained in:
parent
8652cc3be3
commit
827e69f70a
@ -51,6 +51,8 @@ namespace IW4MAdmin.Application
|
||||
newConfig.AutoMessages = new List<string>();
|
||||
newConfig.Rules = new List<string>();
|
||||
|
||||
newConfig.UseT6MParser = Utilities.PromptBool("Use T6M parser");
|
||||
|
||||
configList.Add(newConfig);
|
||||
|
||||
Console.Write("Configuration saved, add another? [y/n]:");
|
||||
|
103
Application/RconParsers/IW4Parser.cs
Normal file
103
Application/RconParsers/IW4Parser.cs
Normal file
@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using SharedLibraryCore.Objects;
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.RCon;
|
||||
using SharedLibraryCore.Exceptions;
|
||||
|
||||
namespace Application.RconParsers
|
||||
{
|
||||
class IW4Parser : IRConParser
|
||||
{
|
||||
public async Task<string[]> ExecuteCommandAsync(Connection connection, string command)
|
||||
{
|
||||
return (await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, command)).Skip(1).ToArray();
|
||||
}
|
||||
|
||||
public async Task<Dvar<T>> GetDvarAsync<T>(Connection connection, string dvarName)
|
||||
{
|
||||
string[] LineSplit = await connection.SendQueryAsync(StaticHelpers.QueryType.DVAR, dvarName);
|
||||
|
||||
if (LineSplit.Length != 3)
|
||||
{
|
||||
var e = new DvarException($"DVAR \"{dvarName}\" does not exist");
|
||||
e.Data["dvar_name"] = dvarName;
|
||||
throw e;
|
||||
}
|
||||
|
||||
string[] ValueSplit = LineSplit[1].Split(new char[] { '"' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (ValueSplit.Length != 5)
|
||||
{
|
||||
var e = new DvarException($"DVAR \"{dvarName}\" does not exist");
|
||||
e.Data["dvar_name"] = dvarName;
|
||||
throw e;
|
||||
}
|
||||
|
||||
string DvarName = Regex.Replace(ValueSplit[0], @"\^[0-9]", "");
|
||||
string DvarCurrentValue = Regex.Replace(ValueSplit[2], @"\^[0-9]", "");
|
||||
string DvarDefaultValue = Regex.Replace(ValueSplit[4], @"\^[0-9]", "");
|
||||
|
||||
return new Dvar<T>(DvarName)
|
||||
{
|
||||
Value = (T)Convert.ChangeType(DvarCurrentValue, typeof(T))
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<List<Player>> GetStatusAsync(Connection connection)
|
||||
{
|
||||
string[] response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, "status");
|
||||
return ClientsFromStatus(response);
|
||||
}
|
||||
|
||||
public async Task<bool> SetDvarAsync(Connection connection, string dvarName, object dvarValue)
|
||||
{
|
||||
return (await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, $"set {dvarName} {dvarValue}")).Length > 0;
|
||||
}
|
||||
|
||||
private List<Player> ClientsFromStatus(string[] Status)
|
||||
{
|
||||
List<Player> StatusPlayers = new List<Player>();
|
||||
|
||||
foreach (String S in Status)
|
||||
{
|
||||
String responseLine = S.Trim();
|
||||
|
||||
if (Regex.Matches(responseLine, @"\d+$", RegexOptions.IgnoreCase).Count > 0 && responseLine.Length > 72) // its a client line!
|
||||
{
|
||||
String[] playerInfo = responseLine.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
int cID = -1;
|
||||
int Ping = -1;
|
||||
Int32.TryParse(playerInfo[2], out Ping);
|
||||
String cName = Encoding.UTF8.GetString(Encoding.Convert(Encoding.UTF7, Encoding.UTF8, Encoding.UTF7.GetBytes(responseLine.Substring(46, 18).StripColors().Trim())));
|
||||
long npID = Regex.Match(responseLine, @"([a-z]|[0-9]){16}", RegexOptions.IgnoreCase).Value.ConvertLong();
|
||||
int.TryParse(playerInfo[0], out cID);
|
||||
var regex = Regex.Match(responseLine, @"\d+\.\d+\.\d+.\d+\:\d{1,5}");
|
||||
#if DEBUG
|
||||
Ping = 1;
|
||||
#endif
|
||||
int cIP = regex.Value.Split(':')[0].ConvertToIP();
|
||||
regex = Regex.Match(responseLine, @"[0-9]{1,2}\s+[0-9]+\s+");
|
||||
int score = Int32.Parse(regex.Value.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[1]);
|
||||
Player P = new Player()
|
||||
{
|
||||
Name = cName,
|
||||
NetworkId = npID,
|
||||
ClientNumber = cID,
|
||||
IPAddress = cIP,
|
||||
Ping = Ping,
|
||||
Score = score
|
||||
};
|
||||
StatusPlayers.Add(P);
|
||||
}
|
||||
}
|
||||
|
||||
return StatusPlayers;
|
||||
}
|
||||
}
|
||||
}
|
107
Application/RconParsers/T6MParser.cs
Normal file
107
Application/RconParsers/T6MParser.cs
Normal file
@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using SharedLibraryCore.Objects;
|
||||
using SharedLibraryCore.RCon;
|
||||
using SharedLibraryCore.Exceptions;
|
||||
using System.Text;
|
||||
|
||||
namespace Application.RconParsers
|
||||
{
|
||||
public class T6MParser : IRConParser
|
||||
{
|
||||
public async Task<string[]> ExecuteCommandAsync(Connection connection, string command)
|
||||
{
|
||||
await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, command, false);
|
||||
return new string[] { "Command Executed" };
|
||||
}
|
||||
|
||||
public async Task<Dvar<T>> GetDvarAsync<T>(Connection connection, string dvarName)
|
||||
{
|
||||
string[] LineSplit = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, $"get {dvarName}");
|
||||
|
||||
|
||||
if (LineSplit.Length < 2)
|
||||
{
|
||||
var e = new DvarException($"DVAR \"{dvarName}\" does not exist");
|
||||
e.Data["dvar_name"] = dvarName;
|
||||
throw e;
|
||||
}
|
||||
|
||||
string[] ValueSplit = LineSplit[1].Split(new char[] { '"' });
|
||||
|
||||
if (ValueSplit.Length == 0)
|
||||
{
|
||||
var e = new DvarException($"DVAR \"{dvarName}\" does not exist");
|
||||
e.Data["dvar_name"] = dvarName;
|
||||
throw e;
|
||||
}
|
||||
|
||||
string DvarName = dvarName;
|
||||
string DvarCurrentValue = Regex.Replace(ValueSplit[1], @"\^[0-9]", "");
|
||||
|
||||
return new Dvar<T>(DvarName)
|
||||
{
|
||||
Value = (T)Convert.ChangeType(DvarCurrentValue, typeof(T))
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<List<Player>> GetStatusAsync(Connection connection)
|
||||
{
|
||||
string[] response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, "status");
|
||||
return ClientsFromStatus(response);
|
||||
}
|
||||
|
||||
public async Task<bool> SetDvarAsync(Connection connection, string dvarName, object dvarValue)
|
||||
{
|
||||
// T6M doesn't respond with anything when a value is set, so we can only hope for the best :c
|
||||
await connection.SendQueryAsync(StaticHelpers.QueryType.DVAR, $"set {dvarName} {dvarValue}", false);
|
||||
return true;
|
||||
}
|
||||
|
||||
private List<Player> ClientsFromStatus(string[] status)
|
||||
{
|
||||
List<Player> StatusPlayers = new List<Player>();
|
||||
|
||||
foreach (string statusLine in status)
|
||||
{
|
||||
String responseLine = statusLine.Trim();
|
||||
|
||||
if (Regex.Matches(responseLine, @"\d+$", RegexOptions.IgnoreCase).Count > 0 && responseLine.Length > 72) // its a client line!
|
||||
{
|
||||
String[] playerInfo = responseLine.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
int clientId = -1;
|
||||
int Ping = -1;
|
||||
|
||||
Int32.TryParse(playerInfo[3], out Ping);
|
||||
string name = Encoding.UTF8.GetString(Encoding.Convert(Encoding.UTF7, Encoding.UTF8, Encoding.UTF7.GetBytes(responseLine.Substring(50, 15).StripColors().Trim())));
|
||||
long networkId = playerInfo[4].ConvertLong();
|
||||
int.TryParse(playerInfo[0], out clientId);
|
||||
var regex = Regex.Match(responseLine, @"\d+\.\d+\.\d+.\d+\:\d{1,5}");
|
||||
#if DEBUG
|
||||
Ping = 1;
|
||||
#endif
|
||||
int ipAddress = regex.Value.Split(':')[0].ConvertToIP();
|
||||
regex = Regex.Match(responseLine, @"[0-9]{1,2}\s+[0-9]+\s+");
|
||||
int score = Int32.Parse(playerInfo[1]);
|
||||
|
||||
StatusPlayers.Add(new Player()
|
||||
{
|
||||
Name = name,
|
||||
NetworkId = networkId,
|
||||
ClientNumber = clientId,
|
||||
IPAddress = ipAddress,
|
||||
Ping = Ping,
|
||||
Score = score
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return StatusPlayers;
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ using SharedLibraryCore.Dtos;
|
||||
using SharedLibraryCore.Configuration;
|
||||
|
||||
using IW4MAdmin.Application.Misc;
|
||||
using Application.RconParsers;
|
||||
|
||||
namespace IW4MAdmin
|
||||
{
|
||||
@ -589,6 +590,8 @@ namespace IW4MAdmin
|
||||
|
||||
public async Task Initialize()
|
||||
{
|
||||
RconParser = ServerConfig.UseT6MParser ? (IRConParser)new T6MParser() : new IW4Parser();
|
||||
|
||||
var version = await this.GetDvarAsync<string>("version");
|
||||
GameName = Utilities.GetGame(version.Value);
|
||||
|
||||
@ -608,7 +611,7 @@ namespace IW4MAdmin
|
||||
var logfile = await this.GetDvarAsync<string>("g_log");
|
||||
var logsync = await this.GetDvarAsync<int>("g_logsync");
|
||||
|
||||
DVAR<int> onelog = null;
|
||||
Dvar<int> onelog = null;
|
||||
if (GameName == Game.IW4)
|
||||
{
|
||||
try
|
||||
@ -618,7 +621,7 @@ namespace IW4MAdmin
|
||||
|
||||
catch (Exception)
|
||||
{
|
||||
onelog = new DVAR<int>("iw4x_onelog")
|
||||
onelog = new Dvar<int>("iw4x_onelog")
|
||||
{
|
||||
Value = -1
|
||||
};
|
||||
@ -682,7 +685,7 @@ namespace IW4MAdmin
|
||||
|
||||
Logger.WriteInfo($"Log file is {logPath}");
|
||||
#if DEBUG
|
||||
LogFile = new RemoteFile("https://raidmax.org/IW4MAdmin/getlog.php");
|
||||
// LogFile = new RemoteFile("https://raidmax.org/IW4MAdmin/getlog.php");
|
||||
#else
|
||||
await Broadcast("IW4M Admin is now ^2ONLINE");
|
||||
#endif
|
||||
|
@ -67,6 +67,13 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
|
||||
float previousAverage = hitLoc.HitOffsetAverage;
|
||||
double newAverage = (previousAverage * (hitLoc.HitCount - 1) + angle) / hitLoc.HitCount;
|
||||
hitLoc.HitOffsetAverage = (float)newAverage;
|
||||
|
||||
if (hitLoc.HitOffsetAverage == float.NaN)
|
||||
{
|
||||
Log.WriteWarning("[Detection::ProcessKill] HitOffsetAvgerage NaN");
|
||||
Log.WriteDebug($"{previousAverage}-{hitLoc.HitCount}-{hitLoc}-{newAverage}");
|
||||
hitLoc.HitOffsetAverage = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -23,8 +23,8 @@ namespace IW4MAdmin.Plugins.Stats.Commands
|
||||
|
||||
stats.Deaths = 0;
|
||||
stats.Kills = 0;
|
||||
stats.SPM = 0;
|
||||
stats.Skill = 0;
|
||||
stats.SPM = 0.0;
|
||||
stats.Skill = 0.0;
|
||||
|
||||
// reset the cached version
|
||||
Plugin.Manager.ResetStats(E.Origin.ClientId, E.Owner.GetHashCode());
|
||||
|
@ -355,6 +355,13 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
if (streakMessage != string.Empty)
|
||||
await attacker.Tell(streakMessage);
|
||||
|
||||
// fixme: why?
|
||||
if (victimStats.SPM == double.NaN || victimStats.Skill == double.NaN)
|
||||
{
|
||||
victimStats.SPM = 0.0;
|
||||
victimStats.Skill = 0.0;
|
||||
}
|
||||
|
||||
// todo: do we want to save this immediately?
|
||||
var statsSvc = ContextThreads[serverId];
|
||||
statsSvc.ClientStatSvc.Update(attackerStats);
|
||||
@ -417,10 +424,11 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
|
||||
// calculate how much the KDR should weigh
|
||||
// 1.637 is a Eddie-Generated number that weights the KDR nicely
|
||||
double KDRWeight = Math.Round(Math.Pow(clientStats.KDR, 1.637 / Math.E), 3);
|
||||
double kdr = clientStats.Deaths == 0 ? clientStats.Kills : clientStats.KDR;
|
||||
double KDRWeight = Math.Round(Math.Pow(kdr, 1.637 / Math.E), 3);
|
||||
|
||||
// if no SPM, weight is 1 else the weight ishe current session's spm / lifetime average score per minute
|
||||
double SPMWeightAgainstAverage = (clientStats.SPM < 1) ? 1 : killSPM / clientStats.SPM;
|
||||
//double SPMWeightAgainstAverage = (clientStats.SPM < 1) ? 1 : killSPM / clientStats.SPM;
|
||||
|
||||
// calculate the weight of the new play time against last 10 hours of gameplay
|
||||
int totalPlayTime = (clientStats.TimePlayed == 0) ?
|
||||
@ -431,12 +439,20 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
||||
|
||||
// calculate the new weight against average times the weight against play time
|
||||
clientStats.SPM = (killSPM * SPMAgainstPlayWeight) + (clientStats.SPM * (1 - SPMAgainstPlayWeight));
|
||||
// fixme: how does this happen?
|
||||
if (clientStats.SPM == double.NaN)
|
||||
clientStats.SPM = 0;
|
||||
|
||||
clientStats.SPM = Math.Round(clientStats.SPM, 3);
|
||||
|
||||
clientStats.Skill = Math.Round((clientStats.SPM * KDRWeight), 3);
|
||||
|
||||
// fixme: how does this happen?
|
||||
if (clientStats.SPM == double.NaN || clientStats.Skill == double.NaN)
|
||||
{
|
||||
Log.WriteWarning("[StatManager::UpdateStats] clientStats SPM/Skill NaN");
|
||||
Log.WriteDebug($"{killSPM}-{KDRWeight}-{totalPlayTime}-{SPMAgainstPlayWeight}-{clientStats.SPM}-{clientStats.Skill}-{scoreDifference}");
|
||||
clientStats.SPM = 0;
|
||||
clientStats.Skill = 0;
|
||||
}
|
||||
|
||||
clientStats.LastStatCalculation = DateTime.UtcNow;
|
||||
clientStats.LastScore = clientStats.SessionScore;
|
||||
|
||||
|
@ -1,13 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SharedLibraryCore.Configuration
|
||||
{
|
||||
public class ServerConfiguration
|
||||
public class ServerConfiguration : IBaseConfiguration
|
||||
{
|
||||
public string IPAddress { get; set; }
|
||||
public short Port { get; set; }
|
||||
public string Password { get; set; }
|
||||
public List<string> Rules { get; set; }
|
||||
public List<string> AutoMessages { get; set; }
|
||||
public bool UseT6MParser { get; set; }
|
||||
|
||||
public IBaseConfiguration Generate()
|
||||
{
|
||||
UseT6MParser = Utilities.PromptBool("Use T6M parser");
|
||||
return this;
|
||||
}
|
||||
|
||||
public string Name() => "ServerConfiguration";
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
namespace SharedLibraryCore
|
||||
{
|
||||
public class DVAR<T>
|
||||
public class Dvar<T>
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
public T Value;
|
||||
|
||||
public DVAR(string name)
|
||||
public Dvar(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
16
SharedLibraryCore/Interfaces/IRConParser.cs
Normal file
16
SharedLibraryCore/Interfaces/IRConParser.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using SharedLibraryCore.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharedLibraryCore.Interfaces
|
||||
{
|
||||
public interface IRConParser
|
||||
{
|
||||
Task<Dvar<T>> GetDvarAsync<T>(RCon.Connection connection, string dvarName);
|
||||
Task<bool> SetDvarAsync(RCon.Connection connection, string dvarName, object dvarValue);
|
||||
Task<string[]> ExecuteCommandAsync(RCon.Connection connection, string command);
|
||||
Task<List<Player>> GetStatusAsync(RCon.Connection connection);
|
||||
}
|
||||
}
|
@ -159,7 +159,7 @@ namespace SharedLibraryCore.RCon
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string[]> SendQueryAsync(StaticHelpers.QueryType type, string parameters = "")
|
||||
public async Task<string[]> SendQueryAsync(StaticHelpers.QueryType type, string parameters = "", bool waitForResponse = true)
|
||||
{
|
||||
// will this really prevent flooding?
|
||||
if ((DateTime.Now - LastQuery).TotalMilliseconds < 35)
|
||||
@ -222,6 +222,9 @@ namespace SharedLibraryCore.RCon
|
||||
throw new NetworkException($"Unexpected error while sending data to server - {e.Message}");
|
||||
}
|
||||
|
||||
if (!waitForResponse)
|
||||
return await Task.FromResult(new string[] { "" });
|
||||
|
||||
var connectionState = new ConnectionState(ServerConnection);
|
||||
|
||||
retryReceive:
|
||||
@ -233,11 +236,6 @@ namespace SharedLibraryCore.RCon
|
||||
|
||||
if (!success)
|
||||
{
|
||||
// t6m doesn't respond to set requests
|
||||
if (type == StaticHelpers.QueryType.DVAR && parameters.Contains("set "))
|
||||
{
|
||||
return await Task.FromResult(new string[] { "" });
|
||||
}
|
||||
|
||||
FailedReceives++;
|
||||
#if DEBUG
|
||||
|
@ -8,6 +8,7 @@ using SharedLibraryCore.Helpers;
|
||||
using SharedLibraryCore.Objects;
|
||||
using SharedLibraryCore.Dtos;
|
||||
using SharedLibraryCore.Configuration;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
|
||||
namespace SharedLibraryCore
|
||||
{
|
||||
@ -25,7 +26,7 @@ namespace SharedLibraryCore
|
||||
T6M,
|
||||
}
|
||||
|
||||
public Server(Interfaces.IManager mgr, ServerConfiguration config)
|
||||
public Server(IManager mgr, ServerConfiguration config)
|
||||
{
|
||||
Password = config.Password;
|
||||
IP = config.IPAddress;
|
||||
@ -313,6 +314,7 @@ namespace SharedLibraryCore
|
||||
public bool CustomCallback { get; protected set; }
|
||||
public string WorkingDirectory { get; protected set; }
|
||||
public RCon.Connection RemoteConnection { get; protected set; }
|
||||
public IRConParser RconParser { get; protected set; }
|
||||
|
||||
// Internal
|
||||
protected string IP;
|
||||
|
@ -52,54 +52,6 @@ namespace SharedLibraryCore
|
||||
return newStr;
|
||||
}
|
||||
|
||||
public static List<Player> PlayersFromStatus(this Server sv, string[] Status)
|
||||
{
|
||||
List<Player> StatusPlayers = new List<Player>();
|
||||
|
||||
foreach (String S in Status)
|
||||
{
|
||||
String responseLine = S.Trim();
|
||||
|
||||
if (Regex.Matches(responseLine, @"\d+$", RegexOptions.IgnoreCase).Count > 0 && responseLine.Length > 72) // its a client line!
|
||||
{
|
||||
String[] playerInfo = responseLine.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
int cID = -1;
|
||||
int Ping = -1;
|
||||
|
||||
try
|
||||
{
|
||||
Ping = (sv.GameName != Game.T6M) ?
|
||||
Int32.Parse(playerInfo[2]) :
|
||||
Int32.Parse(playerInfo[3]);
|
||||
}
|
||||
|
||||
catch (FormatException) { }
|
||||
String cName = (sv.GameName != Game.T6M) ?
|
||||
Encoding.UTF8.GetString(Encoding.Convert(Encoding.UTF7, Encoding.UTF8, Encoding.UTF7.GetBytes(StripColors(responseLine.Substring(46, 18)).Trim()))) :
|
||||
Encoding.UTF8.GetString(Encoding.Convert(Encoding.UTF7, Encoding.UTF8, Encoding.UTF7.GetBytes(StripColors(responseLine.Substring(50, 15)).Trim())));
|
||||
long npID = sv.GameName != Game.T6M ?
|
||||
Regex.Match(responseLine, @"([a-z]|[0-9]){16}", RegexOptions.IgnoreCase).Value.ConvertLong() :
|
||||
playerInfo[4].ConvertLong();
|
||||
|
||||
int.TryParse(playerInfo[0], out cID);
|
||||
var regex = Regex.Match(responseLine, @"\d+\.\d+\.\d+.\d+\:\d{1,5}");
|
||||
#if DEBUG
|
||||
Ping = 1;
|
||||
#endif
|
||||
|
||||
int cIP = regex.Value.Split(':')[0].ConvertToIP();
|
||||
regex = Regex.Match(responseLine, @"[0-9]{1,2}\s+[0-9]+\s+");
|
||||
int score = (sv.GameName != Game.T6M) ?
|
||||
Int32.Parse(regex.Value.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[1]) :
|
||||
Int32.Parse(playerInfo[1]);
|
||||
Player P = new Player() { Name = cName, NetworkId = npID, ClientNumber = cID, IPAddress = cIP, Ping = Ping, Score = score };
|
||||
StatusPlayers.Add(P);
|
||||
}
|
||||
}
|
||||
|
||||
return StatusPlayers;
|
||||
}
|
||||
|
||||
public static Player.Permission MatchPermission(String str)
|
||||
{
|
||||
String lookingFor = str.ToLower();
|
||||
@ -393,115 +345,23 @@ namespace SharedLibraryCore
|
||||
|
||||
public static string PromptString(string question)
|
||||
{
|
||||
Console.Write($"{question}: ");
|
||||
|
||||
string response;
|
||||
do
|
||||
{
|
||||
Console.Write($"{question}: ");
|
||||
response = Console.ReadLine();
|
||||
} while (string.IsNullOrWhiteSpace(response));
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public static async Task<DVAR<T>> GetDvarAsync<T>(this Server server, string dvarName)
|
||||
{
|
||||
string[] LineSplit = null;
|
||||
bool t6m = false;
|
||||
if (server.GameName == Game.UKN)
|
||||
{
|
||||
LineSplit = await server.RemoteConnection.SendQueryAsync(QueryType.COMMAND, $"get {dvarName}");
|
||||
if (LineSplit.Where(l => l.Contains("Unknown command")).Count() > 0)
|
||||
{
|
||||
LineSplit = await server.RemoteConnection.SendQueryAsync(QueryType.DVAR, dvarName);
|
||||
}
|
||||
public static async Task<Dvar<T>> GetDvarAsync<T>(this Server server, string dvarName) => await server.RconParser.GetDvarAsync<T>(server.RemoteConnection, dvarName);
|
||||
|
||||
else
|
||||
t6m = true;
|
||||
}
|
||||
public static async Task SetDvarAsync(this Server server, string dvarName, object dvarValue) => await server.RconParser.SetDvarAsync(server.RemoteConnection, dvarName, dvarValue);
|
||||
|
||||
else if (server.GameName == Game.T6M)
|
||||
{
|
||||
LineSplit = await server.RemoteConnection.SendQueryAsync(QueryType.COMMAND, $"get {dvarName}");
|
||||
}
|
||||
public static async Task<string[]> ExecuteCommandAsync(this Server server, string commandName) => await server.RconParser.ExecuteCommandAsync(server.RemoteConnection, commandName);
|
||||
|
||||
else
|
||||
{
|
||||
LineSplit = await server.RemoteConnection.SendQueryAsync(QueryType.DVAR, dvarName); ;
|
||||
}
|
||||
public static async Task<List<Player>> GetStatusAsync(this Server server) => await server.RconParser.GetStatusAsync(server.RemoteConnection);
|
||||
|
||||
if (server.GameName != Game.T6M && !t6m)
|
||||
{
|
||||
if (LineSplit.Length < 3)
|
||||
{
|
||||
var e = new Exceptions.DvarException($"DVAR \"{dvarName}\" does not exist");
|
||||
e.Data["dvar_name"] = dvarName;
|
||||
throw e;
|
||||
}
|
||||
|
||||
string[] ValueSplit = LineSplit[1].Split(new char[] { '"' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (ValueSplit.Length != 5)
|
||||
{
|
||||
var e = new Exceptions.DvarException($"DVAR \"{dvarName}\" does not exist");
|
||||
e.Data["dvar_name"] = dvarName;
|
||||
throw e;
|
||||
}
|
||||
|
||||
string DvarName = Regex.Replace(ValueSplit[0], @"\^[0-9]", "");
|
||||
string DvarCurrentValue = Regex.Replace(ValueSplit[2], @"\^[0-9]", "");
|
||||
string DvarDefaultValue = Regex.Replace(ValueSplit[4], @"\^[0-9]", "");
|
||||
|
||||
return new DVAR<T>(DvarName) { Value = (T)Convert.ChangeType(DvarCurrentValue, typeof(T)) };
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (LineSplit.Length < 2)
|
||||
{
|
||||
var e = new Exceptions.DvarException($"DVAR \"{dvarName}\" does not exist");
|
||||
e.Data["dvar_name"] = dvarName;
|
||||
throw e;
|
||||
}
|
||||
|
||||
string[] ValueSplit = LineSplit[1].Split(new char[] { '"' });
|
||||
|
||||
if (ValueSplit.Length == 0)
|
||||
{
|
||||
var e = new Exceptions.DvarException($"DVAR \"{dvarName}\" does not exist");
|
||||
e.Data["dvar_name"] = dvarName;
|
||||
throw e;
|
||||
}
|
||||
|
||||
string DvarName = dvarName;
|
||||
string DvarCurrentValue = Regex.Replace(ValueSplit[1], @"\^[0-9]", "");
|
||||
|
||||
return new DVAR<T>(DvarName) { Value = (T)Convert.ChangeType(DvarCurrentValue, typeof(T)) };
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static async Task SetDvarAsync(this Server server, string dvarName, object dvarValue)
|
||||
{
|
||||
await server.RemoteConnection.SendQueryAsync(QueryType.DVAR, $"set {dvarName} {dvarValue}");
|
||||
}
|
||||
|
||||
public static async Task<string[]> ExecuteCommandAsync(this Server server, string commandName)
|
||||
{
|
||||
return (await server.RemoteConnection.SendQueryAsync(QueryType.COMMAND, commandName)).Skip(1).ToArray();
|
||||
}
|
||||
|
||||
public static async Task<List<Player>> GetStatusAsync(this Server server)
|
||||
{
|
||||
#if DEBUG && DEBUG_PLAYERS
|
||||
string[] response = await Task.Run(() => System.IO.File.ReadAllLines("players.txt"));
|
||||
#else
|
||||
string[] response = await server.RemoteConnection.SendQueryAsync(QueryType.DVAR, "status");
|
||||
#endif
|
||||
return server.PlayersFromStatus(response);
|
||||
}
|
||||
|
||||
public static bool IsRunningOnMono() => Type.GetType("Mono.Runtime") != null;
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
|
||||
<nav class="navbar navbar-expand-md navbar-dark bg-dark">
|
||||
@Html.ActionLink("IW4MAdmin", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
@ -101,7 +101,7 @@
|
||||
</div>
|
||||
<!-- End Action Modal -->
|
||||
|
||||
<div class="container pt-0 pb-4 pl-4 pr-4">
|
||||
<div class="container p-4">
|
||||
@RenderBody()
|
||||
<footer></footer>
|
||||
</div>
|
||||
|
15
WebfrontCore/wwwroot/css/bootstrap-custom.scss
vendored
15
WebfrontCore/wwwroot/css/bootstrap-custom.scss
vendored
@ -17,10 +17,6 @@ a.nav-link {
|
||||
padding: $spacer * 1.5;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin-top: 90px;
|
||||
}
|
||||
|
||||
.server-history-row {
|
||||
height: 100px;
|
||||
padding: 0 !important;
|
||||
@ -100,11 +96,11 @@ form * {
|
||||
|
||||
@-webkit-keyframes rotation {
|
||||
from {
|
||||
-webkit-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
}
|
||||
|
||||
to {
|
||||
-webkit-transform: rotate(359deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,16 +108,17 @@ form * {
|
||||
position: fixed !important;
|
||||
left: 50%;
|
||||
top: 50% !important;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 100;
|
||||
margin-left: -37px;
|
||||
margin-top: -37px;
|
||||
color: $primary;
|
||||
z-index: 100;
|
||||
font-size: 4rem;
|
||||
-webkit-animation: rotation 1s infinite linear;
|
||||
background-color: $black;
|
||||
background-color: rgba(0, 0,0, 0.5);
|
||||
border-radius: 40px;
|
||||
padding: 5px;
|
||||
visibility:hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.input-border-transition {
|
||||
|
@ -1,3 +1,8 @@
|
||||
Version 2.0:
|
||||
CHANGELOG:
|
||||
-migrated all projects and remaining plugins to .NET Core 2
|
||||
-database provider = SQLite
|
||||
|
||||
Version 1.6:
|
||||
CHANGELOG:
|
||||
-migrated from SQLite to EntityFramework
|
||||
|
Loading…
Reference in New Issue
Block a user