more plugin tweaks, added console interface!

This commit is contained in:
RaidMax 2015-08-22 01:04:30 -05:00
parent 7ca0b654ac
commit d42a329097
24 changed files with 235 additions and 166 deletions

View File

@ -107,7 +107,6 @@
<Compile Include="Command.cs" />
<Compile Include="Connection.cs" />
<Compile Include="Heartbeat.cs" />
<Compile Include="Helpers.cs" />
<Compile Include="Main.cs" />
<Compile Include="Manager.cs" />
<Compile Include="Plugins.cs" />
@ -141,7 +140,7 @@
<Content Include="plugins\SamplePlugin.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="plugins\Webfront Plugin.dll">
<Content Include="plugins\WebfrontPlugin.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="version.txt">
@ -157,7 +156,7 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="webfront\graph.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="webfront\header.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>

View File

@ -44,6 +44,19 @@ namespace IW4MAdmin
if (serverManager.getServers() != null)
Program.getManager().mainLog.Write("IW4M Now Initialized!", Log.Level.Production);
String userInput;
Server serverToExecuteOn = serverManager.getServers()[0];
Player Origin = new Player("IW4MAdmin Console", "", -1, Player.Permission.Console, -1, "", 0, "");
do
{
userInput = Console.ReadLine();
Event E = new Event(Event.GType.Say, userInput, Origin, null, serverToExecuteOn);
Origin.lastEvent = E;
serverToExecuteOn.processEvent(E);
Console.Write('>');
} while (userInput != null && serverManager.isRunning());
serverMGRThread.Join();
serverManager.mainLog.Write("Shutting down IW4MAdmin...", Log.Level.Debug);

View File

@ -60,16 +60,20 @@ namespace IW4MAdmin
if (S == null)
continue;
if (!isIW4MStillRunning(S.pID()))
if (!isIW4MStillRunning(S.pID()) || !S.isRunning)
{
Thread Defunct = ThreadList[S.pID()];
if (!S.isRunning)
Utilities.shutdownInterface(S.pID());
S.isRunning = false;
if (Defunct != null)
{
Defunct.Join();
ThreadList[S.pID()] = null;
}
mainLog.Write("Server with PID #" + S.pID() + " no longer appears to be running.", Log.Level.Debug);
mainLog.Write("Server with PID #" + S.pID() + " can no longer be monitored.", Log.Level.Debug);
activePIDs.Remove(S.pID());
defunctServers.Add(S);
}
@ -98,6 +102,11 @@ namespace IW4MAdmin
ThreadList[T.Key].Join();
}
public bool isRunning()
{
return activePIDs.Count != 0;
}
public List<Server> getServers()
{
return Servers;

View File

@ -40,6 +40,7 @@ namespace IW4MAdmin
assemblies.Add(assembly);
}
int totalLoaded = 0;
foreach (Assembly Plugin in assemblies)
{
if (Plugin != null)
@ -47,13 +48,14 @@ namespace IW4MAdmin
Type[] types = Plugin.GetTypes();
foreach(Type assemblyType in types)
{
if(assemblyType.IsClass && assemblyType.BaseType.Name == "Notify")
if(assemblyType.IsClass && assemblyType.BaseType.Name == "Plugin")
{
Object notifyObject = Activator.CreateInstance(assemblyType);
Plugin newNotify = (Plugin)notifyObject;
potentialNotifies.Add(newNotify);
newNotify.onLoad();
Program.getManager().mainLog.Write("Loaded event plugin \"" + assemblyType.Name + "\"", Log.Level.All);
Program.getManager().mainLog.Write("Loaded plugin \"" + newNotify.Name + "\"" + " [" + newNotify.Version + "]", Log.Level.Debug);
totalLoaded++;
}
else if (assemblyType.IsClass && assemblyType.BaseType.Name == "Command")
@ -61,14 +63,14 @@ namespace IW4MAdmin
Object commandObject = Activator.CreateInstance(assemblyType);
Command newCommand = (Command)commandObject;
potentialCommands.Add(newCommand);
Program.getManager().mainLog.Write("Loaded command plugin \"" + newCommand.Name + "\"", Log.Level.All);
Program.getManager().mainLog.Write("Registered command \"" + newCommand.Name + "\"", Log.Level.Debug);
totalLoaded++;
}
else
Program.getManager().mainLog.Write("Ignoring invalid plugin \"" + assemblyType.Name + "\"", Log.Level.All);
}
}
}
Program.getManager().mainLog.Write("Loaded " + totalLoaded + " plugins.", Log.Level.Production);
return true;
}
}

