www.pudn.com > boogiebot.zip > BoogieCore.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Text.RegularExpressions;
using System.IO;
using System.Xml;
using Microsoft.Win32;
using Foole.Utils;
namespace BoogieBot.Common
{
// This class keeps track of various important objects. This class cannot be instantiated.
public abstract class BoogieCore
{
// Objects accessible to anyone
public static IniReader configFile; // For reading the bots .ini file
public static World world; // For accessing and modifying World Objects, including the player
public static MPQManager mpqManager; // For reading WoW's MPQ Files
public static TerrainManager terrainManager; // For accessing any terrain (maptile) data
public static WMOManager wmoManager; // For accessing any wmo data
public static DoodadManager doodadManager; // For accessing any doodad .m2 data
public static AreaTable areaTable; // For accessing areatable.dbc
public static MapTable mapTable; // For accessing map.dbc
public static CallBackLog Log; // For sending logtext to the UI
public static CallBackEvent Event; // For sending events to the UI
public static String wowPath; // Obvious
public static WoWVersion wowVersion; // WoW.exe / WoW.app version information
public static WoWType wowType; // WoWtype. (win32, OSX - ppc or x86, etc)
// Internal stuff
private static Boolean inited = false;
private static RealmListClient realmListClient; // My Pvt handle to the RealmListClient
private static WorldServerClient worldServerClient; // My Pvt handle to the WorldServerClient
private static Player player; // For accessing anything Player related.
private static String BoogieBotConfigFileName = "Config.ini";
// Initialize the Core :D
public static void InitCore(CallBackLog l, CallBackEvent e)
{
// Can't run this more than once
if (inited) return;
// We need to be able to Log stuff
if (l == null) return;
if (e == null) return;
Log = l;
Event = e;
Log(LogType.System, "BoogieBot.dll Initializing...");
// Initialize everything
try
{
if (!File.Exists(Environment.CurrentDirectory + "/" + BoogieCore.BoogieBotConfigFileName))
throw new FileNotFoundException("Configuration file not found.", BoogieCore.BoogieBotConfigFileName);
configFile = new IniReader(Environment.CurrentDirectory + "/Config.ini");
// NOTE: Set any OS specific variables so things can be done differently later, ie. Windows or Linux, etc.
OperatingSystem os = Environment.OSVersion;
switch(os.Platform)
{
case PlatformID.Win32Windows:
Log(LogType.System, "> Operating System: Windows");
break;
case PlatformID.Win32NT:
Log(LogType.System, "> Operating System: Windows NT");
break;
case PlatformID.Unix:
Log(LogType.System, "> Operating System: Unix");
break;
}
Log(LogType.System, "> OS Version: {0}.{1} (Build: {2}) ({3})", os.Version.Major, os.Version.Minor, os.Version.Build, os.ServicePack);
// Find WoW's Folder
wowPath = BoogieCore.getWowPath();
Log(LogType.System, "> WowPath: {0}", wowPath);
// Find WoW's Version
wowVersion = BoogieCore.getWoWVersion();
Log(LogType.System, "> WoW Version: World of Warcraft {0}.{1}.{2}.{3} ({4}) Found! Emulating this version.", wowVersion.major, wowVersion.minor, wowVersion.update, wowVersion.build, BoogieCore.WowTypeString);
// Construct some objects :)
mpqManager = new MPQManager(wowPath);
world = new World();
player = new Player();
/*terrainManager = new TerrainManager(); // -- I might move this to World
wmoManager = new WMOManager(); // -- And this
doodadManager = new DoodadManager(); // -- And this too!
areaTable = new AreaTable();
mapTable = new MapTable();*/
}
catch (Exception ex)
{
// Bot Start up Failed. Log why, and rethrow the exception.
Log(LogType.System, ex.Message);
Log(LogType.System, ex.StackTrace);
throw new Exception("BoogieBot.dll Init Failure.", ex);
}
inited = true;
Log(LogType.System, "BoogieBot.dll Initialized.");
}
//// Initialize the Core (WoWChat version) This excludes almost everything... since wowchat doesn't need much :P
//public static void InitCoreWoWChat(CallBackLog l, CallBackEvent e)
//{
// // Can't run this more than once
// if (inited) return;
// // We need to be able to Log stuff
// if (l == null) return;
// if (e == null) return;
// Log = l;
// Event = e;
// try
// {
// if (!File.Exists(Environment.CurrentDirectory + "/" + BoogieCore.WowChatConfigFileName))
// throw new FileNotFoundException("Configuration file not found.", BoogieCore.WowChatConfigFileName);
// configFile = new IniReader(Environment.CurrentDirectory + "/" + BoogieCore.WowChatConfigFileName);
// wowPath = BoogieCore.getWowPath();
// Log(LogType.System, "WowPath = {0}", wowPath);
// wowVersion = getWoWVersion();
// Log(LogType.System, "World of Warcraft {0}.{1}.{2}.{3} {4} Found! Emulating this version.", wowVersion.major, wowVersion.minor, wowVersion.update, wowVersion.build, BoogieCore.WowTypeString);
// world = new World();
// }
// catch (Exception ex)
// {
// // Bot Start up Failed. Log why, and rethrow the exception.
// Log(LogType.System, ex.Message);
// Log(LogType.System, ex.StackTrace);
// throw ex;
// }
// inited = true;
// wowchat = true;
// Log(LogType.System, "WoWChat Initialized.");
//}
public static Boolean ConnectToRealmListServer()
{
if (!inited)
throw new Exception("Run BoogieCore.Init() first.");
if (realmListClient != null)
throw new Exception("Already connected?");
IPAddress RLAddr;
string Address = configFile.ReadString("Connection", "Host", "us.logon.worldofwarcraft.com");
int Port = configFile.ReadInteger("Connection", "Port", 3724);
Regex DnsMatch = new Regex("[a-zA-Z]");
if (DnsMatch.IsMatch(Address))
RLAddr = Dns.GetHostEntry(Address).AddressList[0];
else
RLAddr = System.Net.IPAddress.Parse(Address);
IPEndPoint RLDest = new IPEndPoint(RLAddr, Port);
Log(LogType.System, "Attempting connection to Realm List Server at {0}.", Address);
try
{
realmListClient = new RealmListClient();
if (!realmListClient.Connect(RLDest))
{
realmListClient = null;
return false;
}
if (!realmListClient.Logon())
{
realmListClient = null;
return false;
}
}
catch (Exception ex)
{
BoogieCore.Log(LogType.System, "Failed to maintain connection with realm list server. Details below:\n{0}", ex.Message);
realmListClient = null;
return false;
}
return true;
}
public static void ConnectToWorldServer(IPEndPoint ep)
{
if (!inited)
throw new Exception("Run BoogieCore.Init() first.");
if (worldServerClient != null)
throw new Exception("Already connected?");
if (realmListClient.mUsername.Length > 2 && realmListClient.K.Length >= 16)
worldServerClient = new WorldServerClient(ep, realmListClient.mUsername, realmListClient.K);
else
Log(LogType.Error, "Unable to login to Game server! Unknown error occured. Check above!");
}
public static void Disconnect()
{
if (!inited)
throw new Exception("Run BoogieCore.Init() first.");
realmListClient = null;
if (worldServerClient != null)
{
// Stop the WS thread and wait till it ends.
worldServerClient.StopThread(false); // causes deadlocks atm.
worldServerClient = null;
}
}
// Properties
public static RealmListClient RealmListClient { get { return realmListClient; } }
public static WorldServerClient WorldServerClient { get { return worldServerClient; } }
public static World World { get { return world; } }
public static Player Player { get { return player; } }
public static String WowTypeString
{
get
{
switch (BoogieCore.wowType)
{
case WoWType.OSXppc:
return "OSX/ppc";
case WoWType.OSXx86:
return "OSX/x86";
case WoWType.Win32:
return "WIN32/x86";
default:
return "Unknown";
}
}
}
// Determine the Wow path. Will try to read it from the INI, or from the Registry. INI overrides Registry.
// (ie. you may have multiple wow installations and want to use a specific one)
private static String getWowPath()
{
String wowPath = configFile.ReadString("WoW", "Wowpath");
//if(BoogieCore.wowType != WoWType.Win32) return; // If its not windows wow, it won't be in the registry ;p
// Okay maybe i'll keep that commented out; I just place my WoW.app into my windows wow folder LOL.
if (wowPath.Equals(""))
{
RegistryKey rootKey = RegistryKey.OpenRemoteBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, "");
RegistryKey blizKey = rootKey.OpenSubKey(@"SOFTWARE\Blizzard Entertainment\World of Warcraft");
if(blizKey != null)
wowPath = (String)blizKey.GetValue("InstallPath");
if (wowPath == null || wowPath == "")
throw new Exception("Couldn't determine wowpath! Please set it in your Config.ini file.");
}
return wowPath;
}
// Determine what version of WoW we're running.
private static WoWVersion getWoWVersion()
{
WoWType wowType = (WoWType)configFile.ReadInteger("WoW", "WowType");
switch (wowType)
{
case WoWType.OSXppc:
BoogieCore.wowType = wowType;
return getWoWVersion_OSX();
case WoWType.OSXx86:
BoogieCore.wowType = wowType;
return getWoWVersion_OSX();
case WoWType.Win32:
BoogieCore.wowType = wowType;
return getWoWVersion_Win32();
default:
throw new Exception("Please fix wowtype in your config file.");
}
}
// Find Windows WoW Version using FileVersionInfo
private static WoWVersion getWoWVersion_Win32()
{
try
{
FileVersionInfo wowExeInfo = FileVersionInfo.GetVersionInfo(wowPath + @"\WoW.exe");
return new WoWVersion((byte)wowExeInfo.FileMajorPart, (byte)wowExeInfo.FileMinorPart, (byte)wowExeInfo.FileBuildPart, (ushort)wowExeInfo.FilePrivatePart);
}
catch (Exception)
{
throw new Exception("Couldn't open wow.exe. Check that it exists, and wowpath is set correctly.");
}
}
// Find OSX WoW Version, by reading in World of Warcraft.app's Info.plist. Fuck I hate XML though.
private static WoWVersion getWoWVersion_OSX()
{
XmlTextReader reader;
try
{
reader = new XmlTextReader(BoogieCore.wowPath + @"\World of Warcraft.app\Contents\Info.plist");
}
catch (Exception ex)
{
throw new Exception("Couldn't open WoW.app. Check that it exists, and wowpath is set correctly.");
}
String previousText = "";
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
break;
case XmlNodeType.Text:
if (previousText.Equals("BlizzardFileVersion"))
return new WoWVersion(reader.Value);
previousText = reader.Value;
break;
}
}
throw new Exception("Couldn't figure out World of Warcraft.app's version.");
}
}
// End of BoogieCore class!!
// Delegates - Used to make calls to the UI from this .dll
public delegate void CallBackEvent(Event e);
public delegate void CallBackLog(LogType logType, string format, params object[] parameters);
// Different Types of WoW (platform/OS combiantions)
public enum WoWType
{
Win32 = 0,
OSXppc = 1,
OSXx86 = 2
}
// Log types. Feel free to add more!
public enum LogType
{
Error, // Error Message. (This should be saved for fatal messages?)
System, // System Message
SystemDebug, // System Debug Message
NeworkComms, // Network Communications
FileDebug // File reading debug info
}
// Event types. You'll definitely be adding more.
public enum EventType
{
EVENT_REALMLIST,
EVENT_CHAR_LIST,
EVENT_CHAR_CREATE_RESULT,
EVENT_CHAT,
EVENT_CHANNEL_JOINED,
EVENT_CHANNEL_LEFT,
EVENT_SELF_MOVED,
EVENT_LOCATION_UPDATE,
EVENT_FRIENDS_LIST,
EVENT_IGNORE_LIST,
EVENT_FRIEND_STATUS,
EVENT_NAMEQUERY_RESPONSE
}
public class Event
{
public EventType eventType;
public string eventTime;
public object[] eventArgs;
public Event(EventType type, string time, params object[] parms)
{
eventType = type;
eventTime = time;
eventArgs = parms;
}
}
public struct WoWVersion
{
public WoWVersion(byte a, byte b, byte c, ushort d)
{
major = a; minor = b; update = c; build = d;
}
public WoWVersion(String versionString)
{
String[] versionParts = versionString.Split(new char[] {'.'});
Byte.TryParse(versionParts[0], out major);
Byte.TryParse(versionParts[1], out minor);
Byte.TryParse(versionParts[2], out update);
UInt16.TryParse(versionParts[3], out build);
}
// DON'T CHANGE THE TYPE ON THESE FIELDS
// (otherwise u need to fix RealmListClient.Auth.cs)
public byte major;
public byte minor;
public byte update;
public ushort build;
}
}