Valhalla Legends Forums Archive | Battle.net Bot Development | Setting Bot Users - Method

AuthorMessageTime
Mephisto
I'm new to this whole bot development thing, and I have recently finished coding the necessary code to connect to Battle.net and receive/parse chat events. Now I am moving on to writing the database, and I am wondering how to do this. How do I represent a user? I was thinking of just having the bot read from a database file and get the username and their flags. That brings me to my next question, how should I represent flags? I was thinking of writing a class for each flag, and in that class write each of the commands as a function. But then I get to the point of how do I add a flag (class) to that username, and limit access to other flags (classes)? I havn't put much thought into it, but I will be thinking of ideas as I get feedback from those who can assist in this.

Keep in mind, this is being written in C++.
March 4, 2004, 1:23 AM
Null
For someone who knows 10 or so language's Fluently this should be an easy task..
March 4, 2004, 1:25 AM
Mephisto
You guys are fast.

I never said I knew 10 languages, let alone knew them fluently.

Additionally, I said in the post I havn't put much thought into it, I'm already applying some ideas. This is just to get some feedback on experienced people in doing this, so I don't go implement a system which would be otherwise infurior to other methods which can be used.

Edit: Well, I suppose it's 10 if you count English. But I still stand by the fact I never said I knew them fluently.
March 4, 2004, 1:27 AM
LoRd
Go to the C/C++ programming forum.
March 4, 2004, 2:08 AM
Mephisto
If this was C/C++ specific, I think someone would have moved it by now.

Additionally, you don't necessarily have to know C++ to help me out with this.
March 4, 2004, 2:43 AM
Zakath
Represent a user's flags as a bitmask. When you retrieve a user's information from the database file, convert each flag into the equivalent value, then construct the bitmask out of them. Then when processing a command, simply see if they have the necessary flag by using the & operator.
March 4, 2004, 6:47 AM
K
I like to use a std::map to map battle.net names to unique bot names, to map to user info.
something like

[code]
class BotUserInfo
{
public:
// the name to call the user
std::string ReferenceName;

std::vector<std::string> AccountNames;
std::string Email;
std::string AIM;

bool CanBan() { return (Flags & bn::BAN_MASK); }
bool CanKick() { return (Flags & bn::KICK_MASK); }
// etc or:
bool GetPriv(unsigned int mask) { return (Flags & mask); }

void SetPriv(unsigned int mask) { Flags |= mask; }
private:
unsigned int Flags;
};


// now we can translate one of several battle.net names
// into a unique user account name
std::map<std::string, std::string> UserLookup;

// and that account name into the user's info.
std::map<std::string, bn::BotUserInfo> UserInfo;

[/code]

March 4, 2004, 7:05 AM
Myndfyr
I'm big on extensions, so I created a simple interface (IUser) that any extension assembly (note that I'm writing in C#, so it's .NET) can provide their own implementation and then just pass that around. I also defined an interface for a data provider such as:

[code]
public interface IDataProvider {
IUser GetUser(string szUserName);
IUser CreateUser(string szUserName, int dwRank);
//etc...
void SendBotMail(IUser sender, IUser receiver, string Message);
IBotMaiil[] GetMessages(IUser receiver);
}
[/code]

That is obviously not the entire idea, but I believe if you define well first how you want your database to behave, you'll find yourself in a much better position down the road.
March 4, 2004, 6:20 PM
Adron
I tend to like having flags. If 32 flags is enough for you, use a bitmap. For maximum configurability, allow users to be given any combination of flags, and allow commands or actions to require any combination of flags.

A user could then be:
[code]
struct User {
char name[MAX_NAME];
unsigned flags;
};
[/code]

A command could then be:

[code]
struct Command {
char trigger[MAX_TRIGGER];
unsigned positiveflags;
unsigned negativeflags;
void (*processcommand)( ... );
};
[/code]

[code]
if((user.flags & cmd.positiveflags) && !(user.flags & cmd.negativeflags))
cmd.processcommand(...);
[/code]

March 5, 2004, 5:09 PM
DarkMinion
First I have a struct:

[code]struct User{
   char szMask[32];
   unsigned long dwFlags;
};[/code]

Then a list (if you want my linked list class you can have that too, just ask):

[code]
List<User *> Database;
[/code]

Then I use these 3 functions to set/remove/check my flags (thanks Sky for these, btw):

[code]
bool CheckFlag(unsigned long dwMask, char bFlag)
{
   if(bFlag < 'A' || bFlag > 'Z')
      return false;
   return !!(dwMask & (1 << (bFlag - 'A')));
}

void SetFlag(unsigned long *dwMask, char bFlag)
{
   if(bFlag < 'A' || bFlag > 'Z')
      return;
   *dwMask |= (1 << (bFlag - 'A'));
}

void RemoveFlag(unsigned long *dwMask, char bFlag)
{
   if(bFlag < 'A' || bFlag > 'Z')
      return;
   *dwMask &= ~(1 << (bFlag - 'A'));
}
[/code]

So say I wanted to make a new DB entry I would do something like...

[code]
User *pNew = new User;
strcpy(pNew->szMask, "testuser"); //set the user mask
pNew->dwFlags = 0;
SetFlag(pNew->dwFlags, 'A'); //set flag(s)
Database.Add(pNew);
[/code]

If I wanted to modify an entry's flags, I would do something like...

[code]
//find the user
User *p;
for(int i = 0; i < Database.Count(); i++){
   p = Database.Get(i);
   if(!stricmp(szEntryToFind, p->szMask))
      break;
}
//modify
RemoveFlag(p->dwFlags, 'N'); //or whatever
[/code]

If you have questions, feel free to ask...I'll post a link to my linked list class if you want it.
March 5, 2004, 6:06 PM
Kp
Minor suggested improvement to DarkMinion's approach -- since you're already using new to allocate the structure, it'll take care of calling a constructor if you provide one. As such, you could have two constructors: default, which sets name = "" and flags to 0, and one that takes a const char* and an unsigned, and saves the string + flags into the user structure before returning. It wouldn't be any more or less efficient runtime wise afaik, but it would make for simpler user creation code. :)

[Edit: just noticed that DarkMinion's code will actually produce a user with unpredictable flags. SetFlag is more properly AddFlag, and the flags aren't being set to a known value first. Therefore, your only guarantee is that the resulting user will have 'A' as a flag -- he might have other flags as well. To avoid this, explicitly set the flags variable to zero.]
March 5, 2004, 10:13 PM
DarkMinion
Sorry, forgot to initialize flags...thanks for reminding me Kp, fixed.
March 6, 2004, 1:24 AM

Search