View File

@ -14,7 +14,6 @@ namespace IW4MAdmin
{
public IW4MServer(string address, int port, string password, int H, int PID) : base(address, port, password, H, PID)
{
playerHistory = new Queue<pHistory>();
commandQueue = new Queue<string>();
}
@ -429,8 +428,22 @@ namespace IW4MAdmin
{
Event curEvent = events.Peek();
processEvent(curEvent);
foreach (Notify E in PluginImporter.potentialNotifies)
E.onEvent(curEvent);
foreach (Plugin P in PluginImporter.potentialNotifies)
{
try
{
P.onEvent(curEvent);
}
catch (Exception Except)
{
Log.Write(String.Format("The plugin \"{0}\" (v{1}) generated an error. ( see log )", P.Name, P.Version), Log.Level.Production);
Log.Write(String.Format("Error Message: {0}", Except.Message), Log.Level.Debug);
Log.Write(String.Format("Error Trace: {0}", Except.StackTrace), Log.Level.Debug);
continue;
}
}
events.Dequeue();
}
if (commandQueue.Count > 0)
@ -465,6 +478,7 @@ namespace IW4MAdmin
#if DEBUG == false
Broadcast("IW4M Admin is now ^2ONLINE");
int numExceptions = 0;
#endif
while (isRunning)
@ -480,7 +494,7 @@ namespace IW4MAdmin
{
while (playerHistory.Count > 144 ) // 12 times a minute for 12 hours
playerHistory.Dequeue();
playerHistory.Enqueue(new pHistory(lastCount, clientnum));
playerHistory.Enqueue(new PlayerHistory(lastCount, clientnum));
playerCountStart = DateTime.Now;
}
@ -493,21 +507,9 @@ namespace IW4MAdmin
else
nextMessage++;
start = DateTime.Now;
//if (timesFailed <= 3)
// HB.Send();
String checkVer = new Connection("http://raidmax.org/IW4M/Admin/version.php").Read();
double checkVerNum;
double.TryParse(checkVer, out checkVerNum);
if (checkVerNum != Program.Version && checkVerNum != 0 && !checkedForOutdate)
{
messages.Add("^5IW4M Admin ^7is outdated. Please ^5update ^7to version " + checkVerNum);
checkedForOutdate = true;
}
}
if ((DateTime.Now - lastPoll).Milliseconds > 750)
if ((DateTime.Now - lastPoll).Milliseconds > 300)
{
int numberRead = 0;
int activeClients = 0;
@ -583,8 +585,18 @@ namespace IW4MAdmin
#if DEBUG == false
catch (Exception E)
{
Log.Write("Something unexpected occured. Hopefully we can ignore it :)", Log.Level.All);
continue;
numExceptions++;
Log.Write("Unexpected error on \"" + hostname + "\"", Log.Level.Debug);
Log.Write("Error Message: " + E.Message, Log.Level.Debug);
Log.Write("Error Trace: " + E.StackTrace, Log.Level.Debug);
if (numExceptions < 30)
continue;
else
{
Log.Write("Maximum number of unhandled exceptions reached for \"" + hostname + "\"", Log.Level.Production);
events.Enqueue(new Event(Event.GType.Stop, "Monitoring stopping because of max exceptions reached", null, null, this));
isRunning = false;
}
}
#endif
@ -596,20 +608,20 @@ namespace IW4MAdmin
override public bool intializeBasics()
{
try
{
// inject our dll
if (!Utilities.initalizeInterface(PID))
{
Log.Write("Could not load IW4MAdmin interface!", Log.Level.Debug);
return false;
}
try
{
// inject our dll
if (!Utilities.initalizeInterface(PID))
{
Log.Write("Could not load IW4MAdmin interface!", Log.Level.Debug);
return false;
}
// basic info dvars
hostname = SharedLibrary.Utilities.stripColors(getDvar("sv_hostname").current);
mapname = getDvar("mapname").current;
IW_Ver = getDvar("shortversion").current;
maxClients = -1;
hostname = SharedLibrary.Utilities.stripColors(getDvar("sv_hostname").current);
mapname = getDvar("mapname").current;
IW_Ver = getDvar("shortversion").current;
maxClients = -1;
Int32.TryParse(getDvar("party_maxplayers").current, out maxClients);
if (maxClients == -1)
@ -618,46 +630,47 @@ namespace IW4MAdmin
return false;
}
Gametype = getDvar("g_gametype").current;
Gametype = getDvar("g_gametype").current;
// important log variables
Basepath = getDvar("fs_basepath").current;
Mod = getDvar("fs_game").current;
logPath = getDvar("g_log").current;
int oneLog = -1;
Basepath = getDvar("fs_basepath").current;
Mod = getDvar("fs_game").current;
logPath = getDvar("g_log").current;
int oneLog = -1;
Int32.TryParse(getDvar("iw4m_onelog").current, out oneLog);
if (oneLog == -1)
{
Log.Write("Could not get iw4m_onelog value", Log.Level.Debug);
return false;
}
if (oneLog == -1)
{
Log.Write("Could not get iw4m_onelog value", Log.Level.Debug);
return false;
}
// our settings
setDvar("sv_kickBanTime", "3600"); // 1 hour
setDvar("g_logSync", "1"); // yas
setDvar("sv_kickBanTime", "3600"); // 1 hour
setDvar("g_logSync", "1"); // yas
if (Mod == String.Empty || oneLog == 1)
logPath = Basepath + '\\' + "m2demo" + '\\' + logPath;
else
logPath = Basepath + '\\' + Mod + '\\' + logPath;
if (Mod == String.Empty || oneLog == 1)
logPath = Basepath + '\\' + "m2demo" + '\\' + logPath;
else
logPath = Basepath + '\\' + Mod + '\\' + logPath;
if (!File.Exists(logPath))
{
Log.Write("Gamelog `" + logPath + "` does not exist!", Log.Level.All);
return false;
}
if (!File.Exists(logPath))
{
Log.Write("Gamelog `" + logPath + "` does not exist!", Log.Level.All);
return false;
}
logFile = new IFile(logPath);
Log.Write("Log file is " + logPath, Log.Level.Debug);
Log.Write("Now monitoring " + getName(), Log.Level.Production);
events.Enqueue(new Event(Event.GType.Start, "Server started", null, null, this));
Bans = clientDB.getBans();
return true;
logFile = new IFile(logPath);
Log.Write("Log file is " + logPath, Log.Level.Debug);
Log.Write("Now monitoring " + getName(), Log.Level.Production);
events.Enqueue(new Event(Event.GType.Start, "Server started", null, null, this));
Bans = clientDB.getBans();
return true;
}
catch (Exception E)
{
Log.Write("Error during initialization - " + E.Message +"--" + E.StackTrace, Log.Level.All);
Log.Write("Error during initialization - " + E.Message + "--" + E.StackTrace, Log.Level.All);
return false;
}
}
@ -696,18 +709,6 @@ namespace IW4MAdmin
if (E.Origin != E.Target)
{
/*E.Origin.stats.Kills += 1;
E.Origin.stats.updateKDR();
E.Target.stats.Deaths += 1;
E.Target.stats.updateKDR();
//Skills.updateNewSkill(E.Origin, E.Target);
statDB.updatePlayer(E.Origin);
statDB.updatePlayer(E.Target);
totalKills++;*/
Log.Write(E.Origin.Name + " killed " + E.Target.Name + " with a " + E.Data, Log.Level.Debug);
events.Enqueue(new Event(Event.GType.Death, E.Data, E.Target, null, this));
}
@ -720,7 +721,6 @@ namespace IW4MAdmin
if (E.Type == Event.GType.Say)
{
if (E.Data.Length < 2) // ITS A LIE!
return false;
@ -738,12 +738,53 @@ namespace IW4MAdmin
return false;
}
if (E.Data.Substring(0, 1) != "!") // Not a command so who gives an F?
if (E.Data.Substring(0, 1) == "!" || E.Origin.Level == Player.Permission.Console)
{
Command C = E.isValidCMD(commands);
if (C != null)
{
C = processCommand(E, C);
if (C != null)
{
if (C.needsTarget && E.Target == null)
{
Log.Write("Requested event requiring target does not have a target!", Log.Level.Debug);
return false;
}
try
{
C.Execute(E);
}
catch (Exception Except)
{
Log.Write(String.Format("A command request \"{0}\" generated an error.", C.Name, Log.Level.Debug));
Log.Write(String.Format("Error Message: {0}", Except.Message), Log.Level.Debug);
Log.Write(String.Format("Error Trace: {0}", Except.StackTrace), Log.Level.Debug);
return false;
}
return true;
}
else
{
Log.Write("Player didn't properly enter command - " + E.Origin.Name, Log.Level.Debug);
return true;
}
}
else
E.Origin.Tell("You entered an invalid command!");
}
else // Not a command so who gives an F?
{
E.Data = SharedLibrary.Utilities.stripColors(SharedLibrary.Utilities.cleanChars(E.Data));
if (E.Data.Length > 50)
E.Data = E.Data.Substring(0, 50) + "...";
while (chatHistory.Count > Math.Ceiling((double)clientnum/2))
while (chatHistory.Count > Math.Ceiling((double)clientnum / 2))
chatHistory.RemoveAt(0);
chatHistory.Add(new Chat(E.Origin, E.Data, DateTime.Now));
@ -751,32 +792,6 @@ namespace IW4MAdmin
return true;
}
Command C = E.isValidCMD(commands);
if (C != null)
{
C = processCommand(E, C);
if (C != null)
{
if (C.needsTarget && E.Target == null)
{
Log.Write("Requested event requiring target does not have a target!", Log.Level.Debug);
return false;
}
C.Execute(E);
return true;
}
else
{
Log.Write("Player didn't properly enter command - " + E.Origin.Name, Log.Level.Debug);
return true;
}
}
else
E.Origin.Tell("You entered an invalid command!");
return true;
}
@ -784,35 +799,13 @@ namespace IW4MAdmin
{
Log.Write("New map loaded - " + clientnum + " active players", Log.Level.Debug);
Dictionary<String, String> infoResponseDict = new Dictionary<String, String>();
String[] infoResponse = E.Data.Split('\\');
for (int i = 0; i < infoResponse.Length; i++)
{
if (i % 2 == 0 || infoResponse[i] == String.Empty)
continue;
infoResponseDict.Add(infoResponse[i], infoResponse[i + 1]);
}
String newMapName = null;
infoResponseDict.TryGetValue("mapname", out newMapName);
if (newMapName != null)
{
try
{
Map newMap = maps.Find(m => m.Name.Equals(newMapName));
mapname = newMap.Alias;
}
catch (Exception)
{
Log.Write(mapname + " doesn't appear to be in the maps.cfg", Log.Level.Debug);
}
}
String newMapName = getDvar("mapname").current;
Map newMap = maps.Find(m => m.Name.Equals(newMapName));
if (newMap != null)
mapname = newMap.Alias;
else
Log.Write("Could not get new mapname from InitGame line!", Log.Level.Debug);
mapname = newMapName;
return true;
}
@ -941,8 +934,6 @@ namespace IW4MAdmin
commands.Add(new Find("find", "find player in database. syntax: !find <player>", "f", Player.Permission.SeniorAdmin, 1, false));
commands.Add(new Rules("rules", "list server rules. syntax: !rules", "r", Player.Permission.User, 0, false));
commands.Add(new PrivateMessage("privatemessage", "send message to other player. syntax: !pm <player> <message>", "pm", Player.Permission.User, 2, true));
//commands.Add(new _Stats("stats", "view your stats or another player's. syntax: !stats", "xlrstats", Player.Permission.User, 0, true));
//commands.Add(new TopStats("topstats", "view the top 4 players on this server. syntax: !topstats", "xlrtopstats", Player.Permission.User, 0, false));
commands.Add(new Reload("reload", "reload configurations. syntax: !reload", "reload", Player.Permission.Owner, 0, false));
commands.Add(new Balance("balance", "balance teams. syntax !balance", "bal", Player.Permission.Moderator, 0, false));
commands.Add(new GoTo("goto", "teleport to selected player. syntax !goto", "go", Player.Permission.SeniorAdmin, 1, true));
@ -962,7 +953,6 @@ namespace IW4MAdmin
}
//Objects
public Queue<pHistory> playerHistory;
private Queue<String> commandQueue;
//Info

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -55,3 +55,4 @@ function drawChart() {
chart.draw(data, options);
}
</script>
{{GRAPH}}

