using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Threading;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.Data;
// Work work
using Grunt.Library;
using Warcraft = Grunt.Library.Warcraft;
namespace Grunt.UI
{
///
/// Best class in the world :-)
///
class Program
{
///
/// Private variables
///
private static Warcraft war;
private static Hashtable objsById;
private static Hashtable untsById;
private static Hashtable itemsById;
private static Random rnd;
///
/// Private constants
///
///
/// Used for parsing the /Data/"obj.Type" file
///
private const string START = "#START"; // Object start
private const string END = "#END"; // Object end
private const string CUSTOM_START = "#CUSTOM_START";
private const string CUSTOM_END = "#CUSTOM_END";
private const string GUID = "OBJECT_FIELD_GUID"; // Object guid
private static int fileCount;
public static Hashtable dbc;
///
/// Application Entry
///
///
static void Main(string[] args)
{
Console.Title = "World of Warcraft - 47 72 75 6E 74";
#region Introduction Spam
Console.WriteLine(@"
_______ ______ _______ _______ _______
| __| __ | | | | |_ _| \___/
| | | < | | | | | cO Oc
|_______|___|__|_______|__|____| |___| Moo |_|
For World of Warcraft 1.10.2 /valvet");
Console.WriteLine("");
Console.WriteLine(" 00827024 47 52 55 4E 54 5F 48 45 GRUNT_HE\n" +
" 0082702C 4C 4C 4F LLO\n");
Console.WriteLine(" Please minimize me after starting, in order to reduce memory usage.");
Console.WriteLine(" Starting up..\n");
#endregion // End spam
rnd = new Random();
war = new Warcraft();
war.Interval = 125;
war.ThreadPriority = ThreadPriority.Normal;
Console.WriteLine(" Creating Hashtable.");
objsById = new Hashtable();
untsById = new Hashtable();
itemsById = new Hashtable();
DateTime startTime = DateTime.Now;
Console.WriteLine(" Parsing files. This might take a while.");
string[] dirs = Directory.GetDirectories(@"./Data/");
if (dirs.Length > 0)
{
Console.WriteLine(" Scanning for Object files in {0} directorie(s).", dirs.Length);
foreach (string dir in dirs)
{
GetDirectories(dir);
}
TimeSpan resultTime = DateTime.Now - startTime;
Console.WriteLine(" Done. Parsed {0} files in {1} sec(s).\n", fileCount, resultTime.TotalSeconds);
}
try
{
Console.WriteLine(" Creating new instance of Warcraft object.");
if (war.Start())
{
Console.WriteLine(" Launching update event.\n");
war.OnUpdateEvent += new WarcraftUpdateEvent(GruntUpdateEvent);
Console.WriteLine(" Started. Have a safe journey!\n");
}
else
{
Console.WriteLine(" Unable to start. Please check /Logs/Warcraft.log.");
}
}
catch (Exception E)
{
Console.WriteLine("\n -- Cut here --");
Console.WriteLine(" Caught exception.\n Please report the following to the developers: ");
Console.WriteLine(" Source: {0}", E.Source);
Console.WriteLine(" Message: {0}", E.Message);
Console.WriteLine(" StrackTrace: {0}", E.StackTrace);
Console.WriteLine(" -- Cut here --\n");
}
GC.Collect();
// Main thread will exit
}
#region Parser Specific Functions
///
/// Gets all the directories at the specified path
///
/// Path to look in
private static void GetDirectories(string path)
{
string[] dirs = Directory.GetDirectories(path);
if (dirs.Length > 0)
{
foreach (string subDir in dirs)
{
GetDirectories(subDir);
}
}
string[] files = Directory.GetFiles(path);
if (files.Length > 0)
{
foreach (string fileName in files)
{
FileInfo fileInfo = new FileInfo(fileName);
Console.WriteLine(" Parsing file: {0}, size: {1} bytes.", fileName, fileInfo.Length);
ParseFile(fileName);
fileCount++;
}
}
}
///
/// Parses specified file and adds them to the our collection
///
/// File to parse
private static void ParseFile(string fileName)
{
bool active = false;
StreamReader sr = new StreamReader(fileName);
string line;
while ((line = sr.ReadLine()) != null)
{
if (line.StartsWith(START))
{
active = true;
}
else if (line.StartsWith(END))
{
active = false;
}
else
{
if (active)
{
int ispace = line.IndexOf(" ");
line = line.Insert(ispace, ":");
string[] parts = line.Split(":".ToCharArray());
string key = parts[0].Trim();
string val = parts[1].Trim();
if (key.StartsWith(GUID))
{
if (!objsById.Contains(long.Parse(val)))
objsById.Add(long.Parse(val), "invalid");
}
else
{
//Console.WriteLine(" Unrecognized line " + line);
}
}
}
}
sr.Close();
}
#endregion
///
/// Our callback event for the WarcraftUpdateEvent in the library
///
///
/// This will update every 125 ms by default. You can change the interval
/// by modifying war.Interval = integer; -- Don't set too high!
///
/// Warcraft object
private static void GruntUpdateEvent(Warcraft sender)
{
foreach (War_Object obj in war.Objects.Values)
{
if (!obj.IsValid)
return;
switch (obj.Type)
{
case War_ObjectType.Object:
{
// TODO
break;
}
case War_ObjectType.Item:
{
if (!itemsById.Contains(obj.ReadStorageInt(0xC)))
{
//Console.WriteLine(" Item Name: {0}", obj.Name);
itemsById.Add(obj.ReadStorageInt(0xC), obj);
ObjectToFile(obj);
}
break;
}
case War_ObjectType.Container:
{
// TODO
break;
}
case War_ObjectType.Unit:
{
/*
if (!untsById.Contains(obj.ReadStorageInt(0x0)))
{
Console.WriteLine(" Unit Name: {0}", obj.Name);
Console.WriteLine(" Unit BasePtr: {0}", obj.BasePtr);
untsById.Add(obj.ReadStorageInt(0x0), obj);
ObjectToFile(obj);
}
addUnit(obj);
*/
//ds.Tables["Units"].WriteXml(@"./XmlData/dsUnitsObjects.xml");
break;
}
case War_ObjectType.Player:
{
// TODO
break;
}
case War_ObjectType.AIGroup:
{
Console.WriteLine("Hello AIGroup.");
break;
}
case War_ObjectType.Areatrigger:
{
Console.WriteLine("Hello Areatrigger.");
break;
}
case War_ObjectType.GameObject:
{
// Name was blank, try again later.
if (obj.Name.Length < 1)
return;
if (obj.Name == "Duel Flag")
return; // We don't want duel flags
// TODO: Do some more checking of bogus objects
// like Traps and such.
if (!objsById.Contains(obj.GUID.Full))
{
Console.WriteLine("Name {0} Type: {1}({2})", obj.Name, (War_GameObjectType)obj.ReadStorageInt(war.Descriptors[obj.Type, "GAMEOBJECT_TYPE_ID"]), obj.ReadStorageInt(war.Descriptors[obj.Type, "GAMEOBJECT_TYPE_ID"]));
//Console.WriteLine(" GO Name: {0}", obj.Name);
//Console.WriteLine(" GO BasePtr: {0}", obj.BasePtr);
objsById.Add(obj.GUID.Full, obj);
//ObjectToFile(obj);
//Console.WriteLine("Name {0}, padding(id?): {1}, bob: {2}, flags: {3}", obj.Name, obj.ReadStorageInt(0x14), obj.ReadStorageInt(0xE8), obj.ReadStorageInt(0x24));
}
break;
}
case War_ObjectType.Dynamic:
{
// TODO
break;
}
case War_ObjectType.Corpse:
{
// TODO
break;
}
default:
{
Console.WriteLine("\n -- Cut here --");
Console.WriteLine(" Strange.. Unknown Object type returned.\n Please report the following to the developers:");
Console.WriteLine(" Returned Object Type: {0}.", obj.Type);
Console.WriteLine(" -- Cut here --\n");
break;
}
}
}
// Let's try and sleep a little.. maybe that'll fix the
// name returning blank sometimes on objects.
Thread.Sleep(1000 + rnd.Next(500));
}
///
/// Writes all descriptor fields to a file
///
/// War_Object object
///
/// We need to check all the ReadStorage functions that they're
/// being used correctly. Eg. ReadStorageInt where the return value is
/// integer, Long where it's long and so forth.
///
private static void ObjectToFile(War_Object obj)
{
if (!Directory.Exists(@"./Data/" + obj.Type))
Directory.CreateDirectory(@"./Data/" + obj.Type);
using (StreamWriter sw = new StreamWriter(@"./Data/" + obj.Type + "/" + obj.Name, true))
{
sw.WriteLine("#START"); // Object start
sw.WriteLine("OBJECT_FIELD_GUID {0}", obj.ReadStorageLong(0x0));
sw.WriteLine("OBJECT_FIELD_GUID+1 {0}", obj.ReadStorageLong(0x4));
sw.WriteLine("#START_CUSTOM"); // Start custom descriptors
sw.WriteLine("OBJECT_FIELD_NAME {0}", obj.Name); // Custom
sw.WriteLine("GAMEOBJECT_CONTINENT {0}", obj.Continent); // Custom
sw.WriteLine("GAMEOBJECT_CREATED_BY_NAME {0}", obj.CreatedByName); // Custom
sw.WriteLine("OBJECT_FIELD_GUID_FULL {0}", obj.GUID.Full); // Custom
sw.WriteLine("OBJECT_FIELD_GUID_HIGH {0}", obj.GUID.High); // Custom
sw.WriteLine("OBJECT_FIELD_GUID_LOW {0}", obj.GUID.Low); // Custom
sw.WriteLine("GAMEOBJECT_SOUND {0}", obj.Sound0); // Custom
sw.WriteLine("GAMEOBJECT_SOUND+1 {0}", obj.Sound1); // Custom
sw.WriteLine("GAMEOBJECT_SOUND+2 {0}", obj.Sound2); // Custom
sw.WriteLine("GAMEOBJECT_SOUND+3 {0}", obj.Sound3); // Custom
sw.WriteLine("GAMEOBJECT_SOUND+4 {0}", obj.Sound4); // Custom
sw.WriteLine("GAMEOBJECT_SOUND+5 {0}", obj.Sound5); // Custom
sw.WriteLine("GAMEOBJECT_SOUND+6 {0}", obj.Sound6); // Custom
sw.WriteLine("GAMEOBJECT_SOUND+7 {0}", obj.Sound7); // Custom
sw.WriteLine("GAMEOBJECT_SOUND+8 {0}", obj.Sound8); // Custom
sw.WriteLine("GAMEOBJECT_SOUND+9 {0}", obj.Sound9); // Custom
sw.WriteLine("#END_CUSTOM"); // End custom descriptors
sw.WriteLine("OBJECT_FIELD_TYPE {0}", obj.ReadStorageInt(0x8));
sw.WriteLine("OBJECT_FIELD_ENTRY {0}", obj.ReadStorageInt(0xC));
sw.WriteLine("OBJECT_FIELD_SCALE_X {0}", obj.ReadStorageFloat(0x10));
sw.WriteLine("OBJECT_FIELD_PADDING {0}", obj.ReadStorageFloat(0x14));
// TODO: Figure out how this workes
// Perhaps the first or second is GUID of the creator.
sw.WriteLine("OBJECT_FIELD_CREATED_BY {0}", obj.ReadStorageLong(0x18));
sw.WriteLine("OBJECT_FIELD_CREATED_BY+1 {0}", obj.ReadStorageLong(0x1C));
sw.WriteLine("GAMEOBJECT_DISPLAYID {0}", obj.ReadStorageInt(0x20));
sw.WriteLine("GAMEOBJECT_FLAGS {0}", obj.ReadStorageInt(0x24));
sw.WriteLine("GAMEOBJECT_ROTATION {0}", obj.ReadStorageFloat(0x28));
sw.WriteLine("GAMEOBJECT_ROTATION+1 {0}", obj.ReadStorageFloat(0x2C));
sw.WriteLine("GAMEOBJECT_ROTATION+2 {0}", obj.ReadStorageFloat(0x30));
sw.WriteLine("GAMEOBJECT_ROTATION+3 {0}", obj.ReadStorageFloat(0x34)); // 0x34
sw.WriteLine("GAMEOBJECT_STATE {0}", obj.ReadStorageInt(0x38));
// TODO: Figure out how to calculate to real DateTime
sw.WriteLine("GAMEOBJECT_TIMESTAMP {0}", obj.ReadStorageLong(0x3C));
sw.WriteLine("GAMEOBJECT_POS_X {0}", obj.ReadStorageFloat(0x40));
sw.WriteLine("GAMEOBJECT_POS_Y {0}", obj.ReadStorageFloat(0x44));
sw.WriteLine("GAMEOBJECT_POS_Z {0}", obj.ReadStorageFloat(0x48));
sw.WriteLine("GAMEOBJECT_FACING {0}", obj.ReadStorageFloat(0x4C));
sw.WriteLine("GAMEOBJECT_DYN_FLAGS {0}", obj.ReadStorageInt(0x50));
sw.WriteLine("GAMEOBJECT_FACTION {0}", obj.ReadStorageInt(0x54));
sw.WriteLine("GAMEOBJECT_TYPE_ID {0}", obj.ReadStorageInt(0x58));
sw.WriteLine("GAMEOBJECT_LEVEL {0}", obj.ReadStorageInt(0x5C));
sw.WriteLine("#END"); // Object end
sw.WriteLine("");
}
}
///
/// Class destructor
///
~Program()
{
objsById = null;
GC.Collect();
}
}
}