rendered paste bodyusing System;
using System.Net;
using System.Net.Sockets;
using Chief;
using ChiefD2.Net;
using ChiefD2.Net.Packet;
using D2PacketsNew.D2Packets;
using MBNCSUtil;
using ETUtils;
namespace ChiefD2
{
public class Client : IClient
{
#region IClient properties
public PacketHandler PacketHandler
{
get { return this.Socket.PacketHandler; }
}
public event ClientStateChangeEventHandler LobbyEntered;
public event ClientStateChangeEventHandler GameEntered;
public event ClientStateChangeEventHandler GameExited;
public event ClientStateChangeEventHandler Killed;
#endregion
#region Properties
private D2Socket Socket;
private Log DebugLog;
private int ClientToken;
private int ServerToken;
private ushort GameCounter = 0;
public BotProfile Profile;
#endregion
public Client(BotProfile profile)
{
this.DebugLog = new Log("clientless.log");
this.Profile = profile;
if (this.Profile.ClassicKey == null || this.Profile.LordOfDestructionKey == null)
throw new Exception("You must enter the CD Keys to use a clientless connection!");
this.Socket = new D2Socket();
//this.Socket.PacketReceived += new UnknownPacketEventHandler(Socket_PacketReceived);
//this.Socket.PacketSent += new UnknownPacketEventHandler(Socket_PacketSent);
#region Listeners
// Logging into bnet
//this.Socket.PacketHandler.AddAsyncListener(BnetServerPacket.BnetPing, new PacketEventHandler(BnetPing));
this.Socket.PacketHandler.AddAsyncListener(BnetServerPacket.BnetConnectionResponse, new PacketEventHandler(BnetConnectionResponse));
this.Socket.PacketHandler.AddAsyncListener(BnetServerPacket.BnetAuthResponse, new PacketEventHandler(BnetAuthResponse));
this.Socket.PacketHandler.AddAsyncListener(BnetServerPacket.BnetLogonResponse, new PacketEventHandler(BnetLogonResponse));
this.Socket.PacketHandler.AddAsyncListener(BnetServerPacket.QueryRealmsResponse, new PacketEventHandler(QueryRealmsResponse));
this.Socket.PacketHandler.AddAsyncListener(BnetServerPacket.RealmLogonResponse, new PacketEventHandler(RealmLogonResponse));
// Realms
this.Socket.PacketHandler.AddAsyncListener(RealmServerPacket.RealmStartupResponse, new PacketEventHandler(RealmStartupResponse));
this.Socket.PacketHandler.AddAsyncListener(RealmServerPacket.CharacterLogonResponse, new PacketEventHandler(CharacterLogonResponse));
// Game Server
this.Socket.PacketHandler.AddAsyncListener(GameServerPacket.GameLogonSuccess, new PacketEventHandler(GameLogonSuccess));
#endregion
this.DebugLog.Append("Debugging started ---------------------------------------------------------");
}
#region packet events
void Socket_PacketSent(PacketOrigin origin, byte[] data, int bytesTransferred)
{
string buffer = origin.ToString() + " Packet Sent";
for (int i = 0; i < bytesTransferred; i++)
{
if (i % 10 == 0)
buffer += Environment.NewLine;
string hex = ETUtils.ByteConverter.ToHexString(data, i, 1);
buffer += hex + " ";
}
this.DebugLog.Append(buffer + Environment.NewLine);
}
void Socket_PacketReceived(PacketOrigin origin, byte[] data, int bytesTransferred)
{
string buffer = origin.ToString() + " Packet Received";
for (int i = 0; i < bytesTransferred; i++)
{
if (i % 10 == 0)
buffer += Environment.NewLine;
string hex = ETUtils.ByteConverter.ToHexString(data, i, 1);
buffer += hex + " ";
}
this.DebugLog.Append(buffer + Environment.NewLine);
}
#endregion
#region IClient methods
public void Start()
{
this.Socket.ConnectBS(this.Profile.ServerName);
this.DebugLog.Append("Sending connection request");
this.Socket.SendBS(new byte[] { 0x01 });
this.Socket.SendBS(new ChiefD2.Net.Packet.BC.ConnectionRequest().Data);
}
public void SendBS(byte[] data)
{
this.Socket.SendBS(data);
}
public void SendRS(byte[] data)
{
this.Socket.SendRS(data);
}
public void SendGS(byte[] data)
{
this.Socket.SendGS(data);
}
public void ReceiveGC(byte[] data)
{
// Doesn't do anything--we're clientless, no reason to receive packets!
}
public bool CreateGame()
{
return CreateGame(this.Profile.Difficulty, Util.RandomString(12), Util.RandomString(3));
}
public bool CreateGame(D2DataNew.GameDifficulty difficulty)
{
return CreateGame(difficulty, Util.RandomString(12), Util.RandomString(3));
}
public bool CreateGame(string name, string pass)
{
return CreateGame(this.Profile.Difficulty, name, pass);
}
public bool CreateGame(D2DataNew.GameDifficulty difficulty, string name, string pass)
{
// The first character in game name/pass has to be uppercase, dunno why
name = name.ToUpper();
pass = pass.ToUpper();
this.GameCounter += 0x02;
this.DebugLog.Append("Making game #" + this.GameCounter.ToString() + " " + name + "//" + pass + " for " + difficulty.ToString() + " difficulty");
this.Socket.SendRS(
new ChiefD2.Net.Packet.RC.CreateGame(
this.GameCounter,
difficulty,
name,
pass,
""
).Data);
D2Packet packet = this.Socket.PacketHandler.WaitForPacket(D2PacketsNew.D2Packets.RealmServerPacket.CreateGameResponse, 5000);
if (packet == null)
return false;
D2PacketsNew.RealmServer.CreateGameResponse response = new D2PacketsNew.RealmServer.CreateGameResponse(packet.Data);
if (response.Result != D2PacketsNew.RealmServer.CreateGameResult.Success)
return false;
this.DebugLog.Append("CreateGame success!");
return JoinGame(name, pass);
}
public bool JoinGame(string name)
{
return JoinGame(name, "");
}
public bool JoinGame(string name, string pass)
{
this.DebugLog.Append("Joining game #" + this.GameCounter.ToString() + " " + name + "//" + pass);
this.Socket.SendRS(new ChiefD2.Net.Packet.RC.JoinGame(this.GameCounter, name, pass).Data);
D2Packet packet = this.Socket.PacketHandler.WaitForPacket(D2PacketsNew.D2Packets.RealmServerPacket.JoinGameResponse, 5000);
if (packet == null)
return false;
D2PacketsNew.RealmServer.JoinGameResponse response = new D2PacketsNew.RealmServer.JoinGameResponse(packet.Data);
if (response.Result != D2PacketsNew.RealmServer.JoinGameResult.Success)
return false;
this.DebugLog.Append("JoinGame success!");
this.DebugLog.Append("Connecting to game server: " + response.GameServerIP.ToString());
if (!this.Socket.ConnectGS(response.GameServerIP))
return false;
D2Packet requestLogonInfo = this.Socket.PacketHandler.WaitForPacket(D2PacketsNew.D2Packets.GameServerPacket.RequestLogonInfo, 5000);
if (requestLogonInfo == null)
{
this.DebugLog.Append("Never received RequestLogonInfo");
return false;
}
this.Socket.SendGS(
new ChiefD2.Net.Packet.GC.GameLogon(
response.GameHash,
response.GameToken,
this.Profile.CharacterClass,
this.Profile.CharacterName
).Data);
D2Packet gameLogonSuccess = this.Socket.PacketHandler.WaitForPacket(D2PacketsNew.D2Packets.GameServerPacket.GameLogonSuccess, 5000);
if (gameLogonSuccess == null)
{
this.DebugLog.Append("Never received GameLogonSuccess");
return false;
}
this.Socket.SendGS(new byte[] { 0x6b });
return true;
}
public bool LeaveGame()
{
if (this.Socket.IsInGame)
{
this.Socket.SendGS(new byte[] { 0x69 });
this.DebugLog.Append("Left game!");
this.Socket.CloseGS();
GameExited();
System.Threading.Thread.Sleep(1000);
LobbyEntered();
return true;
}
return false;
}
public void Kill()
{
throw new NotImplementedException();
}
#endregion
#region Listeners
#region BattleNet
//private void BnetPing(D2Packet packet)
//{
// this.Socket.SendBS(new byte[] { 0 });
//}
private void BnetConnectionResponse(D2Packet d2packet)
{
D2PacketsNew.BnetServer.BnetConnectionResponse packet = new D2PacketsNew.BnetServer.BnetConnectionResponse(d2packet.Data);
this.ClientToken = Environment.TickCount;
this.ServerToken = packet.ServerToken;
this.DebugLog.Append("Sending authorization check");
this.Socket.SendBS(
new ChiefD2.Net.Packet.BC.AuthorizationCheck(
(uint)this.ClientToken,
packet.VersionFileName,
packet.VersionFormulae,
new string[] { this.Profile.GameExe, this.Profile.BnClientDll, this.Profile.D2ClientDll },
this.Profile.ClassicKey,
this.Profile.LordOfDestructionKey,
(uint)this.ServerToken,
"Chief"
).Data
);
}
private void BnetAuthResponse(D2Packet d2packet)
{
D2PacketsNew.BnetServer.BnetAuthResponse packet = new D2PacketsNew.BnetServer.BnetAuthResponse(d2packet.Data);
if (packet.Result != D2PacketsNew.BnetServer.BnetAuthResult.Success)
{
this.DebugLog.Append("Couldn't login: " + packet.Result.ToString());
throw new Exception("Couldn't login: " + packet.Result.ToString());
}
this.DebugLog.Append("Logon success!");
this.Socket.SendBS(
new ChiefD2.Net.Packet.BC.AccountInfo(
this.Profile.Username,
this.Profile.Password,
this.ClientToken,
this.ServerToken
).Data);
}
private void BnetLogonResponse(D2Packet d2packet)
{
D2PacketsNew.BnetServer.BnetLogonResponse packet = new D2PacketsNew.BnetServer.BnetLogonResponse(d2packet.Data);
this.DebugLog.Append("Getting list of realms");
this.Socket.SendBS(new MBNCSUtil.BncsPacket(0x40).GetData());
}
private void QueryRealmsResponse(D2Packet d2packet)
{
// PS, figured this out later, too lazy to change back :)
// Doesn't work for some reason -- NullReference exception...
//BnetServer.QueryRealmsResponse packet = new BnetServer.QueryRealmsResponse(d2packet.Data);
// taken from the above function
uint unknown = BitConverter.ToUInt32(d2packet.Data, 4);
uint count = BitConverter.ToUInt32(d2packet.Data, 8);
D2PacketsNew.D2Packets.RealmInfo[] realms = new D2PacketsNew.D2Packets.RealmInfo[count];
int offset = 12;
for (int i = 0; i < count; i++)
{
realms[i] = new D2PacketsNew.D2Packets.RealmInfo(d2packet.Data, offset);
offset += 6 + realms[i].Name.Length + realms[i].Description.Length;
}
this.DebugLog.Append("Found realm: " + realms[0].Name);
this.DebugLog.Append("Logging onto realm");
this.Socket.SendBS(
new ChiefD2.Net.Packet.BC.RealmLogon(
realms[0].Name,
this.ClientToken,
this.ServerToken
).Data);
}
private void RealmLogonResponse(D2Packet d2packet)
{
// This also doesn't work, for some reason it skips a byte or something?
D2PacketsNew.BnetServer.RealmLogonResponse packet = new D2PacketsNew.BnetServer.RealmLogonResponse(d2packet.Data);
if (packet.Result != D2PacketsNew.BnetServer.RealmLogonResult.Success)
{
this.DebugLog.Append("Couldn't log on to that realm: " + packet.Result.ToString());
throw new Exception("Couldn't log on to that realm: " + packet.Result.ToString());
}
this.DebugLog.Append("Logged into realm!");
this.DebugLog.Append("Connecting to realm " + packet.RealmServerIP.ToString());
this.Socket.ConnectRS(packet.RealmServerIP);
this.DebugLog.Append("Connected");
this.Socket.SendRS(new byte[] {0x01});
this.DebugLog.Append("Logging onto realm...");
this.Socket.SendRS(
new ChiefD2.Net.Packet.RC.Logon(
packet.Cookie,
packet.Status,
packet.MCPChunk1,
packet.MCPChunk2,
packet.Username
).Data);
}
#endregion
#region Realm Server
private void RealmStartupResponse(D2Packet d2packet)
{
D2PacketsNew.RealmServer.RealmStartupResponse packet = new D2PacketsNew.RealmServer.RealmStartupResponse(d2packet.Data);
if (packet.Result != D2PacketsNew.RealmServer.RealmStartupResult.Success)
{
this.DebugLog.Append("Couldn't connect to that realm: " + packet.Result.ToString());
throw new Exception("Couldn't connect to that realm: " + packet.Result.ToString());
}
this.DebugLog.Append("Realm logon success!");
this.DebugLog.Append("Request list of characters, just for shits");
System.Threading.Thread.Sleep(50);
this.Socket.SendRS(new byte[] {0x07, 0x00, 0x19, 0x08, 0x00, 0x00, 0x00});
this.Socket.PacketHandler.WaitForPacket(RealmServerPacket.CharacterList, 15000);
System.Threading.Thread.Sleep(50);
this.DebugLog.Append("Selecting character: " + this.Profile.CharacterName);
this.Socket.SendRS(new ChiefD2.Net.Packet.RC.CharacterLogon(this.Profile.CharacterName).Data);
}
private void CharacterLogonResponse(D2Packet d2packet)
{
D2PacketsNew.RealmServer.CharacterLogonResponse packet = new D2PacketsNew.RealmServer.CharacterLogonResponse(d2packet.Data);
if (packet.Result != D2PacketsNew.RealmServer.RealmCharacterActionResult.Success)
{
this.DebugLog.Append("Couldn't select character: " + packet.Result.ToString());
throw new Exception("Couldn't select character: " + packet.Result.ToString());
}
this.DebugLog.Append("Character selected, entering lobby");
//this.Socket.SendRS(new D2PacketsNew.BnetClient.EnterChatRequest();
//this.Socket.PacketHandler.WaitForPacket(RealmServerPacket.CharacterList, 5000);
this.DebugLog.Append("Ready to make games!");
LobbyEntered();
}
#endregion
#region Game Server
private void GameLogonSuccess(D2Packet d2packet)
{
this.DebugLog.Append("Entered game!");
GameEntered();
}
#endregion
#endregion
}
}