View File

@ -414,8 +414,10 @@
<script type="text/javascript">
function searchPlayerName() {
var nameValue = document.getElementById("search_playerName").value;
if (nameValue.length > 0)
if (nameValue.length > 3)
window.location.href = ("/player?query=" + encodeURIComponent(nameValue));
else
alert("Please enter at least 4 characters of the name");
}
</script>
<div id="player_search">

Binary file not shown.

View File

@ -77,7 +77,7 @@ namespace SamplePlugin
}
}
public class Stats : Notify
public class Stats : Plugin
{
public static StatsDB playerStats { get; private set; }
@ -108,6 +108,7 @@ namespace SamplePlugin
victimStats.Deaths++;
victimStats.KDR = victimStats.Kills / victimStats.Deaths;
playerStats.updateStats(Victim, victimStats);
}
}
@ -116,6 +117,16 @@ namespace SamplePlugin
{
playerStats = new StatsDB("stats.rm");
}
public override string Name
{
get { return "Basic Stats"; }
}
public override float Version
{
get { return 0.1f; }
}
}
public class StatsDB : Database

View File

@ -58,21 +58,15 @@ namespace SharedLibrary
public Command isValidCMD(List<Command> list)
{
if (this.Data.Substring(0, 1) == "!")
string[] cmd = this.Data.Substring(1, this.Data.Length - 1).Split(' ');
foreach (Command C in list)
{
string[] cmd = this.Data.Substring(1, this.Data.Length - 1).Split(' ');
foreach (Command C in list)
{
if (C.Name == cmd[0].ToLower() || C.Alias == cmd[0].ToLower())
return C;
}
return null;
if (C.Name == cmd[0].ToLower() || C.Alias == cmd[0].ToLower())
return C;
}
else
return null;
return null;
}
public static Event requestEvent(String[] line, Server SV)

