How to develop a Battle.net client in 10 minutes

From JinxBot

Jump to: navigation, search

Please note: In order to complete this tutorial you will need a basic understanding of the C# programming language and already have a development environment set up. It will familiarize you with the concepts of programming with BN# and will present a rudimentary console-based client.

Although BN# is developed so that it is compatible with the Microsoft .NET Framework 2.0, this sample uses C# 3.0 features only found by using the .NET Framework 3.5 compiler.


Contents

Step 1: Set up the environment

First, create a new Windows Console project in C#. Once you have created a new project, be sure to add a reference to BN#. To do so, right-click on your project and choose "Add Reference". Choose "Browse", navigate to the location in which BNSharp.dll is located, and double-click it.


Step 2: Implement IBattleNetSettings

The IBattleNetSettings interface must be implemented. Here is a sample implementation:

   class Settings : IBattleNetSettings
   { 
       #region IBattleNetSettings Members
 
       public string Client
       {
           get
           {
               return "STAR";
           }
           set
           {
               
           }
       }
 
       public int VersionByte
       {
           get
           {
               return 0xd1;
           }
           set
           {
              
           }
       }
 
       public string CdKey1
       {
           get;
           set;
       }
 
       public string CdKey2
       {
           get
           {
               return null;
           }
           set
           {
               
           }
       }
 
       public string GameExe
       {
           get
           {
               return @"C:\Gamefiles\STAR\Starcraft.exe";
           }
           set
           {
               
           }
       }
 
       public string GameFile2
       {
           get
           {
               return @"C:\Gamefiles\STAR\Storm.dll";
           }
           set
           {
               
           }
       }
 
       public string GameFile3
       {
           get
           {
               return @"C:\Gamefiles\STAR\Battle.snp";
           }
           set
           {
               
           }
       }
 
       public string Username
       {
           get;
           set;
       }
 
       public string ImageFile
       {
           get
           {
               return @"C:\Gamefiles\STAR\STAR.bin";
           }
           set
           {
               
           }
       }
 
       public string Password
       {
           get;
           set;
       }
 
       public string Server
       {
           get
           {
               return "useast.battle.net";
           }
           set
           {
               
           }
       }
 
       public int Port
       {
           get
           {
               return 6112;
           }
           set
           {
               
           }
       }
 
       public string CdKeyOwner
       {
           get;
           set;
       }
 
       #endregion
   }

This implementation has four Automatic Properties that are required: CdKey1, CdKeyOwner, Username, and Password. It connects with Starcraft to the server useast.battle.net. It also makes assumptions about where your game files are; it requires Starcraft.exe, Storm.dll, Battle.snp, and Star.bin (for Lockdown support).

Step 3: Create the Client

Within your Program.cs file, prompt the user for the information needed to connect and then instantiate the client. Here's a sample:

       static void Main(string[] args)
       {
           Console.WriteLine("Logging on with Starcraft; enter CD key.");
           string cdKey = Console.ReadLine().Trim();
           Console.WriteLine("Enter account name:");
           string acct = Console.ReadLine().Trim();
           Console.WriteLine("Enter account password for {0}:", acct);
           string password = Console.ReadLine().Trim();
 
           Settings set = new Settings() { CdKey1 = cdKey, Username = acct, Password = password, CdKeyOwner = acct };
 
           BattleNetClient client = new BattleNetClient(set);
       }

You might note that instantiating the Settings object uses the new C# 3.0 object initializer syntax to set properties.


Step 4: Wire up the events.

