All pastes #827843 Raw Edit

Something

public text v1 · immutable
#827843 ·published 2007-12-22 01:34 UTC
rendered paste body
using System;
using System.Collections.Generic;
using System.Text;
using D2Sniffer;
using System.Diagnostics;
using System.Net.Sockets;

namespace data
{
    public class Bot
    {
        //fields
        BotConfig myBotConfig; //configuration for current bot instance
        static PacketSniffer myPacketSniffer; //d2Smell sniffer instance
        TcpClient myBnetServerClient, myRealmServerClient,myGameServerClient;//connections to battle.net servers
        static System.Net.IPAddress RealmServerIp; //Used as storage to connect to realmserver after the response from BNLS is received
        ushort CurrentGameNum = 0; //used in CreateGame packet, increment by 0x02 each game
        uint ClientToken, ServerToken; //Tokens used to Hash data at run-time
        //TODO change this when implementing the cdkey files and store the damn index cuz appsettings are so retarded...
        int KeyListIndex = 0; //keep track of the current used cdkey
        string RealmServerString, BNCSUniqueName, CurrentGameName, CurrentGamePassword = "sadsapog"; //game related + internal stuff
        bool LoginDone = false, InGame = false, FailedToJoin = false; //used in the Creat/Join game proc
        byte[] RSLogon; //a packet that is built in a function but sent in another one.
        int RunCreationWaitDelay = 5000; //the delay between each game creation attemps
        public int TotalRuns = 0, TotalCompletedRuns = 0; //runs state: TotalCompletedRuns/TotalRuns
        public RealmServer.JoinGameResult LastJoinResult = RealmServer.JoinGameResult.Success;
        