View File

@ -3,11 +3,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace IW4MAdmin
namespace SharedLibrary
{
class pHistory
public class PlayerHistory
{
public pHistory(DateTime w, int cNum)
public PlayerHistory(DateTime w, int cNum)
{
When = w;
Players = cNum;

View File

@ -31,6 +31,7 @@ namespace SharedLibrary
SeniorAdmin = 4,
Owner = 5,
Creator = 6,
Console = 7,
}
public Player(string n, string id, int num, int l)

View File

@ -8,10 +8,10 @@ namespace SharedLibrary
public abstract class Plugin
{
public abstract void onLoad();
}
public abstract class Notify : Plugin
{
public abstract void onEvent(Event E);
//for logging purposes
public abstract string Name { get; }
public abstract float Version { get; }
}
}

View File

@ -29,6 +29,7 @@ namespace SharedLibrary
Macros = new Dictionary<String, Object>();
Reports = new List<Report>();
statusPlayers = new Dictionary<string, Player>();
playerHistory = new Queue<PlayerHistory>();
chatHistory = new List<Chat>();
lastWebChat = DateTime.Now;
nextMessage = 0;
@ -240,6 +241,13 @@ namespace SharedLibrary
{
if (Target.clientID > -1)
executeCommand("tellraw " + Target.clientID + " " + Message + "^7");
if (Target.Level == Player.Permission.Console)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine(Utilities.stripColors(Message));
Console.ForegroundColor = ConsoleColor.Gray;
}
}
/// <summary>
@ -474,6 +482,7 @@ namespace SharedLibrary
public int totalKills = 0;
public List<Report> Reports;
public List<Chat> chatHistory;
public Queue<PlayerHistory> playerHistory { get; private set; }
//Info
protected String IP;