Now you'll need to hook up your events. Take a look at the modified Main() function as well as the new functions added to the Program class:

   class Program
   {
       static void Main(string[] args)
       {
           Console.WriteLine("Logging on with Starcraft; enter CD key.");
           string cdKey = Console.ReadLine().Trim();
           Console.WriteLine("Enter account name:");
           string acct = Console.ReadLine().Trim();
           Console.WriteLine("Enter account password for {0}:", acct);
           string password = Console.ReadLine().Trim();
 
           Settings set = new Settings() { CdKey1 = cdKey, Username = acct, Password = password, CdKeyOwner = acct };
 
           BattleNetClient client = new BattleNetClient(set);
           client.Connected += delegate { Console.WriteLine("--- CONNECTED"); };
           client.Error += new ErrorEventHandler(client_Error);
           client.EnteredChat += new EnteredChatEventHandler(client_EnteredChat);
           client.LoginSucceeded += new EventHandler(client_LoginSucceeded);
           client.LoginFailed += new EventHandler(client_LoginFailed);
           client.ServerBroadcast += new ServerChatEventHandler(client_ServerBroadcast);
           client.ServerErrorReceived += new ServerChatEventHandler(client_ServerErrorReceived);
           client.UserShown += new UserEventHandler(client_UserShown);
           client.UserJoined += new UserEventHandler(client_UserJoined);
           client.UserLeft += new UserEventHandler(client_UserLeft);
           client.UserSpoke += new ChatMessageEventHandler(client_UserSpoke);
           client.UserEmoted += new ChatMessageEventHandler(client_UserEmoted);
           client.ClientCheckPassed += delegate { Console.WriteLine("--- VERSIONING PASSED"); };
           client.ClientCheckFailed += new ClientCheckFailedEventHandler(client_ClientCheckFailed);
           client.JoinedChannel += new ServerChatEventHandler(client_JoinedChannel);
           client.WardentUnhandled += delegate { Console.WriteLine("--- WARNING: Warden requested and unhandled!!"); };
           client.MessageSent += new ChatMessageEventHandler(client_MessageSent);
           client.Disconnected += delegate { Console.WriteLine("--- DISCONNECTED"); };
 
           Console.WriteLine("Events hooked up; press <enter> to connect.");
           Console.ReadLine();
       }
 
       static void client_MessageSent(object sender, ChatMessageEventArgs e)
       {
           if (e.EventType == ChatEventType.Emote)
           {
               Console.WriteLine("<{0} {1}>", e.Username, e.Text);
           }
           else
           {
               Console.WriteLine("[{0}]: {1}", e.Username, e.Text);
           }
       }
 
       static void client_JoinedChannel(object sender, ServerChatEventArgs e)
       {
           Console.WriteLine("CHANNEL: {0}", e.Text);
       }
 
       static void client_ClientCheckFailed(object sender, ClientCheckFailedEventArgs e)
       {
           Console.WriteLine("--- VERSIONING FAILED {0}:", e.Reason);
           Console.WriteLine(e.AdditionalInformation);
       }
 
       static void client_UserEmoted(object sender, ChatMessageEventArgs e)
       {
           Console.WriteLine("<{0} {1}>", e.Username, e.Text);
       }
 
       static void client_UserSpoke(object sender, ChatMessageEventArgs e)
       {
           Console.WriteLine("{0}: {1}", e.Username, e.Text);
       }
 
       static void client_UserLeft(object sender, UserEventArgs e)
       {
           Console.WriteLine("USER LEFT: {0}", e.Username);
       }
 
       static void client_UserJoined(object sender, UserEventArgs e)
       {
           Console.WriteLine("USER JOIN: {0} ({1})", e.Username, e.Statstring);
       }
 
       static void client_UserShown(object sender, UserEventArgs e)
       {
           Console.WriteLine("USER: {0} ({1})", e.Username, e.Statstring);
       }
 
       static void client_ServerErrorReceived(object sender, ServerChatEventArgs e)
       {
           Console.WriteLine("SERVER ERROR: {0}", e.Text);
       }
 
       static void client_ServerBroadcast(object sender, ServerChatEventArgs e)
       {
           Console.WriteLine("SERVER: {0}", e.Text);
       }
 
       static void client_LoginFailed(object sender, EventArgs e)
       {
           Console.WriteLine("--- LOGIN FAILED:");
       }
 
       static void client_LoginSucceeded(object sender, EventArgs e)
       {
           Console.WriteLine("--- LOGIN SUCCEEDED");
       }
 
       static void client_EnteredChat(object sender, EnteredChatEventArgs e)
       {
           Console.WriteLine("Entered chat as {0}", e.UniqueUsername);
       }
 
       static void client_Error(object sender, ErrorEventArgs e)
       {
           Console.WriteLine("ERROR: {0}", e.Error);
       }
   }


Step 5: Create the Client Running Loop

The client needs to stay alive while your program is running. After you have wired up the events, it is easy to connect your client.

       static void Main(string[] args)
       {
           Console.WriteLine("Logging on with Starcraft; enter CD key.");
           string cdKey = Console.ReadLine().Trim();
           Console.WriteLine("Enter account name:");
           string acct = Console.ReadLine().Trim();
           Console.WriteLine("Enter account password for {0}:", acct);
           string password = Console.ReadLine().Trim();
 
           Settings set = new Settings() { CdKey1 = cdKey, Username = acct, Password = password, CdKeyOwner = acct };
 
           BattleNetClient client = new BattleNetClient(set);
           client.Connected += delegate { Console.WriteLine("--- CONNECTED"); };
           client.Error += new ErrorEventHandler(client_Error);
           client.EnteredChat += new EnteredChatEventHandler(client_EnteredChat);
           client.LoginSucceeded += new EventHandler(client_LoginSucceeded);
           client.LoginFailed += new EventHandler(client_LoginFailed);
           client.ServerBroadcast += new ServerChatEventHandler(client_ServerBroadcast);
           client.ServerErrorReceived += new ServerChatEventHandler(client_ServerErrorReceived);
           client.UserShown += new UserEventHandler(client_UserShown);
           client.UserJoined += new UserEventHandler(client_UserJoined);
           client.UserLeft += new UserEventHandler(client_UserLeft);
           client.UserSpoke += new ChatMessageEventHandler(client_UserSpoke);
           client.UserEmoted += new ChatMessageEventHandler(client_UserEmoted);
           client.ClientCheckPassed += delegate { Console.WriteLine("--- VERSIONING PASSED"); };
           client.ClientCheckFailed += new ClientCheckFailedEventHandler(client_ClientCheckFailed);
           client.JoinedChannel += new ServerChatEventHandler(client_JoinedChannel);
           client.WardentUnhandled += delegate { Console.WriteLine("--- WARNING: Warden requested and unhandled!!"); };
           client.MessageSent += new ChatMessageEventHandler(client_MessageSent);
           client.Disconnected += delegate { Console.WriteLine("--- DISCONNECTED"); };
 
           Console.WriteLine("Events hooked up; press <enter> to connect.");
           Console.ReadLine();
 
           Console.WriteLine("Type /exit to quit.");
 
           client.Connect();
 
           string text;
           bool exit = false;
           do
           {
               text = Console.ReadLine();
               if (!text.Equals("/exit", StringComparison.Ordinal))
               {
                   client.SendMessage(text);
               }
               else
               {
                   exit = true;
               }
           } while (!exit);
 
           client.Close();
           Console.WriteLine("Disconnected; press <enter> to exit.");
           Console.ReadLine();
 
       }