        public bool NeedIPReset = false; //this is not yet set
        private bool FatalDebugError = false; //replace this eventually; (or I might keep it)
        
        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="botConfig">a BotConfig object containing all revelant information to run the bot</param>
        public Bot(BotConfig botConfig)
        {
            this.myBotConfig = botConfig; //keep this
        }
        int TotalTimeOutGame = 0;
        /// <summary>
        /// Will perform a hard-coded number of runs. Then return to change cdkey
        /// Caution: Some runs use 2 games but are considered being only 1run (when the bot use ComeBack if 2000 received packets is reached)
        /// So be carefull since if you set it to swap cdkey every 20runs it can create up to 40 games
        /// </summary>
        public void doRuns()
        {
            this.NeedIPReset = false;
            //myPacketSniffer.OnConnectionChange += new ConnectionChangeHandler(myPacketSniffer_OnConnectionChange);
            CurrentGameNum = 0; //increment by 2 at each game creation
            Game.PacketDispatcher myPacketDispatcher = new data.Game.PacketDispatcher();
            myPacketSniffer.AddListener(D2Packets.PacketOrigin.GameServer, new PacketEventHandler(myPacketDispatcher.onPacketArrival));
            int InitialTicks = 0;
            Test myTest = new Test(myBotConfig, false);
            //for (int i = 0; i < 10; i++)
            int i = 0;
            while (true) 
            {

                if (i > 0)
                {
                    //Disconnect_BnetServer();
                    //Disconnect_RealmServer();
                    onRunDone();
                }
                i++;

                //if (this.NeedIPReset)
                //    return;

                Game.GameInfo.RST = false;
                CurrentGameNum += 2;
                this.FailedToJoin = false;
                this.InGame = false;
                Random rnd = new Random();
                Sleep(this.RunCreationWaitDelay);
                Game.Belt.Init();
                CurrentGameName = rnd.Next(1000000, 99999999).ToString();
                CreateGame(CurrentGameNum, CurrentGameName, CurrentGamePassword, DifficultyType.Nightmare, "");
                //JoinGame(1, "Dkk3", "Q");
                int Timeout2 = 0;
                //while (!this.FatalDebugError && !this.InGame)
                while (!this.InGame)
                {
                    System.Threading.Thread.Sleep(1);
                    Timeout2++;
                    if (Timeout2 > 5000)
                    {
                        if (TotalTimeOutGame > 20)
                            return;
                        Sleep(5000);
                        TotalTimeOutGame++;
                        Logger.Log("Bot(): Create game timed out");
                        break; ;
                    }
                    if (this.FailedToJoin)
                    {
                        //Sleep(30000);
                        Sleep(5000);
                        this.FailedToJoin = false;
                        break;
                    }
                }
                if (!this.InGame)
                {
                    //onRunDone();
                    continue;
                }
                TotalTimeOutGame = 0;
                InitialTicks = Environment.TickCount;

                //Sleep(100);
                //if (Game.GameInfo.RST)
                //{
                //    Logger.Log("RST, create new game");
                //    continue;
                //}
                bool RunSuccess = false;
                try
                {
                    RunSuccess = myTest.DoRun(ref myGameServerClient);
                }
                catch
                {
                    this.TotalRuns += 1;
                    myTest.onRunDone();
                    continue;
                }
                if (RunSuccess)
                    this.TotalCompletedRuns += 1;
                this.TotalRuns += 1;

                

                myTest.onRunDone();
                
                //go back to the same game in case we did not finish the run under 2000 rcv packets
                if (!RunSuccess && Game.GameInfo.Catacomb2Path.Count > 0 && Game.GameInfo.Catacomb3Path.Count == 0)
                {
                    onRunDone();
                    Game.Belt.Init();
                    Game.GameInfo.RST = false;
                    CurrentGameNum += 2;
                    this.FailedToJoin = false;
                    this.InGame = false;
                    LastJoinResult = RealmServer.JoinGameResult.Success;
                    Sleep(2000);
                    for (int ia = 0; ia < 3; ia++)
                    {
                        if (ia > 0)
                            Sleep(this.RunCreationWaitDelay);
                        JoinGame(this.CurrentGameNum, this.CurrentGameName, this.CurrentGamePassword);
                        for (int tt = 0; tt < 1000; tt++)
                        {
                            Sleep(1);
                            if (this.InGame)
                                break;
                            if (this.FailedToJoin)
                                continue;
                        }
                        if (this.InGame)
                            break;
                        if (LastJoinResult == RealmServer.JoinGameResult.GameDoesNotExist)
                            break;
                    }
                    //Sleep(1000);
                    if (!this.InGame)
                        continue;
                    try
                    {
                        if (myTest.ComeBack(ref myGameServerClient))
                            this.TotalCompletedRuns += 1;
                    }
                    catch
                    {

                    }
                }

                //go back to the same game in case we did not finish the run under 2000 rcv packets
                if (!RunSuccess && Game.GameInfo.Catacomb2Path.Count > 0 && Game.GameInfo.Catacomb3Path.Count > 0)
                {
                    onRunDone();
                    Game.Belt.Init();
                    Game.GameInfo.RST = false;
                    CurrentGameNum += 2;
                    this.FailedToJoin = false;
                    this.InGame = false;
                    LastJoinResult = RealmServer.JoinGameResult.Success;
                    Sleep(2000);
                    for (int ia = 0; ia < 3; ia++)
                    {
                        if (ia > 0)
                            Sleep(this.RunCreationWaitDelay);
                        JoinGame(this.CurrentGameNum, this.CurrentGameName, this.CurrentGamePassword);
                        for (int tt = 0; tt < 1000; tt++)
                        {
                            Sleep(1);
                            if (this.InGame)
                                break ;
                                //break;
                            if (this.FailedToJoin)
                                continue;
                        }
                        if (this.InGame)
                            break;
                        if (LastJoinResult == RealmServer.JoinGameResult.GameDoesNotExist)
                            break;
                    }
                    //Sleep(1000);
                    if (!this.InGame)
                        continue;
                    try
                    {
                        if (myTest.ComeBack(ref myGameServerClient))
                            this.TotalCompletedRuns += 1;
                    }
                    catch
                    {

                    }
                }
                
                Logger.Log("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
                Logger.Log("Total completed runs: " + this.TotalCompletedRuns + " on " + this.TotalRuns);
                Logger.Log("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");

                if (FatalDebugError)
                {
                    Logger.Log("Fatal error, trying to reconnect to bnet");
                    onRunDone();
                    //continue;
                }
                
            }
        }

        public void CheckCdKeys()
        {
            if (!System.IO.File.Exists(Environment.CurrentDirectory + "\\system\\State\\" + this.myBotConfig._CharacterName))
                System.IO.File.Create(Environment.CurrentDirectory + "\\system\\State\\" + this.myBotConfig._CharacterName).Close();
            System.IO.StreamReader sr = new System.IO.StreamReader(Environment.CurrentDirectory + "\\system\\State\\" + this.myBotConfig._CharacterName);
            string line = sr.ReadLine();
            Logger.Log("CHECK CD KEYS: LINE = " + line);
            if (line == null || line == "")
            {
                this.KeyListIndex = 0;
            }
            else
            {
                this.KeyListIndex = Convert.ToInt32(line) + 1;
            }
            sr.Close();
            sr.Dispose();
            if (this.KeyListIndex > this.myBotConfig._ClassicKeyList.Length - 1)
                this.KeyListIndex = 0;
            System.IO.StreamWriter sw = new System.IO.StreamWriter(Environment.CurrentDirectory + "\\system\\State\\" + this.myBotConfig._CharacterName, false);
            sw.Write(this.KeyListIndex);
            sw.Close();
            sw.Dispose();
        }

        /// <summary>
        /// will simply try to disconnect from the gameserver
        /// </summary>
        public void onRunDone()
        {
            Sleep(100);
            byte[] GCExitGame = GameClient.ExitGame.Build();
            try
            {
                myGameServerClient.GetStream().Write(GCExitGame, 0, GCExitGame.Length);
            }
            catch {}
            Sleep(100);
            try
            {
                myGameServerClient.Client.Shutdown(SocketShutdown.Both);
            }
            catch { }
            Sleep(100);
            try
            {
                myGameServerClient.Client.Close();
            }
            catch { }
            Sleep(100);
            myGameServerClient = null;
            Sleep(100);
            
        }

        /// <summary>
        /// Used to connect to battle.net
        /// </summary>
        /// <param name="botConfig">Somewhat redundant I can probably remove this (?)</param>
        /// <returns>success or not</returns>
        public bool ConnectToBattleNet(BotConfig botConfig)
        {
            CheckCdKeys();
            Logger.Log("Connecting to battle.net...");
            this.FatalDebugError = false;
            this.LoginDone = false;
            this.myBotConfig = botConfig;
            myBnetServerClient = new TcpClient(this.GetServerString(this.myBotConfig._Server), 6112);
            myBnetServerClient.LingerState = new LingerOption(true, 0);
            if (myPacketSniffer != null)
            {
                myPacketSniffer.Dispose();
                myPacketSniffer = null;
            }
            myPacketSniffer = new PacketSniffer();
            myPacketSniffer.AddListener(D2Packets.PacketOrigin.BattleNetServer, new PacketEventHandler(this.onBnetPacketReceived));
            myPacketSniffer.AddListener(D2Packets.PacketOrigin.RealmServer, new PacketEventHandler(this.onRealmPacketReceived));
            myPacketSniffer.StartSniffing(Process.GetCurrentProcess().Id, myBotConfig._PcapName);

            try
            {
                myBnetServerClient.GetStream().WriteByte(0x01);
                myBnetServerClient.GetStream().Write(new BC.ConnectionRequest().Build(), 0, new BC.ConnectionRequest().Build().Length);
            }
            catch
            {
                this.NeedIPReset = true;
                return false;
            }

            int Timeout = 0;
            while (!this.FatalDebugError && !this.LoginDone)
            {
                System.Threading.Thread.Sleep(1);
                if (Timeout > 5000)
                {
                    Logger.Log("Failed to connect to battle.net: Timed out");
                    this.NeedIPReset = true;
                    return false;
                }
                Timeout++;
            }
            if (this.FatalDebugError)
            {
                Logger.Log("Failed to connect to battle.net");
                return false;
            }
            this.NeedIPReset = false;
            Logger.Log("We are now logged onto battle.net");
            return true;
        }
        
        /// <summary>
        /// Disconnect from battle.net
        /// this function should maby check gameserver (?)
        /// </summary>
        public void Disconnect()
        {
            Logger.Log("Disconnecting from battle.net...");
            this.onRunDone();
            if (myRealmServerClient != null)
            {
                try
                {
                    myRealmServerClient.Client.Shutdown(SocketShutdown.Both);
                }
                catch { }
                Sleep(100);
                try
                {
                    myRealmServerClient.Client.Close();
                }
                catch { }
                Sleep(100);
            }
            if (myBnetServerClient != null)
            {
                try
                {
                    myBnetServerClient.Client.Shutdown(SocketShutdown.Both);
                }
                catch { }
                Sleep(100);
                try
                {
                    myBnetServerClient.Client.Close();
                }
                catch { }
                Sleep(100);
            }
            myRealmServerClient = null;
            myBnetServerClient = null;
            myGameServerClient = null;
        }
        void Disconnect_BnetServer()
        {
            if (myBnetServerClient != null)
            {
                try
                {
                    myBnetServerClient.Client.Shutdown(SocketShutdown.Both);
                }
                catch { }
                Sleep(100);
                try
                {
                    myBnetServerClient.Client.Close();
                }
                catch { }
                Sleep(100);
            }
        }
        void Disconnect_RealmServer()
        {
            this.onRunDone();
            if (myRealmServerClient != null)
            {
                try
                {
                    myRealmServerClient.Client.Shutdown(SocketShutdown.Both);
                }
                catch { }
                Sleep(100);
                try
                {
                    myRealmServerClient.Client.Close();
                }
                catch { }
                Sleep(100);
            }
        }
      
        /// <summary>
        /// Join a game. I need to change the return value to bool, it would be alot easier to use.
        /// </summary>
        /// <param name="GameNumber"></param>
        /// <param name="GameName"></param>
        /// <param name="GamePassword"></param>
        void JoinGame(ushort GameNumber, string GameName, string GamePassword)
        {
            Logger.Log("Joining game: " + GameName);
            byte[] myJoinGame = new data.RC.JoinGame(GameNumber, GameName, GamePassword).GetData();
            Sleep(100);
            myRealmServerClient.GetStream().Write(myJoinGame, 0, myJoinGame.Length);
        }
        
        /// <summary>
        /// Create a game. I need to change the return value to bool, it would be alot easier to use.
        /// </summary>
        /// <param name="GameNumber"></param>
        /// <param name="GameName"></param>
        /// <param name="GamePassword"></param>
        /// <param name="type"></param>
        /// <param name="GameDescription"></param>
        void CreateGame(ushort GameNumber, string GameName, string GamePassword,DifficultyType type,string GameDescription)
        {
            Logger.Log("Creating game: " + GameName);
            byte[] myCreateGame = new data.RC.CreateGame(GameNumber, type, GameName, GamePassword, GameDescription).GetData();
            Sleep(100);
            myRealmServerClient.GetStream().Write(myCreateGame, 0, myCreateGame.Length);
        }

        /// <summary>
        /// BNCS recv packets handler (event)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        void onBnetPacketReceived(object sender, PacketEventArgs args)
        {
            switch (args.Packet.Data[0])
            {
                case (int) D2Packets.BnetServerPacket.BnetPing:
                    BnetServer.BnetPing ping = args.Packet as BnetServer.BnetPing;
                    //Logger.Log("Bnet: Ping? " + ping.Timestamp);
                    uint Timestamp = ping.Timestamp;
                    BC.BasePacket pong = new data.BC.BasePacket(0x25);
                    pong.InsertUInt32(Timestamp);
                    byte[] raw = pong.GetData();
                    try
                    {
                        myBnetServerClient.GetStream().Write(raw, 0, raw.Length);
                    }
                    catch { }
                    //Logger.Log("Bnet: Pong!");
                    break;
                case (int)D2Packets.BnetServerPacket.BnetConnectionResponse:
                    //0x50
                    //this.KeyListIndex += 1;
                    if (this.KeyListIndex >= myBotConfig._ClassicKeyList.Length)
                        this.KeyListIndex = 0;
                    Logger.Log("BNetConnectionResponse received");
                    BnetServer.BnetConnectionResponse packet = args.Packet as BnetServer.BnetConnectionResponse;
                    this.ClientToken = (uint)Environment.TickCount;
                    MBNCSUtil.DataReader myReader = new MBNCSUtil.DataReader(packet.Data);
                    myReader.Seek(7);
                    this.ServerToken = myReader.ReadUInt32();
                    //send 0x51
                    BC.AuthorizationCheck myAUTH_CHECK = new data.BC.AuthorizationCheck(ClientToken, packet.VersionFileName
                        , packet.VersionFormulae, myBotConfig._GameFiles, myBotConfig._ClassicKeyList[KeyListIndex]
                        , myBotConfig._LodKeyList[KeyListIndex], ServerToken, myBotConfig._OwnerName);
                    Logger.Log("Sending AuthorizationCheck for cdkey #" + KeyListIndex);
                    Sleep(50);
                    myBnetServerClient.GetStream().Write(myAUTH_CHECK.Build(), 0, myAUTH_CHECK.Build().Length);
                    break;
                case (int)D2Packets.BnetServerPacket.BnetAuthResponse:
                    //0x51
                     BnetServer.BnetAuthResponse packet2 = args.Packet as BnetServer.BnetAuthResponse;
                     if (packet2.Result == BnetServer.BnetAuthResult.Success)
                     {
                         Logger.Log("Battle.net authorization success");
                         Logger.Log("Logging onto account: " + myBotConfig._AccountName);
                         Sleep(10);
                         byte[] accinfo = new BC.AccountInfo(myBotConfig._AccountName,myBotConfig._AccountPassword,(int)this.ClientToken,(int)this.ServerToken).Build();
                         myBnetServerClient.GetStream().Write(accinfo, 0, accinfo.Length);
                     }
                     else
                     {
                         Logger.Log("Could not pass battle.net authorization check. Result: " + packet2.Result.ToString());
                         if (packet2.Result != BnetServer.BnetAuthResult.CDKeyInUse)
                         {
                             this.NeedIPReset = true;
                             Logger.Log("BAD CDKEY DETECTED AT INDEX " + this.KeyListIndex);
                         };
                         this.FatalDebugError = true;
                     }
                     break;
                case (int) D2Packets.BnetServerPacket.BnetLogonResponse:
                    //0x3a
                     BnetServer.BnetLogonResponse packet3 = args.Packet as BnetServer.BnetLogonResponse;
                     if (packet3.Result == BnetServer.BnetLogonResult.Success)
                     {
                         Logger.Log("Account logon success");
                         //query a list of realms
                         MBNCSUtil.BncsPacket myQueryPacket = new MBNCSUtil.BncsPacket(0x40);
                         myBnetServerClient.GetStream().Write(myQueryPacket.GetData(), 0, myQueryPacket.GetData().Length);
                     }
                     else
                     {
                         Logger.Log("Could not log onto account. Result: " + packet3.Result);
                         this.FatalDebugError=true;
                     }
                    break;
                case (int) D2Packets.BnetServerPacket.QueryRealmsResponse:
                    //0x40
                     BnetServer.QueryRealmsResponse packet4 = args.Packet as BnetServer.QueryRealmsResponse;
                     this.RealmServerString = packet4.Realms[0].Name;
                     //send a request for realm server logon
                     byte[] myRealmLogon = new data.BC.RealmLogon(this.RealmServerString,(int) this.ClientToken,(int) this.ServerToken).Build();
                     Sleep(50);
                     myBnetServerClient.GetStream().Write(myRealmLogon, 0, myRealmLogon.Length);
                    break;
                case (int) D2Packets.BnetServerPacket.RealmLogonResponse :
                    //0x3e
                     BnetServer.RealmLogonResponse packet5 = args.Packet as BnetServer.RealmLogonResponse;
                     if (packet5.Result == BnetServer.RealmLogonResult.Success)
                     {
                         Logger.Log("Realm logon data received successfully");
                         RealmServerIp = packet5.RealmServerIP;
                         this.BNCSUniqueName = packet5.Username;
                         myRealmServerClient = new TcpClient();
                         myRealmServerClient.LingerState = new LingerOption(true, 0);
                         myRealmServerClient.Connect(RealmServerIp, 6112);
                         System.Threading.Thread.Sleep(10);
                         myRealmServerClient.GetStream().WriteByte(0x01);
                         System.Threading.Thread.Sleep(10);
                         byte[] tmpdata = new byte[packet5.Data.Length+1];
                         tmpdata[0] = 0x01;
                         for (int i = 0; i < packet5.Data.Length; i++)
                             tmpdata[i + 1] = packet5.Data[i];
                         RS.Logon alogon = new data.RS.Logon(tmpdata);
                         RSLogon = new RC.Logon(alogon).Build();
                         Sleep(50);
                         myRealmServerClient.GetStream().Write(RSLogon, 0, RSLogon.Length);
                     }
                     else
                     {
                         Logger.Log("Failed to log onto realm server");
                         
                         this.FatalDebugError = true;
                     }
                    break;
                default:
                    break;
            }
            
        }
        
        /// <summary>
        /// Realmserver recv packets handler (event)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        void onRealmPacketReceived(object sender, PacketEventArgs args)
        {
            switch (args.Packet.Data[0])
            {

                case (int) D2Packets.RealmServerPacket.RealmStartupResponse:
                    //0x01
                    RealmServer.RealmStartupResponse rsesponce = args.Packet as RealmServer.RealmStartupResponse;
                    if (rsesponce.Result == RealmServer.RealmStartupResult.Success)
                    {
                        Logger.Log("Realm logon success");
                        byte[] CharLogonPacket = new RC.CharacterLogon(myBotConfig._CharacterName).GetData();
                        System.Threading.Thread.Sleep(100);
                        myRealmServerClient.GetStream().Write(CharLogonPacket, 0, CharLogonPacket.Length);
                        this.LoginDone = true;
                    }
                    else
                    {
                        Logger.Log("Failed to log onto realm server. result: " + rsesponce.Result.ToString());
                        if (rsesponce.Result == RealmServer.RealmStartupResult.TemporaryIPBan)
                            this.NeedIPReset = true;
                        this.FatalDebugError = true;
                    }

                    break;

                case (int)D2Packets.RealmServerPacket.JoinGameResponse:
                    //0x04
                    RealmServer.JoinGameResponse JoinResponse = args.Packet as RealmServer.JoinGameResponse;
                    Logger.Log("JoinGameResponse received. result: " + JoinResponse.Result.ToString());
                    if (JoinResponse == null)
                    {
                        Logger.Log("Failed to join game, Packet is null (WTF?)");
                        this.FailedToJoin = true;
                        return;
                    }
                    LastJoinResult = JoinResponse.Result;
                    if (JoinResponse.Result != RealmServer.JoinGameResult.Success)
                    {
                        Logger.Log("Failed to join game. Reason: " + JoinResponse.Result);
                        this.FailedToJoin = true;
                        if (JoinResponse.Result == RealmServer.JoinGameResult.GameDoesNotExist)
                            this.NeedIPReset = true;
                        return;
                    }
                    Logger.Log("Connecting to GameServer...");
                    myGameServerClient = new TcpClient();
                    myGameServerClient.LingerState = new LingerOption(true, 0);

                    if (myGameServerClient.Connected)
                    {
                        return;
                    }
                    myGameServerClient.Connect(JoinResponse.GameServerIP, 4000);
                    for (int c = 0; c < 1000 && !myGameServerClient.Connected; c++)
                        System.Threading.Thread.Sleep(1);
                    if (!myGameServerClient.Connected)
                    {
                        this.FailedToJoin = true;
                        Logger.Log("Failed to connect to gameserver");
                        return;
                    }
                    BC.NotifyJoin myNotifyJoin = new data.BC.NotifyJoin(CurrentGameName,CurrentGamePassword);
                    byte[] BSNotifyJoin = myNotifyJoin.GetData();//bug here retrieve like packet x10
                    try
                    {
                        myBnetServerClient.GetStream().Write(BSNotifyJoin, 0, BSNotifyJoin.Length);
                    }
                    catch
                    {
                        this.FailedToJoin = true;
                        return;
                    }
                    Sleep(50);
                    byte[] GCLogon = new GCp.GameLogon(JoinResponse.GameHash, JoinResponse.GameToken
                        , myBotConfig._CharacterClass, myBotConfig._CharacterName).GetData();

                    try
                    {
                        myGameServerClient.GetStream().Write(GCLogon, 0, GCLogon.Length);
                    }
                    catch
                    {
                        this.FailedToJoin = true;
                        return;
                    }
                    Sleep(50);
                    try
                    {
                        myGameServerClient.GetStream().WriteByte(0x6b);
                    }
                    catch
                    {
                        this.FailedToJoin = true;
                        return;
                    }
                    Sleep(50);
                    try
                    {
                        byte[] TestConnectionPacket = GameClient.SelectSkill.Build(D2Data.SkillType.Telekinesis,D2Data.SkillHand.Right);
                        myGameServerClient.GetStream().Write(TestConnectionPacket,0,TestConnectionPacket.Length);
                    }
                    catch
                    {
                        this.FailedToJoin = true;
                        return;
                    }
                    this.InGame = true;
                    break;

                case (int)D2Packets.RealmServerPacket.CreateGameResponse:
                    //0x03
                    RealmServer.CreateGameResponse CreateResponse = args.Packet as RealmServer.CreateGameResponse;
                    if (CreateResponse.Result == RealmServer.CreateGameResult.Success)
                    {
                        JoinGame(CurrentGameNum, CurrentGameName, CurrentGamePassword);
                    }
                    else
                    {
                        Logger.Log("Failed to create game: " + CreateResponse.Result);
                        this.FatalDebugError = true;
                    }
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// Convert a Server enum used in botconfig to a server string used in TcpClient.Connect()
        /// </summary>
        /// <param name="server"></param>
        /// <returns></returns>
        string GetServerString(Server server)
        {
            switch (server)
            {
                case Server.Asia:
                    return "asia.battle.net";
                case Server.Europe:
                    return "europe.battle.net";
                case Server.UsEast:
                    return "useast.battle.net";
                case Server.UsWest:
                    return "uswest.battle.net";
                default:
                    throw new ApplicationException("GetServerString() unknown server passed to function");
            }
        }

        /// <summary>
        /// Non-Blocking sleep method
        /// </summary>
        /// <param name="delay"></param>
        void Sleep(int delay)
        {
            int StartTime = Environment.TickCount;
            while (true)
            {
                System.Threading.Thread.Sleep(1);
                if (Environment.TickCount - StartTime >= delay)
                    return;
            }
        }

        /// <summary>
        /// This is more for debugging purpose. What is state IdentifyConnection?
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        void myPacketSniffer_OnConnectionChange(object sender, D2Packets.ConnectionChangeEventArgs args)
        {
            Logger.Log("----------- CONNECTION CHANGED -----------");
            Logger.Log("CONNECTION STATE: " + args.Type);
            Game.GameInfo.RST = true;
        }
    }
}