Bot Naming - View/Delete Databuckets

^bottitle
^botsuffix
^botsurname
#viewbuckets
#deletebucket
This commit is contained in:
kentai 2019-09-05 14:12:56 +10:00
parent eb4592c3ae
commit 8e1b6a23eb
9 changed files with 262 additions and 25 deletions

View File

@ -255,6 +255,18 @@ void Bot::SetBotSpellID(uint32 newSpellID) {
this->npc_spells_id = newSpellID;
}
void Bot::SetSurname(std::string bot_surname) {
_surname = bot_surname.substr(0, 31);
}
void Bot::SetTitle(std::string bot_title) {
_title = bot_title.substr(0, 31);
}
void Bot::SetSuffix(std::string bot_suffix) {
_suffix = bot_suffix.substr(0, 31);
}
uint32 Bot::GetBotArcheryRange() {
const EQEmu::ItemInstance *range_inst = GetBotItem(EQEmu::invslot::slotRange);
const EQEmu::ItemInstance *ammo_inst = GetBotItem(EQEmu::invslot::slotAmmo);
@ -3260,7 +3272,7 @@ bool Bot::Spawn(Client* botCharacterOwner) {
else
this->GetBotOwner()->CastToClient()->Message(Chat::Red, "%s save failed!", this->GetCleanName());
// Spawn the bot at the bow owner's loc
// Spawn the bot at the bot owner's loc
this->m_Position.x = botCharacterOwner->GetX();
this->m_Position.y = botCharacterOwner->GetY();
this->m_Position.z = botCharacterOwner->GetZ();
@ -3365,6 +3377,9 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
ns->spawn.helm = helmtexture; //(GetShowHelm() ? helmtexture : 0); //0xFF;
ns->spawn.equip_chest2 = texture; //0xFF;
ns->spawn.show_name = true;
strcpy(ns->spawn.lastName, GetSurname().c_str());
strcpy(ns->spawn.title, GetTitle().c_str());
strcpy(ns->spawn.suffix, GetSuffix().c_str());
const EQEmu::ItemData* item = nullptr;
const EQEmu::ItemInstance* inst = nullptr;
uint32 spawnedbotid = 0;

View File

@ -270,7 +270,12 @@ public:
bool GetNeedsHateRedux(Mob *tar);
bool HasOrMayGetAggro();
void SetDefaultBotStance();
void SetSurname(std::string bot_surname);
void SetTitle(std::string bot_title);
void SetSuffix(std::string bot_suffix);
std::string GetSurname() { return _surname; }
std::string GetTitle() { return _title; }
std::string GetSuffix() { return _suffix; }
inline virtual int32 GetMaxStat();
inline virtual int32 GetMaxResist();
inline virtual int32 GetMaxSTR();
@ -650,6 +655,9 @@ private:
uint32 _guildId;
uint8 _guildRank;
std::string _guildName;
std::string _surname;
std::string _title;
std::string _suffix;
uint32 _lastZoneId;
bool _rangerAutoWeaponSelect;
BotRoleType _botRole;

View File

@ -1351,10 +1351,13 @@ int bot_command_init(void)
bot_command_add("botspawn", "Spawns a created bot", 0, bot_subcommand_bot_spawn) ||
bot_command_add("botstance", "Changes the stance of a bot", 0, bot_subcommand_bot_stance) ||
bot_command_add("botstopmeleelevel", "Sets the level a caster or spell-casting fighter bot will stop melee combat", 0, bot_subcommand_bot_stop_melee_level) ||
bot_command_add("botsuffix", "Sets a bots suffix", 0, bot_subcommand_bot_suffix) ||
bot_command_add("botsummon", "Summons bot(s) to your location", 0, bot_subcommand_bot_summon) ||
bot_command_add("botsurname", "Sets a bots surname (last name)", 0, bot_subcommand_bot_surname) ||
bot_command_add("bottattoo", "Changes the Drakkin tattoo of a bot", 0, bot_subcommand_bot_tattoo) ||
bot_command_add("bottogglearcher", "Toggles a archer bot between melee and ranged weapon use", 0, bot_subcommand_bot_toggle_archer) ||
bot_command_add("bottogglehelm", "Toggles the helm visibility of a bot between shown and hidden", 0, bot_subcommand_bot_toggle_helm) ||
bot_command_add("bottitle", "Sets a bots title", 0, bot_subcommand_bot_title) ||
bot_command_add("botupdate", "Updates a bot to reflect any level changes that you have experienced", 0, bot_subcommand_bot_update) ||
bot_command_add("botwoad", "Changes the Barbarian woad of a bot", 0, bot_subcommand_bot_woad) ||
bot_command_add("charm", "Attempts to have a bot charm your target", 0, bot_command_charm) ||
@ -4408,7 +4411,7 @@ void bot_subcommand_bot_create(Client *c, const Seperator *sep)
return;
}
std::string bot_name = sep->arg[1];
bot_name = ucfirst(bot_name);
if (sep->arg[2][0] == '\0' || !sep->IsNumber(2)) {
c->Message(m_fail, "Invalid Class!");
return;
@ -4936,17 +4939,22 @@ void bot_subcommand_bot_list(Client *c, const Seperator *sep)
if (helper_command_alias_fail(c, "bot_subcommand_bot_list", sep->arg[0], "botlist"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(m_usage, "usage: %s ([class] [value]) ([race] [value]) ([name] [partial-full])", sep->arg[0]);
c->Message(m_usage, "usage: %s (account) ([class] [value]) ([race] [value]) ([name] [partial-full])", sep->arg[0]);
c->Message(m_note, "note: filter criteria is orderless and optional");
return;
}
bool Account = false;
int seps = 1;
uint32 filter_value[FilterCount];
int name_criteria_arg = 0;
memset(&filter_value, 0, sizeof(uint32) * FilterCount);
int filter_mask = 0;
for (int i = 1; i < (FilterCount * 2); i += 2) {
if (strcasecmp(sep->arg[1], "account") == 0) {
Account = true;
seps = 2;
}
for (int i = seps; i < (FilterCount * 2); i += 2) {
if (sep->arg[i][0] == '\0')
break;
@ -4971,7 +4979,7 @@ void bot_subcommand_bot_list(Client *c, const Seperator *sep)
}
std::list<BotsAvailableList> bots_list;
if (!database.botdb.LoadBotsList(c->CharacterID(), bots_list)) {
if (!database.botdb.LoadBotsList(c->CharacterID(), bots_list, Account)) {
c->Message(m_fail, "%s", BotDatabase::fail::LoadBotsList());
return;
}
@ -4981,6 +4989,7 @@ void bot_subcommand_bot_list(Client *c, const Seperator *sep)
}
int bot_count = 0;
int bots_owned = 0;
for (auto bots_iter : bots_list) {
if (filter_mask) {
if ((filter_mask & MaskClass) && filter_value[FilterClass] != bots_iter.Class)
@ -4996,23 +5005,26 @@ void bot_subcommand_bot_list(Client *c, const Seperator *sep)
continue;
}
}
c->Message(m_message, "%s is a level %u %s %s %s",
bots_iter.Name,
Bot * botCheckNotOnline = entity_list.GetBotByBotName(bots_iter.Name);
std::string botspawn_saylink = StringFormat("^botspawn %s", bots_iter.Name);
c->Message(Chat::White, "%s is a level %u %s %s %s who is owned by %s",
((c->CharacterID() == bots_iter.Owner_ID) && (!botCheckNotOnline) ? (EQEmu::SayLinkEngine::GenerateQuestSaylink(botspawn_saylink, false, bots_iter.Name).c_str()) : (bots_iter.Name)),
bots_iter.Level,
Bot::RaceIdToString(bots_iter.Race).c_str(),
((bots_iter.Gender == FEMALE) ? ("Female") : ((bots_iter.Gender == MALE) ? ("Male") : ("Neuter"))),
Bot::ClassIdToString(bots_iter.Class).c_str()
Bot::ClassIdToString(bots_iter.Class).c_str(),
bots_iter.Owner
);
if (c->CharacterID() == bots_iter.Owner_ID) { ++bots_owned; }
++bot_count;
}
if (!bot_count) {
c->Message(m_fail, "You have no bots meeting this criteria");
c->Message(Chat::Red, "You have no bots meeting this criteria");
}
else {
c->Message(m_action, "%i of %i bot%s shown", bot_count, bots_list.size(), ((bot_count != 1) ? ("s") : ("")));
c->Message(m_message, "Your limit is %i bot%s", RuleI(Bots, CreationLimit), ((RuleI(Bots, CreationLimit) != 1) ? ("s") : ("")));
c->Message(Chat::Yellow, "%i of %i bot%s shown.", bot_count, bots_list.size(), ((bot_count != 1) ? ("s") : ("")));
c->Message(Chat::Yellow, "%i of %i bot%s are owned by you. (You may spawn any available by clicking name)", bots_owned, bot_count, ((bot_count != 1) ? ("s") : ("")));
c->Message(Chat::White, "Your limit is %i bot%s", RuleI(Bots, CreationLimit), ((RuleI(Bots, CreationLimit) != 1) ? ("s") : ("")));
}
}
@ -5058,6 +5070,103 @@ void bot_subcommand_bot_out_of_combat(Client *c, const Seperator *sep)
}
}
void bot_subcommand_bot_surname(Client *c, const Seperator *sep)
{
if (sep->arg[1][0] == '\0' || sep->IsNumber(1)) {
c->Message(Chat::Red, "You must specify a [surname] to use this command (use _ to define spaces or -remove to clear.)");
return;
}
auto my_bot = ActionableBots::AsTarget_ByBot(c);
if (!my_bot) {
c->Message(Chat::Red, "You must <target> a bot that you own to use this command");
return;
}
if (strlen(sep->arg[1]) > 31) {
c->Message(Chat::Red, "Surname must be 31 characters or less.");
return;
}
std::string bot_surname = sep->arg[1];
bot_surname = (bot_surname == "-remove") ? "" : bot_surname;
std::replace(bot_surname.begin(), bot_surname.end(), '_', ' ');
my_bot->SetSurname(bot_surname);
if (!database.botdb.SaveBot(my_bot)) {
c->Message(Chat::Red, BotDatabase::fail::SaveBot());
return;
}
else {
auto outapp = new EQApplicationPacket(OP_GMLastName, sizeof(GMLastName_Struct));
GMLastName_Struct * gmn = (GMLastName_Struct*)outapp->pBuffer;
strcpy(gmn->name, my_bot->GetCleanName());
strcpy(gmn->gmname, my_bot->GetCleanName());
strcpy(gmn->lastname, my_bot->GetSurname().c_str());
gmn->unknown[0] = 1;
gmn->unknown[1] = 1;
gmn->unknown[2] = 1;
gmn->unknown[3] = 1;
entity_list.QueueClients(my_bot->CastToClient(), outapp);
safe_delete(outapp);
c->Message(Chat::Yellow, "Bot Surname Saved.");
}
}
void bot_subcommand_bot_title(Client *c, const Seperator *sep)
{
if (sep->arg[1][0] == '\0' || sep->IsNumber(1)) {
c->Message(Chat::Red, "You must specify a [title] to use this command. (use _ to define spaces or -remove to clear.)");
return;
}
auto my_bot = ActionableBots::AsTarget_ByBot(c);
if (!my_bot) {
c->Message(Chat::Red, "You must <target> a bot that you own to use this command");
return;
}
if (strlen(sep->arg[1]) > 31) {
c->Message(Chat::Red, "Title must be 31 characters or less.");
return;
}
std::string bot_title = sep->arg[1];
bot_title = (bot_title == "-remove") ? "" : bot_title;
std::replace(bot_title.begin(), bot_title.end(), '_', ' ');
my_bot->SetTitle(bot_title);
if (!database.botdb.SaveBot(my_bot)) {
c->Message(Chat::Red, BotDatabase::fail::SaveBot());
return;
}
else {
my_bot->CastToClient()->SetAATitle(my_bot->GetTitle().c_str());
c->Message(Chat::Yellow, "Bot Title Saved.");
}
}
void bot_subcommand_bot_suffix(Client *c, const Seperator *sep)
{
if (sep->arg[1][0] == '\0' || sep->IsNumber(1)) {
c->Message(Chat::Red, "You must specify a [suffix] to use this command. (use _ to define spaces or -remove to clear.)");
return;
}
auto my_bot = ActionableBots::AsTarget_ByBot(c);
if (!my_bot) {
c->Message(Chat::Red, "You must <target> a bot that you own to use this command");
return;
}
if (strlen(sep->arg[1]) > 31) {
c->Message(Chat::Red, "Suffix must be 31 characters or less.");
return;
}
std::string bot_suffix = sep->arg[1];
bot_suffix = (bot_suffix == "-remove") ? "" : bot_suffix;
std::replace(bot_suffix.begin(), bot_suffix.end(), '_', ' ');
my_bot->SetSuffix(bot_suffix);
if (!database.botdb.SaveBot(my_bot)) {
c->Message(Chat::Red, BotDatabase::fail::SaveBot());
return;
}
else {
my_bot->CastToClient()->SetTitleSuffix(my_bot->GetSuffix().c_str());
c->Message(Chat::Yellow, "Bot Suffix Saved.");
}
}
void bot_subcommand_bot_report(Client *c, const Seperator *sep)
{
if (helper_command_alias_fail(c, "bot_subcommand_bot_report", sep->arg[0], "botreport"))

View File

@ -614,8 +614,11 @@ void bot_subcommand_bot_report(Client *c, const Seperator *sep);
void bot_subcommand_bot_spawn(Client *c, const Seperator *sep);
void bot_subcommand_bot_stance(Client *c, const Seperator *sep);
void bot_subcommand_bot_stop_melee_level(Client *c, const Seperator *sep);
void bot_subcommand_bot_suffix(Client *c, const Seperator *sep);
void bot_subcommand_bot_summon(Client *c, const Seperator *sep);
void bot_subcommand_bot_surname(Client *c, const Seperator *sep);
void bot_subcommand_bot_tattoo(Client *c, const Seperator *sep);
void bot_subcommand_bot_title(Client *c, const Seperator *sep);
void bot_subcommand_bot_toggle_archer(Client *c, const Seperator *sep);
void bot_subcommand_bot_toggle_helm(Client *c, const Seperator *sep);
void bot_subcommand_bot_update(Client *c, const Seperator *sep);

View File

@ -163,12 +163,19 @@ bool BotDatabase::LoadQuestableSpawnCount(const uint32 owner_id, int& spawn_coun
return true;
}
bool BotDatabase::LoadBotsList(const uint32 owner_id, std::list<BotsAvailableList>& bots_list)
bool BotDatabase::LoadBotsList(const uint32 owner_id, std::list<BotsAvailableList>& bots_list, bool ByAccount)
{
if (!owner_id)
return false;
query = StringFormat("SELECT `bot_id`, `name`, `class`, `level`, `race`, `gender` FROM `bot_data` WHERE `owner_id` = '%u'", owner_id);
if (ByAccount == true)
query = StringFormat("SELECT bot_id, bd.`name`, bd.class, bd.`level`, bd.race, bd.gender, cd.`name` as owner, bd.owner_id, cd.account_id, cd.id"
" FROM bot_data as bd inner join character_data as cd on bd.owner_id = cd.id"
" WHERE cd.account_id = (select account_id from bot_data bd inner join character_data as cd on bd.owner_id = cd.id where bd.owner_id = '%u' LIMIT 1)"
" ORDER BY bd.owner_id", owner_id);
else
query = StringFormat("SELECT `bot_id`, `name`, `class`, `level`, `race`, `gender`, 'You' as owner, owner_id FROM `bot_data` WHERE `owner_id` = '%u'", owner_id);
auto results = database.QueryDatabase(query);
if (!results.Success())
return false;
@ -186,12 +193,17 @@ bool BotDatabase::LoadBotsList(const uint32 owner_id, std::list<BotsAvailableLis
bot_name = bot_name.substr(0, 63);
if (!bot_name.empty())
strcpy(bot_entry.Name, bot_name.c_str());
memset(&bot_entry.Owner, 0, sizeof(bot_entry.Owner));
std::string bot_owner = row[6];
if (bot_owner.size() > 63)
bot_owner = bot_owner.substr(0, 63);
if (!bot_owner.empty())
strcpy(bot_entry.Owner, bot_owner.c_str());
bot_entry.Class = atoi(row[2]);
bot_entry.Level = atoi(row[3]);
bot_entry.Race = atoi(row[4]);
bot_entry.Gender = atoi(row[5]);
bot_entry.Owner_ID = atoi(row[7]);
bots_list.push_back(bot_entry);
}
@ -266,8 +278,8 @@ bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot)
" `spells_id`,"
" `name`,"
" `last_name`,"
" `title`," /* planned use[4] */
" `suffix`," /* planned use[5] */
" `title`,"
" `suffix`,"
" `zone_id`,"
" `gender`,"
" `race`,"
@ -364,7 +376,9 @@ bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot)
loaded_bot = new Bot(bot_id, atoi(row[0]), atoi(row[1]), atof(row[14]), atoi(row[6]), tempNPCStruct);
if (loaded_bot) {
loaded_bot->SetShowHelm((atoi(row[43]) > 0 ? true : false));
loaded_bot->SetSurname(row[3]);//maintaining outside mob::lastname to cater to spaces
loaded_bot->SetTitle(row[4]);
loaded_bot->SetSuffix(row[5]);
uint32 bfd = atoi(row[44]);
if (bfd < 1)
bfd = 1;
@ -573,12 +587,14 @@ bool BotDatabase::SaveBot(Bot* bot_inst)
" `corruption` = '%i',"
" `show_helm` = '%i',"
" `follow_distance` = '%i',"
" `stop_melee_level` = '%u'"
" `stop_melee_level` = '%u',"
" `title` = '%s',"
" `suffix` = '%s'"
" WHERE `bot_id` = '%u'",
bot_inst->GetBotOwnerCharacterID(),
bot_inst->GetBotSpellID(),
bot_inst->GetCleanName(),
bot_inst->GetLastName(),
bot_inst->GetSurname().c_str(),
bot_inst->GetLastZoneID(),
bot_inst->GetBaseGender(),
bot_inst->GetBaseRace(),
@ -616,6 +632,8 @@ bool BotDatabase::SaveBot(Bot* bot_inst)
((bot_inst->GetShowHelm()) ? (1) : (0)),
bot_inst->GetFollowDistance(),
bot_inst->GetStopMeleeLevel(),
bot_inst->GetTitle().c_str(),
bot_inst->GetSuffix().c_str(),
bot_inst->GetBotID()
);
auto results = database.QueryDatabase(query);

View File

@ -50,7 +50,7 @@ public:
bool QueryNameAvailablity(const std::string& bot_name, bool& available_flag);
bool QueryBotCount(const uint32 owner_id, uint32& bot_count);
bool LoadQuestableSpawnCount(const uint32 owner_id, int& spawn_count);
bool LoadBotsList(const uint32 owner_id, std::list<BotsAvailableList>& bots_list);
bool LoadBotsList(const uint32 owner_id, std::list<BotsAvailableList>& bots_list, bool ByAccount = false);
bool LoadOwnerID(const std::string& bot_name, uint32& owner_id);
bool LoadOwnerID(const uint32 bot_id, uint32& owner_id);

View File

@ -32,6 +32,8 @@ struct BotsAvailableList {
uint8 Level;
uint16 Race;
uint8 Gender;
char Owner[64];
uint32 Owner_ID;
};
struct BotGroup {

View File

@ -185,6 +185,7 @@ int command_init(void)
command_add("date", "[yyyy] [mm] [dd] [HH] [MM] - Set EQ time", 90, command_date) ||
command_add("dbspawn2", "[spawngroup] [respawn] [variance] - Spawn an NPC from a predefined row in the spawn2 table", 100, command_dbspawn2) ||
command_add("delacct", "[accountname] - Delete an account", 150, command_delacct) ||
command_add("deletebucket", "[key]- Deletes data bucket", 80, command_deletebucket) ||
command_add("deletegraveyard", "[zone name] - Deletes the graveyard for the specified zone.", 200, command_deletegraveyard) ||
command_add("delpetition", "[petition number] - Delete a petition", 20, command_delpetition) ||
command_add("depop", "- Depop your NPC target", 50, command_depop) ||
@ -418,6 +419,7 @@ int command_init(void)
command_add("untraindiscs", "- Untrains all disciplines from your target.", 180, command_untraindiscs) ||
command_add("uptime", "[zone server id] - Get uptime of worldserver, or zone server if argument provided", 10, command_uptime) ||
command_add("version", "- Display current version of EQEmu server", 0, command_version) ||
command_add("viewbuckets", "[search string|limit]- View data buckets, limit 50 default", 80, command_viewbuckets) ||
command_add("viewnpctype", "[npctype id] - Show info about an npctype", 100, command_viewnpctype) ||
command_add("viewpetition", "[petition number] - View a petition", 20, command_viewpetition) ||
command_add("wc", "[wear slot] [material] - Sends an OP_WearChange for your target", 200, command_wc) ||
@ -12574,6 +12576,84 @@ void command_scale(Client *c, const Seperator *sep)
}
}
void command_viewbuckets(Client *c, const Seperator *sep)
{
std::string key_filter;
uint8 limit = 50;
for (int i = 1; i < 3; i++) {
if (sep->arg[i][0] == '\0')
break;
if (strcasecmp(sep->arg[i], "limit") == 0) {
limit = (uint8)atoi(sep->arg[i + 1]);
continue;
}
}
if (sep->arg[1]) {
key_filter = str_tolower(sep->arg[1]);
}
std::string query = "SELECT `id`, `key`, `value`, `expires` FROM data_buckets";
if (!key_filter.empty()) query += StringFormat(" WHERE `key` LIKE '%%%s%%'", key_filter.c_str());
query += StringFormat(" LIMIT %u", limit);
auto results = database.QueryDatabase(query);
if (!results.Success())
return;
if (results.RowCount() == 0) {
c->Message(Chat::Yellow, "No data_buckets found");
return;
}
int _ctr = 0;
// put in window for easier readability in case want command line for something else
std::string window_title = "Data Buckets";
std::string window_text =
"<table>"
"<tr>"
"<td>ID</td>"
"<td>Expires</td>"
"<td>Key</td>"
"<td>Value</td>"
"</tr>";
for (auto row = results.begin(); row != results.end(); ++row) {
auto id = static_cast<uint32>(atoi(row[0]));
std::string key = row[1];
std::string value = row[2];
std::string expires = row[3];
window_text.append(StringFormat(
"<tr>"
"<td>%u</td>"
"<td>%s</td>"
"<td>%s</td>"
"<td>%s</td>"
"</tr>",
id,
expires.c_str(),
key.c_str(),
value.c_str()
));
_ctr++;
std::string del_saylink = StringFormat("#deletebucket %s", key.c_str());
c->Message(Chat::Blue, "%s : %s",
EQEmu::SayLinkEngine::GenerateQuestSaylink(del_saylink, false, "Delete").c_str(), key.c_str(), " Value: ", value.c_str());
}
window_text.append("</table>");
c->SendPopupToClient(window_title.c_str(), window_text.c_str());
std::string response = _ctr > 0 ? StringFormat("Found %i matching data buckets", _ctr).c_str() : "No Databuckets found.";
c->Message(Chat::Yellow, response.c_str());
c->Message(Chat::Yellow, "Usage: #viewbuckets [partial_bucket_name] ['limit' value ] - both optional (default limit 50) ");
}
void command_deletebucket(Client *c, const Seperator *sep)
{
if (sep->arg[1][0] == 0) {
c->Message(Chat::Yellow, "Usage: #deletebucket (key) Type #viewbuckets for a list");
return;
}
if (DataBucket::DeleteData(sep->argplus[1]))
c->Message(Chat::Yellow, "data bucket %s deleted.", sep->argplus[1]);
else
c->Message(Chat::Red, "An error occurred deleting data bucket %s", sep->argplus[1]);
return;
}
void command_who(Client *c, const Seperator *sep)
{
std::string query =

View File

@ -80,6 +80,7 @@ void command_damage(Client *c, const Seperator *sep);
void command_date(Client *c, const Seperator *sep);
void command_dbspawn2(Client *c, const Seperator *sep);
void command_delacct(Client *c, const Seperator *sep);
void command_deletebucket(Client *c, const Seperator *sep);
void command_deletegraveyard(Client *c, const Seperator *sep);
void command_delpetition(Client *c, const Seperator *sep);
void command_depop(Client *c, const Seperator *sep);
@ -327,6 +328,7 @@ void command_untraindisc(Client *c, const Seperator *sep);
void command_untraindiscs(Client *c, const Seperator *sep);
void command_uptime(Client *c, const Seperator *sep);
void command_version(Client *c, const Seperator *sep);
void command_viewbuckets(Client *c, const Seperator *sep);
void command_viewnpctype(Client *c, const Seperator *sep);
void command_viewpetition(Client *c, const Seperator *sep);
void command_wc(Client *c, const Seperator *sep);