View File

@ -55,6 +55,7 @@
<Compile Include="Dvar.cs" />
<Compile Include="Log.cs" />
<Compile Include="Map.cs" />
<Compile Include="Miscellaneous.cs" />
<Compile Include="Player.cs" />
<Compile Include="Plugin.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

View File

@ -171,7 +171,15 @@ namespace SharedLibrary
{
String Match = M.Value;
String Identifier = M.Value.Substring(2, M.Length - 4);
String Replacement = Dict[Identifier].ToString();
Object foundVal;
Dict.TryGetValue(Identifier, out foundVal);
String Replacement;
if (foundVal != null)
Replacement = foundVal.ToString();
else
Replacement = "";
str = str.Replace(Match, Replacement);
}

View File

@ -367,6 +367,25 @@ namespace Webfront_Plugin
return Input.Replace(Macro, buffer.ToString());
}
if (Looking == "GRAPH")
{
StringBuilder buffer = new StringBuilder();
buffer.Append("<script type='text/javascript' src='//www.google.com/jsapi'></script><div id='chart_div'></div>");
buffer.Append("<script> var players = [");
int count = 1;
List<PlayerHistory> run = Servers[0].playerHistory.ToList();
foreach (PlayerHistory i in run) //need to reverse for proper timeline
{
buffer.AppendFormat("[new Date({0}, {1}, {2}, {3}, {4}), {5}]", i.When.Year, i.When.Month - 1, i.When.Day, i.When.Hour, i.When.Minute, i.Players);
if (count < run.Count)
buffer.Append(",\n");
count++;
}
buffer.Append("];\n");
buffer.Append("</script>");
return Input.Replace(Macro, buffer.ToString());
}
if (Looking == "TITLE")
return Input.Replace(Macro, "IW4MAdmin by RaidMax");
@ -399,7 +418,7 @@ namespace Webfront_Plugin
break;
case "graph":
requestedPage = new graph();
break;
return processTemplate(requestedPage.Load(), request.QueryString);
case "stats":
requestedPage = new stats();
break;

View File

@ -4,7 +4,7 @@ using System.Threading;
namespace Webfront_Plugin
{
public class Webfront : Notify
public class Webfront : Plugin
{
private static Manager webManager;
@ -33,5 +33,15 @@ namespace Webfront_Plugin
webManagerThread.Start();
}
public override String Name
{
get { return "Webfront"; }
}
public override float Version
{
get { return 0.1f; }
}
}
}

View File

@ -52,7 +52,7 @@
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>copy /Y "$(TargetDir)$(TargetName).dll" "$(SolutionDir)Admin\plugins\$(TargetName).dll"</PostBuildEvent>
<PostBuildEvent>copy /Y "$(TargetDir)$(TargetName).dll" "$(SolutionDir)Admin\plugins\WebfrontPlugin.dll"</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.