rendered paste bodyusing System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using Tamir.IPLib;
using D2Sniffer;
using D2Data;
using D2Packets;
namespace Chief
{
public delegate bool PacketConfirmation(object packet);
public class Game
{
#region Win32
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
private static extern uint MapVirtualKey(uint uCode, uint uMapType);
[DllImport("user32.dll")]
private static extern bool FlashWindow(IntPtr hwnd, bool bInvert);
/*
[DllImport("user32.dll")]
private static extern bool TranslateMessage([In] ref MSG lpMsg);
private struct MSG
{
public IntPtr hwnd;
public uint message;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
public POINT pt;
}
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
public static implicit operator System.Drawing.Point(POINT p)
{
return new System.Drawing.Point(p.X, p.Y);
}
public static implicit operator POINT(System.Drawing.Point p)
{
return new POINT(p.X, p.Y);
}
}*/
#endregion
//private OutOfGameState State = OutOfGameState.None;
#region Collections
public Games Games = new Games();
public Items Items = new Items();
public Objects Objects = new Objects();
public Units Units = new Units();
#endregion
public D2Toolkit.D2Instance Diablo;
public Hero Hero = new Hero();
private PacketSniffer Sniffer = new PacketSniffer();
public Game()
{
}
public void Attach(Process proc)
{
this.Diablo = new D2Toolkit.D2Instance(proc.MainWindowHandle);
if (!this.Sniffer.StartSniffing(this.Diablo.ProcessID))
throw new Exception("Couldn't start sniffing.");
// Realm Server Packets
this.Sniffer.AddAsyncListener(RealmServerPacket.GameList, new PacketEventHandler(this.GameList));
// Game Server Packets
this.Sniffer.AddAsyncListener(GameServerPacket.AssignPlayer, new PacketEventHandler(this.AssignPlayer));
this.Sniffer.AddAsyncListener(GameServerPacket.AssignNPC, new PacketEventHandler(this.AssignNPC));
this.Sniffer.AddAsyncListener(GameServerPacket.AssignGameObject, new PacketEventHandler(this.AssignGameObject));
this.Sniffer.AddAsyncListener(GameServerPacket.AssignSkill, new PacketEventHandler(this.AssignSkill));
this.Sniffer.AddAsyncListener(GameServerPacket.SetNPCMode, new PacketEventHandler(this.SetNPCMode));
this.Sniffer.AddAsyncListener(GameServerPacket.NPCMove, new PacketEventHandler(this.NPCMove));
this.Sniffer.AddAsyncListener(GameServerPacket.WalkVerify, new PacketEventHandler(this.WalkVerify));
this.Sniffer.AddAsyncListener(GameServerPacket.PlayerReassign, new PacketEventHandler(this.PlayerReassign));
//this.Sniffer.AddAsyncListener(GameServerPacket.WorldItemAction, new PacketEventHandler(this.WorldItemAction));
this.Sniffer.AddAsyncListener(GameServerPacket.OwnedItemAction, new PacketEventHandler(this.OwnedItemAction));
// Game Client Packets
this.Sniffer.AddAsyncListener(GameClientPacket.SelectSkill, new PacketEventHandler(this.SelectSkill));
this.Sniffer.AddAsyncListener(GameClientPacket.RequestReassign, new PacketEventHandler(this.RequestReassign));
//this.Sniffer.AddAsyncListener(GameClientPacket.WaypointInteract, new PacketEventHandler(this.WaypointInteract));
}
public void Clear()
{
this.Units.Clear();
this.Objects.Clear();
this.Items.Clear();
this.Games.Clear();
}
#region Packet interpreting
#region Realm Server
private void GameList(object sender, PacketEventArgs args)
{
RealmServer.GameList gameList = (args.Packet as RealmServer.GameList);
this.Games.Add(gameList);
}
#endregion
#region Game Server
private void AssignPlayer(object sender, PacketEventArgs args)
{
GameServer.AssignPlayer packet = args.Packet as GameServer.AssignPlayer;
// Grab our bot's character UID, if it's not already found
if (this.Hero.UID == 0)
{
this.Hero.Initialize(packet);
}
}
private void AssignNPC(object sender, PacketEventArgs args)
{
NPC npc = new NPC(args.Packet as GameServer.AssignNPC);
// Add NPC if it doesn't already exist, otherwise just update
NPC npcInList = this.Units.Find(npc.UID);
if (npcInList != null)
npcInList = npc;
else
this.Units.Add(npc);
}
private void AssignGameObject(object sender, PacketEventArgs args)
{
Object theObject = new Object(args.Packet as GameServer.AssignGameObject);
// Add Object if it doesn't already exist, otherwise just update
Object objectInList = this.Objects.Find(theObject.UID);
if (objectInList != null)
objectInList = theObject;
else
this.Objects.Add(theObject);
}
private void AssignSkill(object sender, PacketEventArgs args)
{
GameServer.AssignSkill packet = args.Packet as GameServer.AssignSkill;
// Grab our bot's character UID, if it's not already found
if (this.Hero.UID == packet.UID)
{
this.Hero.SetSkillSelected(packet.Hand, packet.Skill);
}
}
private void SetNPCMode(object sender, PacketEventArgs args)
{
uint uid = (args.Packet as GameServer.SetNPCMode).UID;
NPC npc = this.Units.Find(uid);
if (npc != null)
npc.UpdateMode(args.Packet as GameServer.SetNPCMode);
}
private void WalkVerify(object sender, PacketEventArgs args)
{
GameServer.WalkVerify packet = args.Packet as GameServer.WalkVerify;
this.Hero.X = (uint)packet.X;
this.Hero.Y = (uint)packet.Y;
}
private void PlayerReassign(object sender, PacketEventArgs args)
{
GameServer.PlayerReassign packet = args.Packet as GameServer.PlayerReassign;
this.Hero.X = (uint)packet.X;
this.Hero.Y = (uint)packet.Y;
}
private void NPCMove(object sender, PacketEventArgs args)
{
NPC npc = this.Units.Find((args.Packet as GameServer.NPCMove).UID);
if (npc != null)
{
npc.UpdatePosition(args.Packet as GameServer.NPCMove);
}
}
private void WorldItemAction(object sender, PacketEventArgs args)
{
//GameServer.WorldItemAction item = (args.Packet as GameServer.WorldItemAction);
Item item = new Item(args.Packet as GameServer.WorldItemAction);
if (!this.Items.ContainsKey(item.UID) && item != null)
try
{
this.Items.Add(item.UID, item);
}
catch (NullReferenceException)
{ /* TODO: Why do I get this exception? Do some items not have UID's?*/ }
}
private void OwnedItemAction(object sender, PacketEventArgs args)
{
Item item = new Item(args.Packet as GameServer.OwnedItemAction);
if (!this.Hero.Items.ContainsKey(item.UID))
try
{
this.Hero.Items.Add(item.UID, item);
}
catch (NullReferenceException)
{ /* TODO: Why do I get this exception? Do some items not have UID's?*/ }
}
#endregion
#region Game Client
private void SelectSkill(object sender, PacketEventArgs args)
{
GameClient.SelectSkill packet = args.Packet as GameClient.SelectSkill;
this.Hero.SetSkillSelected(packet.Hand, packet.Skill);
}
private void RequestReassign(object sender, PacketEventArgs args)
{
GameClient.RequestReassign packet = args.Packet as GameClient.RequestReassign;
// Grab our bot's character UID, if it's not already found
if (this.Hero.UID == 0)
{
this.Hero.UID = packet.MeUID;
}
}
private void WaypointInteract(object sender, PacketEventArgs args)
{
// When we go through a waypoint, we should remove all objects/npcs/etc. so we don't
// get any mix ups
this.Clear();
}
#endregion
#endregion
#region Packet actions
public void Move(int x, int y)
{
this.Diablo.Sender.SendToGameServer(new GameClient.RunToLocation((ushort)x, (ushort)y).Data);
uint myUID = this.Hero.UID;
uint toX = (uint)x;
uint toY = (uint)y;
uint fromX = this.Hero.X;
uint fromY = this.Hero.Y;
byte[] PlayerMove = new byte[]
{
0x0F, // PlayerMove
0x00, // Client Type (always 0x00)
(byte)(myUID & 0xFF), (byte)((myUID >> 8) & 0xFF), (byte)((myUID >> 16) & 0xFF), (byte)(myUID >> 24), // Client ID
0x17, // Run/Walk (0x01 for walk, 0x17 for run)
(byte)(toX & 0xFF), (byte)((toX >> 8) & 0xFF), (byte)(toY & 0xFF), (byte)((toY >> 8) & 0xFF), // Location to walk to
0x00, // Unknown, always 0x00
(byte)(fromX & 0xFF), (byte)((fromX >> 8) & 0xFF), (byte)(fromY & 0xFF), (byte)((fromY >> 8) & 0xFF) // Current location of the client
};
this.Diablo.Sender.SendToGameClient(new GameServer.PlayerMove(PlayerMove).Data);
}
public void Move(Unit unit)
{
this.Diablo.Sender.SendToGameServer(new GameClient.RunToLocation((ushort)unit.X, (ushort)unit.Y).Data);
this.Diablo.Sender.SendToGameServer(new GameClient.RunToTarget(UnitType.NPC, unit.UID).Data);
uint myUID = this.Hero.UID;
uint toX = (uint)unit.X;
uint toY = (uint)unit.Y;
uint fromX = this.Hero.X;
uint fromY = this.Hero.Y;
byte[] PlayerMove = new byte[]
{
0x0F, // PlayerMove
0x00, // Client Type (always 0x00)
(byte)(myUID & 0xFF), (byte)((myUID >> 8) & 0xFF), (byte)((myUID >> 16) & 0xFF), (byte)(myUID >> 24), // Client ID
0x17, // Run/Walk (0x01 for walk, 0x17 for run)
(byte)(toX & 0xFF), (byte)((toX >> 8) & 0xFF), (byte)(toY & 0xFF), (byte)((toY >> 8) & 0xFF), // Location to walk to
0x00, // Unknown, always 0x00
(byte)(fromX & 0xFF), (byte)((fromX >> 8) & 0xFF), (byte)(fromY & 0xFF), (byte)((fromY >> 8) & 0xFF) // Current location of the client
};
this.Diablo.Sender.SendToGameClient(new GameServer.PlayerMove(PlayerMove).Data);
}
public bool MoveWait(int x, int y)
{
Move(x, y);
PacketConfirmation myDel = delegate(object packet)
{
if ((packet as GameServer.WalkVerify).X == x && (packet as GameServer.WalkVerify).Y == y)
return true;
else
return false;
};
if (!WaitForPacket(GameServerPacket.WalkVerify, myDel, 5000))
return false;
return true;
}
public bool MoveWait(Unit unit)
{
Move(unit);
PacketConfirmation myDel = delegate(object packet)
{
if ((packet as GameServer.WalkVerify).X == unit.X && (packet as GameServer.WalkVerify).Y == unit.Y)
return true;
else
return false;
};
if (!WaitForPacket(GameServerPacket.WalkVerify, myDel, 5000))
return false;
return true;
}
public bool PortalInteract(Object unit)
{
// If we didn't move on the first try, try 1 more time
//if (!MoveWait(unit))
Move(unit);
this.Diablo.Sender.SendToGameServer(new GameClient.UnitInteract(UnitType.GameObject, unit.UID).Data);
//if (!WaitForPacket(GameServerPacket.PortalInfo, 5000))
// return false;
this.Diablo.Sender.SendToGameServer(new GameClient.RequestReassign(UnitType.NPC, this.Hero.UID).Data);
return true;
}
public bool WaypointInteract(Object waypoint, WaypointDestination destination)
{
Move(waypoint);
this.Diablo.Sender.SendToGameServer(new GameClient.UnitInteract(UnitType.GameObject, waypoint.UID).Data);
this.Diablo.Sender.SendToGameServer(new GameClient.WaypointInteract(waypoint.UID, destination).Data);
this.Diablo.Sender.SendToGameServer(new GameClient.RequestReassign(UnitType.NPC, this.Hero.UID).Data);
return false;
}
public bool TeleportWait(int x, int y)
{
SelectSkill(SkillHand.Right, SkillType.Teleport);
this.CastRightSkill(x, y);
if (!WaitForPacket(GameServerPacket.PlayerReassign, 5000))
return false;
// Delay so we don't keep teleporting
System.Threading.Thread.Sleep(200);
return true;
}
public void Attack(NPC npc, SkillType skill)
{
SelectSkill(SkillHand.Left, skill);
this.Diablo.Sender.SendToGameServer(new GameClient.CastLeftSkill((ushort)npc.X, (ushort)npc.Y).Data);
}
public bool SelectSkill(SkillHand hand, SkillType type)
{
if (!this.Hero.IsSkillSelected(hand, type))
{
this.Diablo.Sender.SendToGameServer(new GameClient.SelectSkill(type, hand).Data);
if (!WaitForPacket(GameServerPacket.AssignSkill, 5000))
return false;
}
return true;
}
public void CastLeftSkill(int x, int y)
{
this.Diablo.Sender.SendToGameServer(new GameClient.CastLeftSkill((ushort)x, (ushort)y).Data);
}
public void CastRightSkill(int x, int y)
{
this.Diablo.Sender.SendToGameServer(new GameClient.CastRightSkill((ushort)x, (ushort)y).Data);
}
public bool SwitchWeaponSlotWait()
{
this.Diablo.Sender.SendToGameServer(new GameClient.SwitchWeapons().Data);
PacketConfirmation myDel = delegate(object packet)
{
if ((packet as GameServer.OwnedItemAction).Destination == ItemDestination.Equipment)
return true;
else
return false;
};
if (!WaitForPacket(GameServerPacket.OwnedItemAction, myDel, 5000))
return false;
return true;
}
public void SendChatMessage(string text)
{
this.Diablo.Sender.SendToGameServer(new GameClient.SendMessage(GameMessageType.GameMessage, text).Data);
}
public bool WaitForPacket(RealmServerPacket packet, int timeOut)
{
return WaitForPacket(packet, delegate(object pckt) { return true; }, timeOut);
}
public bool WaitForPacket(RealmServerPacket packet, PacketConfirmation confirmation, int timeOut)
{
bool isBusy = true;
this.Sniffer.AddAsyncListener(packet,
delegate(object sender, PacketEventArgs args)
{
if (confirmation(args.Packet))
isBusy = false;
});
DateTime start = DateTime.Now;
while (isBusy)
{
if (((TimeSpan)DateTime.Now.Subtract(start)).TotalMilliseconds > timeOut)
return false;
System.Threading.Thread.Sleep(10);
}
return true;
}
public bool WaitForPacket(RealmClientPacket packet, int timeOut)
{
return WaitForPacket(packet, delegate(object pckt) { return true; }, timeOut);
}
public bool WaitForPacket(RealmClientPacket packet, PacketConfirmation confirmation, int timeOut)
{
bool isBusy = true;
this.Sniffer.AddAsyncListener(packet,
delegate(object sender, PacketEventArgs args)
{
if (confirmation(args.Packet))
isBusy = false;
});
DateTime start = DateTime.Now;
while (isBusy)
{
if (((TimeSpan)DateTime.Now.Subtract(start)).TotalMilliseconds > timeOut)
return false;
System.Threading.Thread.Sleep(10);
}
return true;
}
public bool WaitForPacket(GameServerPacket packet, int timeOut)
{
return WaitForPacket(packet, delegate(object pckt) { return true; }, timeOut);
}
public bool WaitForPacket(GameServerPacket packet, PacketConfirmation confirmation, int timeOut)
{
bool isBusy = true;
this.Sniffer.AddAsyncListener(packet,
delegate(object sender, PacketEventArgs args)
{
if (confirmation(args.Packet))
isBusy = false;
});
DateTime start = DateTime.Now;
while (isBusy)
{
if (((TimeSpan)DateTime.Now.Subtract(start)).TotalMilliseconds > timeOut)
return false;
System.Threading.Thread.Sleep(10);
}
return true;
}
public bool WaitForPacket(GameClientPacket packet, int timeOut)
{
return WaitForPacket(packet, delegate(object pckt) { return true; }, timeOut);
}
public bool WaitForPacket(GameClientPacket packet, PacketConfirmation confirmation, int timeOut)
{
bool isBusy = true;
this.Sniffer.AddAsyncListener(packet,
delegate(object sender, PacketEventArgs args)
{
if (confirmation(args.Packet))
isBusy = false;
});
DateTime start = DateTime.Now;
while (isBusy)
{
if (((TimeSpan)DateTime.Now.Subtract(start)).TotalMilliseconds > timeOut)
return false;
System.Threading.Thread.Sleep(10);
}
return true;
}
public bool WaitForPacket(BnetServerPacket packet, int timeOut)
{
return WaitForPacket(packet, delegate(object pckt) { return true; }, timeOut);
}
public bool WaitForPacket(BnetServerPacket packet, PacketConfirmation confirmation, int timeOut)
{
bool isBusy = true;
this.Sniffer.AddAsyncListener(packet,
delegate(object sender, PacketEventArgs args)
{
if (confirmation(args.Packet))
isBusy = false;
});
DateTime start = DateTime.Now;
while (isBusy)
{
if (((TimeSpan)DateTime.Now.Subtract(start)).TotalMilliseconds > timeOut)
return false;
System.Threading.Thread.Sleep(10);
}
return true;
}
public bool WaitForPacket(BnetClientPacket packet, int timeOut)
{
return WaitForPacket(packet, delegate(object pckt) { return true; }, timeOut);
}
public bool WaitForPacket(BnetClientPacket packet, PacketConfirmation confirmation, int timeOut)
{
bool isBusy = true;
this.Sniffer.AddAsyncListener(packet,
delegate(object sender, PacketEventArgs args)
{
if (confirmation(args.Packet))
isBusy = false;
});
DateTime start = DateTime.Now;
while (isBusy)
{
if (((TimeSpan)DateTime.Now.Subtract(start)).TotalMilliseconds > timeOut)
return false;
System.Threading.Thread.Sleep(10);
}
return true;
}
#endregion
#region Out of game
/// <summary>
/// Creates and attaches to Diablo II instance
/// </summary>
/// <param name="workingPath"></param>
/// <param name="exe"></param>
/// <param name="parameters"></param>
/// <returns></returns>
public bool Launch(string workingPath, string exe, string parameters)
{
Process tempProcess = new Process();
tempProcess.StartInfo.WorkingDirectory = workingPath;
tempProcess.StartInfo.FileName = exe;
tempProcess.StartInfo.Arguments = parameters;
if (!tempProcess.Start())
return false;
// DEBUG -- non-static delay here, maybe?
System.Threading.Thread.Sleep(1000);
this.Attach(tempProcess);
// Assume -skiptobnet
return this.WaitForPacket(BnetClientPacket.ExtraWorkResponse, 15000);
}
public bool Login(string username, string password)
{
// Type in name/pass
this.Diablo.SendKey(System.Windows.Forms.Keys.Tab);
this.SendKeys(username);
this.Diablo.SendKey(System.Windows.Forms.Keys.Tab);
this.SendKeys(password);
this.Diablo.SendKey(System.Windows.Forms.Keys.Enter);
return this.WaitForPacket(RealmServerPacket.CharacterList, 15000);
}
public bool CharacterSelect(int slot)
{
if(slot % 2 == 0)
{
this.Diablo.SendKey(System.Windows.Forms.Keys.Right);
}
for (int i = 2; i < slot; i+=2)
{
this.Diablo.SendKey(System.Windows.Forms.Keys.Down);
}
this.Diablo.SendKey(System.Windows.Forms.Keys.Enter);
return this.WaitForPacket(RealmServerPacket.MessageOfTheDay, 15000);
}
public bool CreateGame(string name, string password, Difficulty difficulty)
{
// Create Game
this.Diablo.Click(592, 460, Poseur32.ClickType.Left);
// Type in name/pass
this.SendKeys(name);
this.Diablo.SendKey(System.Windows.Forms.Keys.Tab);
this.SendKeys(password);
// Difficulty
Point difficultyRadio = new Point();
switch(difficulty)
{
case Difficulty.Normal:
difficultyRadio = new Point(440, 374);
break;
case Difficulty.Nightmare:
difficultyRadio = new Point(565, 375);
break;
case Difficulty.Hell:
difficultyRadio = new Point(707, 375);
break;
}
this.Diablo.Click(difficultyRadio.X, difficultyRadio.Y, Poseur32.ClickType.Left);
// Create the game
this.Diablo.Click(681, 419, Poseur32.ClickType.Left);
return this.WaitForPacket(D2Packets.GameServerPacket.PlayerReassign, 15000);
}
public bool JoinGame(string name, string password)
{
// Type in name/pass
this.SendKeys(name);
this.Diablo.SendKey(System.Windows.Forms.Keys.Tab);
this.SendKeys(password);
// Join
this.Diablo.Click(678, 417, Poseur32.ClickType.Left);
this.Games.Clear();
return this.WaitForPacket(D2Packets.GameServerPacket.PlayerReassign, 15000);
}
public bool JoinGame(string name)
{
return this.JoinGame(name, "");
}
/// <summary>
/// Joins a random game, with the most people
/// </summary>
public bool JoinGame()
{
// Join game
this.Diablo.Click(713, 461, Poseur32.ClickType.Left);
// Wait for list of games
this.WaitForPacket(D2Packets.RealmServerPacket.GameList, 5000);
System.Threading.Thread.Sleep(2000);
// Select the best game
string bestGame = "";
for (int i = 7; i > 0; i--)
{
foreach (RealmServer.GameList gameList in this.Games)
{
if (gameList.PlayerCount >= i)
{
bestGame = gameList.Name;
break;
}
}
if (bestGame != "")
break;
}
return this.JoinGame(bestGame);
}
public void SendKeys(string text)
{
foreach (char c in text)
{
this.Diablo.SendKey(c);
//System.Threading.Thread.Sleep(5);
}
}
#endregion
public void Kill()
{
this.Diablo.Exit(true);
}
public void FlashWindow()
{
FlashWindow(this.Diablo.Process.MainWindowHandle, true);
}
}
/*
public enum OutOfGameState
{
None,
Login,
CharacterSelect,
Chat,
CreateGame,
JoinGame,
InGame
}
*/
public enum Difficulty
{
Normal,
Nightmare,
Hell
}
}