namespace Remote_Control
{
public class CharThread
{
//Attached thread's PID info
public PID ThreadPIDInfo;
public static Dictionary<int, PID> PIDSessionDict = new Dictionary<int,PID>();
//Each instance of CharThread should hold a Character
private Characters _myChar;
//Should also have the thread crap it'll be using
private Thread _charThread;
//Instance
private static CharThread _instance;
//Array for splitting
private static char[] _splitArr = " ".ToCharArray();
//bool for the stats display
private static bool _isLaunched = false;
//Constructor should take the char this will be holding
public CharThread(Characters Character)
{
//Set our held character reference to whatever we're passed
_myChar = Character;
}
//Private constructor used for singleton
private CharThread()
{
}
public static void StartCharacter(CharThread charRef)
{
/*
CharThread._charThread = new Thread(new ParameterizedThreadStart(CharThread.Start));
CharThread._charThread.IsBackground = true;
CharThread._charThread.Start(_myChar);
*/
charRef._charThread = new Thread(new ThreadStart(charRef.Start));
charRef._charThread.IsBackground = true;
charRef._charThread.Start();
}
public static void StopCharacter()
{
}
//One public method to rule them all...
private static void Start()
{
//Launch the session
PID tempStruct = LaunchSession(_myChar);
//Load extensions and apps
LoadExtAndApps(tempStruct);
}
//Launch a session for our Character
private static PID LaunchSession(Characters Character)
{
PID tempPID = default(PID);
//If our character is a wow character...
if (Character is WoWCharacter)
{
//May be error-ish if configuration isn't correct.
//Start the process for an IS-session of WoW.
System.Diagnostics.Process.Start(String.Format("{0} open {1} {2}", Config.ISfilePath, Config.WoWProfile, Config.WoWProfileName));
Main.OnLogEvent(CharThread.Instance, String.Format("CharThread.LaunchSession(): Launched {0} for {1}, {2}", Config.ISfilePath, Config.WoWProfile, Config.WoWProfileName));
}
else if (Character is EVECharacter)
{
//Same as above, but for EVE
System.Diagnostics.Process.Start(String.Format("{0}\\InnerSpace.exe", Config.ISfilePath), String.Format("open \"{1}\" \"{2}\"", Config.ISfilePath, Config.EVEProfileName, Config.EVEProfile));
Main.OnLogEvent(CharThread.Instance, String.Format("CharThread.LaunchSession(): Launched {0} for {1}, {2}", Config.ISfilePath, Config.EVEProfileName, Config.EVEProfile));
}
_isLaunched = true;
//Give the thread a breather to get running, 5 seconds sounds good
Thread.Sleep(20000);
List<int> tempList = new List<int>();
//Go through and add all IS processes detected to a temp list
foreach (System.Diagnostics.Process p in System.Diagnostics.Process.GetProcessesByName("ExeFile"))
{
tempList.Add(p.Id);
Main.OnLogEvent(CharThread.Instance, String.Format("CharThread.LaunchSession(): Added {0} ({1}) to tempList.", p.Id, p.ToString()));
}
//Check our temp list against known list for differences
if (tempList.Count > MonitorThread.ListCount())
{
//For every PID in the temp list...
foreach (int i in tempList)
{
using (System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(i))
{
//If our window is an IS session, is one of the valid game .exe files, and isn't in the pidlist...
if (p.MainWindowTitle.Contains(" (Ctrl+Alt") && (p.ProcessName.Contains("ExeFile") || p.ToString().Contains("WoW.exe"))
&& !MonitorThread.ContainsID(p.Id))
{
//we've found a session that needs added.
string[] tempString = p.MainWindowTitle.Split(_splitArr);
// Should grab the # from is2 and similar for the session #
tempPID = new PID(p.Id, _myChar, int.Parse(tempString[0].Substring(2)));
//Add a new PID to our list of things to monitor
MonitorThread.AddToList(tempPID);
ThreadPIDInfo = tempPID;
//Make sure monitor is starting
MonitorThread.StartMonitoring();
Main.OnLogEvent(CharThread.Instance, String.Format("CharThread.LaunchThread(): Adding process {0} ({1}) to list.", p.ProcessName, p.Id));
}
}
}
}
return tempPID;
//We're launched. Move on to the next step.
}
//run, in a character's session, commands to load relevant ext's and apps
private static void LoadExtAndApps(PID infoStruct)
{
//Temporary semi-stub
//LavishScript.ExecuteCommand("relay {0} ext {1}", infoStruct.Session, "isxeve");
System.Diagnostics.Process.Start(String.Format("\"{0}\\{1}\"", Config.ISfilePath, "InnerSpace.exe"),
String.Format("relay is{0} ext {1}", infoStruct.Session, "isxeve"));
Main.OnLogEvent(CharThread.Instance, String.Format("CharThread.LoadExtAndApps(): Testing echo on is{0}", infoStruct.Session));
}
//Singleton property
public static CharThread Instance
{
get
{
if (_instance == null)
_instance = new CharThread();
return _instance;
}
}
//IsCharacterLaunched?
public static bool IsLaunched
{
get { return _isLaunched; }
}
}
public class MonitorThread
{
//Monitoring thread
private static Thread _monitorThread;
//dictionary of PIDs to watch
private static List<PID> MonitorList = new List<PID>();
//killswitch for monitoring
private static bool ShouldMonitor = false;
//Singleton reg
private static MonitorThread _instance;
private MonitorThread()
{
}
public static void AddToList(PID myPid)
{
MonitorList.Add(myPid);
}
public static void RemoveFromList(PID myPid)
{
MonitorList.Remove(myPid);
}
public static int ListCount()
{
return MonitorList.Count;
}
public static bool ContainsID(int ID)
{
foreach (PID p in MonitorList)
{
if (p.ID == ID)
return true;
}
return false;
}
//Flip the switch on and start a thread for it
public static void StartMonitoring()
{
if (ShouldMonitor == false)
{
Main.OnLogEvent(MonitorThread.Instance, "MonitorThread.Start(): Starting to monitor.");
ShouldMonitor = true;
_monitorThread = new Thread(new ThreadStart(MonitorThread.Monitor));
_monitorThread.IsBackground = true;
_monitorThread.Start();
}
}
//flip the switch off, effectively ending the thread
public static void StopMonitoring()
{
Main.OnLogEvent(MonitorThread.Instance, "MonitorThread.Stop(): Stopping!");
ShouldMonitor = false;
_monitorThread.Join();
}
//Do the monitoring
private static void Monitor()
{
//While I should monitor...
while (MonitorThread.ShouldMonitor)
{
//queue for changes to MonitorList
Queue<PID> changeQueue = new Queue<PID>();
//de-stubify later
foreach (PID pid in MonitorThread.MonitorList)
{
//If we can't find our process id, it's dead.
try
{
System.Diagnostics.Process.GetProcessById(pid.ID);
}
catch (ArgumentException)
{
Main.OnLogEvent(MonitorThread.Instance,
String.Format("MonitorThread.Monitor(): Lost {0}, re-launching", pid.ID));
//Start a new session for it
CharThread tempChar = new CharThread(pid.Character);
//Perform some cleanup by removing the old entry in the PID list
changeQueue.Enqueue(pid);
}
}
foreach (PID pid in changeQueue)
{
MonitorList.Remove(pid);
}
//Give our poor CPU some time off
Thread.Sleep(1000);
}
}
//Singleton instance
public static MonitorThread Instance
{
get
{
if (_instance == null)
_instance = new MonitorThread();
return _instance;
}
}
}
public struct PID
{
private int _id;
private Characters _character;
private int _session;
#region constructors
public PID(int id, Characters mychar, int session)
{
_id = id;
_character = mychar;
_session = session;
}
public PID(int id, int session)
{
_id = id;
_character = null;
_session = session;
}
#endregion
#region properties
public int ID
{
get { return _id; }
set { _id = value; }
}
public Characters Character
{
get { return _character; }
set { _character = value; }
}
public int Session
{
get { return _session; }
set { _session = value; }
}
#endregion
}
}