Created
January 6, 2015 23:06
-
-
Save copygirl/9e019a5651e7e6007443 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Threading; | |
namespace obsidianUpdater.Utility | |
{ | |
public class ServerSniffer | |
{ | |
private StreamReader _reader; | |
private int _progress = 0; | |
public ServerStatus Status { get; private set; } | |
public ServerSniffer(StreamReader reader) | |
{ | |
_reader = reader; | |
} | |
public void WaitUntilRunning() | |
{ | |
Status = ServerStatus.Starting; | |
Console.WriteLine(); | |
while (Status < ServerStatus.Running) | |
ParseLine(_reader.ReadLine()); | |
if (Status > ServerStatus.Running) | |
throw new Exception("There was an error while starting up the server."); | |
} | |
public void WaitUntilStopped() | |
{ | |
Status = ServerStatus.Running; | |
Console.WriteLine(); | |
while (Status < ServerStatus.Stopped) | |
ParseLine(_reader.ReadLine()); | |
} | |
public void ParseLine(string line) | |
{ | |
if (line == null) { | |
Thread.Sleep(0); | |
return; | |
} | |
// TODO: Detect crashing. | |
switch (Status) { | |
case ServerStatus.Starting: | |
if (_startup[_progress](line, _progress, _startup.Length - 1) && (++_progress >= _startup.Length)) | |
Status = ServerStatus.Running; | |
break; | |
case ServerStatus.Running: | |
if (UpdateStatus(LookForText(line, 44, "Sending event FMLServerStoppingEvent"), 0.5F, "Server stopping")) | |
Status = ServerStatus.Stopping; | |
break; | |
case ServerStatus.Stopping: | |
if (UpdateStatus(LookForText(line, 44, "Sending event FMLServerStoppedEvent"), 1.0F, "Server stopped!")) | |
Status = ServerStatus.Stopped; | |
break; | |
} | |
} | |
private static readonly Func<string, int, int, bool>[] _startup = new Func<string, int, int, bool>[]{ | |
LookForText(31, "Forge Mod Loader version", "FML initializing"), | |
LookForText(51, "Attempting early MinecraftForge initialization", "Forge initializing"), | |
LookForEvent("FMLConstructionEvent", "Construction"), | |
LookForEvent("FMLConstructionEvent", "Construction", false) + | |
LookForEvent("FMLPreInitializationEvent", "Pre-initialization"), | |
LookForEvent("FMLPreInitializationEvent", "Pre-initialization", false) + | |
LookForEvent("FMLInitializationEvent", "Initialization"), | |
LookForEvent("FMLInitializationEvent", "Initialization", false) + | |
LookForEvent("FMLPostInitializationEvent", "Post-initialization"), | |
LookForEvent("FMLPostInitializationEvent", "Post-initialization", false) + | |
LookForText(40, "Injecting existing block and item data into this server instance", "Server about to start"), | |
LookForText(40, "Applying holder lookups", "Server starting"), | |
LookForText(44, "Sending event FMLServerStartedEvent", "Server started!") | |
}; | |
private static bool UpdateStatus(bool update, float progress, string status) | |
{ | |
if (!update) | |
return false; | |
string format; | |
if (!Console.IsOutputRedirected) { | |
Console.SetCursorPosition(Console.CursorLeft, Console.CursorTop - 1); | |
format = "[{0,3}%] {1,-" + (Console.WindowWidth - 7) + "}"; | |
} else | |
format = "[{0,3}%] {1}"; | |
Console.WriteLine(String.Format(format, (int)(progress * 100), status)); | |
return true; | |
} | |
private static bool LookForText(string line, int start, string message) | |
{ | |
return ((line.Length >= start + message.Length) && (line[0] == '[') && | |
(line.IndexOf(message, start, message.Length) >= 0)); | |
} | |
private static Func<string, int, int, bool> LookForText(int start, string message, string status) | |
{ | |
return (line, progress, maxProgress) => UpdateStatus( | |
LookForText(line, start, message), (float)progress / maxProgress, status); | |
} | |
private static bool LookForEvent(string line, string eventName, out string modName) | |
{ | |
int slashIndex; | |
modName = null; | |
return ((line.Length >= 63 + eventName.Length) && (line[33] == '[') && | |
((slashIndex = line.IndexOf('/', 35, line.Length - 63)) >= 0) && | |
(line.Length >= 60 + eventName.Length + (modName = line.Substring(34, slashIndex - 34)).Length * 3) && | |
(line.IndexOf("Sending event", 38 + modName.Length * 2, 13) >= 0) && | |
(line.IndexOf(eventName, 52 + modName.Length * 2, eventName.Length) >= 0)); | |
} | |
private static Func<string, int, int, bool> LookForEvent(string eventName, string status, bool last = true) | |
{ | |
string modName; | |
return (line, progress, maxProgress) => UpdateStatus( | |
LookForEvent(line, eventName, out modName), | |
(float)(progress - (last ? 0 : 1)) / maxProgress, status + ": " + modName); | |
} | |
} | |
public enum ServerStatus | |
{ | |
Unknown, | |
Starting, | |
Running, | |
Stopping, | |
Stopped, | |
Crashed | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment