How to develop a Battle.net client in 10 minutes
From JinxBot
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.

