From cece66adc6c8a730b9cc85685106f2439f889abf Mon Sep 17 00:00:00 2001 From: Kinglykrab <89047260+Kinglykrab@users.noreply.github.com> Date: Sun, 21 Nov 2021 19:02:01 -0500 Subject: [PATCH] [Commands] Cleanup #instance Command. (#1803) * [Commands] Cleanup #instance Command. - Cleanups message and logic. - Cleanup ListAllInstances() method. - Fix day calculation in ConvertSecondsToTime(). * Cleanup. * Add return. --- common/string_util.cpp | 4 +- zone/gm_commands/instance.cpp | 408 +++++++++++++++++++++++----------- zone/zonedb.cpp | 146 ++++++++++-- zone/zonedb.h | 2 +- 4 files changed, 406 insertions(+), 154 deletions(-) diff --git a/common/string_util.cpp b/common/string_util.cpp index d8f5cab9b..4b53d32dc 100644 --- a/common/string_util.cpp +++ b/common/string_util.cpp @@ -1041,8 +1041,8 @@ std::string ConvertSecondsToTime(int duration, bool is_milliseconds) duration ); - int days = int(timer_length / 86400000); - timer_length %= 86400000; + int days = int(timer_length / 86400); + timer_length %= 86400; int hours = int(timer_length / 3600); timer_length %= 3600; int minutes = int(timer_length / 60); diff --git a/zone/gm_commands/instance.cpp b/zone/gm_commands/instance.cpp index 27c1171d7..f9bd357e3 100755 --- a/zone/gm_commands/instance.cpp +++ b/zone/gm_commands/instance.cpp @@ -2,187 +2,327 @@ void command_instance(Client *c, const Seperator *sep) { - if (!c) { + int arguments = sep->argnum; + if (!arguments) { + c->Message( + Chat::White, + "Usage: #instance create [Zone ID|Zone Short Name] [Version] [Duration]" + ); + c->Message( + Chat::White, + "Usage: #instance destroy [Instance ID]" + ); + c->Message( + Chat::White, + "Usage: #instance add [Instance ID] [Name]" + ); + c->Message( + Chat::White, + "Usage: #instance remove [Instance ID] [Name]" + ); + c->Message( + Chat::White, + "Usage: #instance list [Name]" + ); return; } - //options: - //help - //create [zone_id] [version] - //destroy [instance_id] - //add [instance_id] [player_name] - //remove [instance_id] [player_name] - //list [player_name] + Client* target = c; + if (c->GetTarget() && c->GetTarget()->IsClient()) { + target = c->GetTarget()->CastToClient(); + } - if (strcasecmp(sep->arg[1], "help") == 0) { - c->Message(Chat::White, "#instance usage:"); + bool is_add = !strcasecmp(sep->arg[1], "add"); + bool is_create = !strcasecmp(sep->arg[1], "create"); + bool is_destroy = !strcasecmp(sep->arg[1], "destroy"); + bool is_help = !strcasecmp(sep->arg[1], "help"); + bool is_list = !strcasecmp(sep->arg[1], "list"); + bool is_remove = !strcasecmp(sep->arg[1], "remove"); + if ( + !is_add && + !is_create && + !is_destroy && + !is_help && + !is_list && + !is_remove + ) { c->Message( - Chat::White, "#instance create zone_id version duration - Creates an instance of version 'version' in the " - "zone with id matching zone_id, will last for duration seconds." - ); - c->Message(Chat::White, "#instance destroy instance_id - Destroys the instance with id matching instance_id."); - c->Message( - Chat::White, "#instance add instance_id player_name - adds the player 'player_name' to the instance " - "with id matching instance_id." + Chat::White, + "Usage: #instance create [Zone ID|Zone Short Name] [Version] [Duration]" ); c->Message( - Chat::White, "#instance remove instance_id player_name - removes the player 'player_name' from the " - "instance with id matching instance_id." + Chat::White, + "Usage: #instance destroy [Instance ID]" + ); + c->Message( + Chat::White, + "Usage: #instance add [Instance ID] [Name]" + ); + c->Message( + Chat::White, + "Usage: #instance remove [Instance ID] [Name]" + ); + c->Message( + Chat::White, + "Usage: #instance list [Name]" ); - c->Message(Chat::White, "#instance list player_name - lists all the instances 'player_name' is apart of."); return; } - else if (strcasecmp(sep->arg[1], "create") == 0) { - if (!sep->IsNumber(3) || !sep->IsNumber(4)) { + + if (is_add) { + if (!sep->IsNumber(2)) { c->Message( Chat::White, - "#instance create zone_id version duration - Creates an instance of version 'version' in the " - "zone with id matching zone_id, will last for duration seconds." + "#instance add [Instance ID] [Name]" ); return; } - const char *zn = nullptr; - uint32 zone_id = 0; - - if (sep->IsNumber(2)) { - zone_id = atoi(sep->arg[2]); - } - else { - zone_id = ZoneID(sep->arg[2]); - } - - uint32 version = atoi(sep->arg[3]); - uint32 duration = atoi(sep->arg[4]); - zn = ZoneName(zone_id); - - if (!zn) { - c->Message(Chat::White, "Zone with id %lu was not found by the server.", (unsigned long) zone_id); + std::string character_name = sep->arg[3]; + uint16 instance_id = static_cast(std::stoul(sep->arg[2])); + uint32 character_id = database.GetCharacterID(character_name.c_str()); + if (instance_id <= 0 || character_id <= 0) { + c->Message(Chat::White, "You must enter a valid Instance ID and player name."); return; } - uint16 id = 0; - if (!database.GetUnusedInstanceID(id)) { + if (!database.CheckInstanceExists(instance_id)) { + c->Message( + Chat::White, + fmt::format( + "Instance ID {} does not exist.", + instance_id + ).c_str() + ); + return; + } + + uint32 zone_id = database.ZoneIDFromInstanceID(instance_id); + uint32 version = database.VersionFromInstanceID(instance_id); + uint32 current_id = database.GetInstanceID(zone_id, character_id, version); + if (!current_id) { + std::string target_string = ( + c == target ? + "yourself" : + fmt::format( + "{} ({})", + character_name, + character_id + ) + ); + + c->Message( + Chat::White, + ( + database.AddClientToInstance(instance_id, character_id) ? + fmt::format( + "Added {} to Instance ID {}.", + target_string, + instance_id + ) : + fmt::format( + "Failed to add {} to Instance ID {}.", + target_string, + instance_id + ) + ).c_str() + ); + } + else { + c->Message( + Chat::White, + fmt::format( + "Client was already saved to Instance ID {}{}.", + current_id, + ( + current_id != instance_id ? + fmt::format( + "which has the same zone and version as Instance ID {}", + instance_id + ) : + "" + ) + ).c_str() + ); + } + } else if (is_create) { + if (!sep->IsNumber(3) || !sep->IsNumber(4)) { + c->Message( + Chat::White, + "Usage: #instance create [Zone ID|Zone Short Name] [Version] [Duration]" + ); + return; + } + + uint32 zone_id = ( + sep->IsNumber(2) ? + std::stoul(sep->arg[2]) : + ZoneID(sep->arg[2]) + ); + uint32 version = std::stoul(sep->arg[3]); + uint32 duration = std::stoul(sep->arg[4]); + std::string zone_short_name = ZoneName(zone_id); + if (zone_short_name.empty()) { + c->Message( + Chat::White, + fmt::format( + "Zone ID {} was not found by the server.", + zone_id + ).c_str() + ); + return; + } + + uint16 instance_id = 0; + if (!database.GetUnusedInstanceID(instance_id)) { c->Message(Chat::White, "Server was unable to find a free instance id."); return; } - if (!database.CreateInstance(id, zone_id, version, duration)) { + if (!database.CreateInstance(instance_id, zone_id, version, duration)) { c->Message(Chat::White, "Server was unable to create a new instance."); return; } - c->Message(Chat::White, "New instance %s was created with id %lu.", zn, (unsigned long) id); - } - else if (strcasecmp(sep->arg[1], "destroy") == 0) { + c->Message( + Chat::White, + fmt::format( + "Instance {} Created | Zone: {} ({}){}", + instance_id, + ZoneLongName(zone_id), + zone_id, + ( + version ? + fmt::format( + " Version: {}", + version + ) : + "" + ) + ).c_str() + ); + + c->Message( + Chat::White, + fmt::format( + "Instance {} Created | Duration: {} ({})", + instance_id, + ConvertSecondsToTime(duration), + duration + ).c_str() + ); + } else if (is_destroy) { if (!sep->IsNumber(2)) { c->Message( Chat::White, - "#instance destroy instance_id - Destroys the instance with id matching instance_id." + "#instance destroy [Instance ID]" ); return; } - uint16 id = atoi(sep->arg[2]); - database.DeleteInstance(id); - c->Message(Chat::White, "Destroyed instance with id %lu.", (unsigned long) id); - } - else if (strcasecmp(sep->arg[1], "add") == 0) { - if (!sep->IsNumber(2)) { - c->Message( - Chat::White, "#instance add instance_id player_name - adds the player 'player_name' to the instance " - "with id matching instance_id." - ); - return; - } - - uint16 id = atoi(sep->arg[2]); - uint32 charid = database.GetCharacterID(sep->arg[3]); - - if (id <= 0 || charid <= 0) { - c->Message(Chat::White, "Must enter a valid instance id and player name."); - return; - } - - if (!database.CheckInstanceExists(id)) { - c->Message(Chat::White, "Instance does not exist."); - return; - } - - uint32 zone_id = database.ZoneIDFromInstanceID(id); - uint32 version = database.VersionFromInstanceID(id); - uint32 cur_id = database.GetInstanceID(zone_id, charid, version); - if (cur_id == 0) { - if (database.AddClientToInstance(id, charid)) { - c->Message(Chat::White, "Added client to instance."); - } - else { - c->Message(Chat::White, "Failed to add client to instance."); - } - } - else { + uint16 instance_id = std::stoul(sep->arg[2]); + if (!database.CheckInstanceExists(instance_id)) { c->Message( Chat::White, - "Client was already saved to %u which has uses the same zone and version as that instance.", - cur_id - ); - } - } - else if (strcasecmp(sep->arg[1], "remove") == 0) { - if (!sep->IsNumber(2)) { - c->Message( - Chat::White, "#instance remove instance_id player_name - removes the player 'player_name' from the " - "instance with id matching instance_id." + fmt::format( + "Instance ID {} does not exist.", + instance_id + ).c_str() ); return; } - uint16 id = atoi(sep->arg[2]); - uint32 charid = database.GetCharacterID(sep->arg[3]); - - if (id <= 0 || charid <= 0) { - c->Message(Chat::White, "Must enter a valid instance id and player name."); - } - - if (database.RemoveClientFromInstance(id, charid)) { - c->Message(Chat::White, "Removed client from instance."); - } - else { - c->Message(Chat::White, "Failed to remove client from instance."); - } - } - else if (strcasecmp(sep->arg[1], "list") == 0) { - uint32 charid = database.GetCharacterID(sep->arg[2]); - if (charid <= 0) { - if (c->GetTarget() == nullptr || (c->GetTarget() && !c->GetTarget()->IsClient())) { - c->Message(Chat::White, "Character not found."); - return; - } - else { - charid = c->GetTarget()->CastToClient()->CharacterID(); - } - } - - database.ListAllInstances(c, charid); - } - else { - c->Message(Chat::White, "Invalid Argument."); - c->Message(Chat::White, "#instance usage:"); + database.DeleteInstance(instance_id); c->Message( - Chat::White, "#instance create zone_id version duration - Creates an instance of version 'version' in the " - "zone with id matching zone_id, will last for duration seconds." + Chat::White, + fmt::format( + "Instance ID {} Deleted.", + instance_id + ).c_str() ); - c->Message(Chat::White, "#instance destroy instance_id - Destroys the instance with id matching instance_id."); + } else if (is_help) { c->Message( - Chat::White, "#instance add instance_id player_name - adds the player 'player_name' to the instance " - "with id matching instance_id." + Chat::White, + "Usage: #instance create [Zone ID|Zone Short Name] [Version] [Duration]" ); c->Message( - Chat::White, "#instance remove instance_id player_name - removes the player 'player_name' from the " - "instance with id matching instance_id." + Chat::White, + "Usage: #instance destroy [Instance ID]" + ); + c->Message( + Chat::White, + "Usage: #instance add [Instance ID] [Name]" + ); + c->Message( + Chat::White, + "Usage: #instance remove [Instance ID] [Name]" + ); + c->Message( + Chat::White, + "Usage: #instance list [Name]" ); - c->Message(Chat::White, "#instance list player_name - lists all the instances 'player_name' is apart of."); return; + } else if (is_list) { + uint32 character_id = database.GetCharacterID(sep->arg[2]); + if (character_id <= 0) { + character_id = target->CharacterID(); + } + + database.ListAllInstances(c, character_id); + } else if (is_remove) { + if (!sep->IsNumber(2)) { + c->Message( + Chat::White, + "#instance remove [Instance ID] [Name]" + ); + return; + } + + std::string character_name = sep->arg[3]; + uint16 instance_id = static_cast(std::stoul(sep->arg[2])); + uint32 character_id = database.GetCharacterID(character_name.c_str()); + if (instance_id <= 0 || character_id <= 0) { + c->Message(Chat::White, "You must enter a valid Instance ID and player name."); + return; + } + + if (!database.CheckInstanceExists(instance_id)) { + c->Message( + Chat::White, + fmt::format( + "Instance ID {} does not exist.", + instance_id + ).c_str() + ); + return; + } + + std::string target_string = ( + c->CharacterID() == character_id ? + "yourself" : + fmt::format( + "{} ({})", + character_name, + character_id + ) + ); + + c->Message( + Chat::White, + ( + database.RemoveClientFromInstance(instance_id, character_id) ? + fmt::format( + "Removed {} from Instance ID {}.", + target_string, + instance_id + ) : + fmt::format( + "Failed to remove {} from Instance ID {}.", + target_string, + instance_id + ) + ).c_str() + ); } } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index f382c300e..c4b6363a0 100755 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3491,28 +3491,140 @@ void ZoneDatabase::UpdateKarma(uint32 acct_id, uint32 amount) QueryDatabase(query); } -void ZoneDatabase::ListAllInstances(Client* client, uint32 charid) +void ZoneDatabase::ListAllInstances(Client* client, uint32 character_id) { - if(!client) + if (!client) { return; + } - std::string query = StringFormat("SELECT instance_list.id, zone, version " - "FROM instance_list JOIN instance_list_player " - "ON instance_list.id = instance_list_player.id " - "WHERE instance_list_player.charid = %lu", - (unsigned long)charid); - auto results = QueryDatabase(query); - if (!results.Success()) - return; + std::string query = fmt::format( + "SELECT instance_list.id, zone, version, start_time, duration, never_expires " + "FROM instance_list JOIN instance_list_player " + "ON instance_list.id = instance_list_player.id " + "WHERE instance_list_player.charid = {}", + character_id + ); + auto results = QueryDatabase(query); + if (!results.Success()) { + return; + } - char name[64]; - database.GetCharName(charid, name); - client->Message(Chat::White, "%s is part of the following instances:", name); + auto character_name = database.GetCharNameByID(character_id); + bool is_same_client = client->CharacterID() == character_id; + if (character_name.empty()) { + client->Message( + Chat::White, + fmt::format( + "Character ID '{}' does not exist.", + character_id + ).c_str() + ); + return; + } - for (auto row = results.begin(); row != results.end(); ++row) { - client->Message(Chat::White, "%s - id: %lu, version: %lu", ZoneName(atoi(row[1])), - (unsigned long)atoi(row[0]), (unsigned long)atoi(row[2])); - } + if (!results.RowCount()) { + client->Message( + Chat::White, + fmt::format( + "{} not in any Instances.", + ( + is_same_client ? + "You are" : + fmt::format( + "{} ({}) is", + character_name, + character_id + ) + ) + ).c_str() + ); + return; + } + + client->Message( + Chat::White, + fmt::format( + "{} in the following Instances.", + ( + is_same_client ? + "You are" : + fmt::format( + "{} ({}) is", + character_name, + character_id + ) + ) + ).c_str() + ); + + uint32 instance_count = 0; + for (auto row : results) { + auto instance_id = std::stoul(row[0]); + auto zone_id = std::stoul(row[1]); + auto version = std::stoul(row[2]); + auto start_time = std::stoul(row[3]); + auto duration = std::stoul(row[4]); + auto never_expires = std::stoi(row[5]) ? true : false; + std::string remaining_time_string = "Never"; + timeval time_value; + gettimeofday(&time_value, nullptr); + auto current_time = time_value.tv_sec; + auto remaining_time = ((start_time + duration) - current_time); + if (!never_expires) { + if (remaining_time > 0) { + remaining_time_string = ConvertSecondsToTime(remaining_time); + } else { + remaining_time_string = "Already Expired"; + } + } + + client->Message( + Chat::White, + fmt::format("Instance {} | Zone: {} ({}){}", + instance_id, + ZoneLongName(zone_id), + zone_id, + ( + version ? + fmt::format( + " Version: {}", + version + ) : + "" + ) + ).c_str() + ); + + client->Message( + Chat::White, + fmt::format( + "Instance {} | Expires: {}", + instance_id, + remaining_time_string, + remaining_time + ).c_str() + ); + + instance_count++; + } + + client->Message( + Chat::White, + fmt::format( + "{} in {} Instance{}.", + ( + is_same_client ? + "You are" : + fmt::format( + "{} ({}) is", + character_name, + character_id + ) + ), + instance_count, + instance_count != 1 ? "s" : "" + ).c_str() + ); } void ZoneDatabase::QGlobalPurge() diff --git a/zone/zonedb.h b/zone/zonedb.h index 2a35d5632..d019d6fc4 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -576,7 +576,7 @@ public: uint8 RaidGroupCount(uint32 raidid, uint32 groupid); /* Instancing */ - void ListAllInstances(Client* c, uint32 charid); + void ListAllInstances(Client* c, uint32 character_id); /* QGlobals */ void QGlobalPurge();