All done!

Go ahead and run; barring any compilation errors, you should get something like this.

 Logging on with Starcraft; enter CD key.
 (removed)
 Enter account name:
 DarkTemplar~AoA
 Enter account password for DarkTemplar~AoA:
 (removed)
 Events hooked up; press <enter> to connect.
 
 Type /exit to quit.
 --- CONNECTED
 --- VERSIONING PASSED
 Entered chat as DarkTemplar~AoA
 CHANNEL: StarCraft USA-5
 USER: deckard97 (RATS 0 0 53 0 0 0 0 0 RATS)
 USER: Twizted(LT) (RATS 0 0 4 0 0 0 0 0 RATS)
 USER: NewbieForEver (RATS 0 0 4 0 0 0 0 0 RATS)
 USER: Adderall (RATS 0 0 21 0 0 0 0 0 RATS)
 USER: beastybunny (RATS 0 0 0 0 0 0 0 0 RATS)
 USER: SCv.KinG (RATS 0 0 0 0 0 0 0 0 RATS)
 USER: Evil[H3RO] (RATS 0 0 5 0 0 0 0 0 RATS)
 USER: DarkTemplar~AoA (RATS 0 0 3 0 0 0 0 0 RATS)
 USER: hyphyg8er71 (RATS 0 0 0 0 0 0 0 0 RATS)
 USER: FsL.Budzilla (RATS 0 0 0 0 0 0 0 0 RATS)
 USER: Bsparkes (RATS 0 0 0 0 0 0 0 0 RATS)
 --- WARNING: Warden requested and unhandled!!
 USER JOIN: letsgetropical (RATS 0 0 5 0 0 0 0 0 RATS)
 USER JOIN: rupepsu (RATS 0 0 200 0 0 0 0 0 RATS)
 USER JOIN: panzers (RATS 0 0 11 0 0 0 0 0 RATS)
 Evil[H3RO]: hey dark u there
 /eUSER LEFT: rupepsu
 xUSER LEFT: panzers                                                          YUS
 ER LEFT: letsgetropical
 es
 [Me]: Yes
 USER LEFT: SCv.KinG
 Hi
 [Me]: Hi
 Evil[H3RO]: sup dude
 Not much
 [Me]: Not much
 USER JOIN: SpliffBuilder (RATS 0 0 0 0 0 0 0 0 RATS)
 Just working on my new bot
 [Me]: Just working on my new bot
 Evil[H3RO]: yo i was wondering where did u get ur bot from??
 I'm making it
 [Me]: I'm making it
 Evil[H3RO]: ive been trying to get one
 Watch www.jinxbot.net
 [Me]: Watch www.jinxbot.net
 it'll be aUSER JOIN: panzers (RATS 0 0 11 0 0 0 0 0 RATS)
 round in the next couple weeks
 [Me]: it'll be around in the next couple weeks
 Evil[H3RO]: u dnyt need approval or anything??
 USER JOIN: SCv.KinG (RATS 0 0 0 0 0 0 0 0 RATS)
 Nope
 [Me]: Nope
 USER LEFT: panzers
 USER JOIN: l)r_FeeLgOOd (RATS 0 0 85 0 0 0 0 0 RATS)
 Evil[H3RO]: sweet
 Evil[H3RO]: thnx bro
 anUSER JOIN: panzers (RATS 0 0 11 0 0 0 0 0 RATS)
 yway, taking off
 [Me]: anyway, taking off
 take care
 [Me]: take care
 /exit
 Disconnected; press <enter> to exit.
 --- DISCONNECTED
 --- DISCONNECTED

This program is available in its entirety within the Subversion repository under the BNSharpTest project.

Personal tools
references