[Bug Fix] Fix Bot/Character ID Overlap in Groups (#4093)

* [Bug Fix] Fix Bot/Character ID Overlap in Groups

- Attempt to fix bot/character ID overlap in groups keeping bots with the same unique identifier as players from not spawning on zone.
- Adds `bot_id` to `group_id` to differentiate bots from characters and hopefully alleviate this issue.

* Update base_group_id_repository.h

* Final push
This commit is contained in:
Alex King
2024-03-23 18:55:03 -04:00
committed by GitHub
parent abdec39cdd
commit 21cec87ac4
19 changed files with 361 additions and 281 deletions
+45 -67
View File
@@ -35,6 +35,8 @@
#include "../common/repositories/character_languages_repository.h"
#include "../common/repositories/character_leadership_abilities_repository.h"
#include "../common/repositories/character_skills_repository.h"
#include "../common/repositories/group_id_repository.h"
#include "../common/repositories/group_leaders_repository.h"
// Disgrace: for windows compile
#ifdef _WINDOWS
@@ -1280,24 +1282,6 @@ void Database::AddReport(std::string who, std::string against, std::string lines
safe_delete_array(escape_str);
}
void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc) {
std::string query;
if (id == 0) {
// removing from group
query = StringFormat("delete from group_id where charid=%i and name='%s' and ismerc=%i",charid, name, ismerc);
auto results = QueryDatabase(query);
if (!results.Success())
LogError("Error deleting character from group id: {}", results.ErrorMessage().c_str());
return;
}
/* Add to the Group */
query = StringFormat("REPLACE INTO `group_id` SET `charid` = %i, `groupid` = %i, `name` = '%s', `ismerc` = '%i'", charid, id, name, ismerc);
QueryDatabase(query);
}
void Database::ClearAllGroups(void)
{
std::string query("DELETE FROM `group_id`");
@@ -1305,71 +1289,65 @@ void Database::ClearAllGroups(void)
return;
}
void Database::ClearGroup(uint32 gid) {
ClearGroupLeader(gid);
void Database::ClearGroup(uint32 group_id) {
ClearGroupLeader(group_id);
if(gid == 0)
{
if (!group_id) {
//clear all groups
ClearAllGroups();
return;
}
//clear a specific group
std::string query = StringFormat("delete from group_id where groupid = %lu", (unsigned long)gid);
QueryDatabase(query);
}
uint32 Database::GetGroupID(const char* name){
std::string query = StringFormat("SELECT groupid from group_id where name='%s'", name);
auto results = QueryDatabase(query);
if (!results.Success()) {
return 0;
}
if (results.RowCount() == 0)
{
// Commenting this out until logging levels can prevent this from going to console
//LogDebug(, "Character not in a group: [{}]", name);
return 0;
}
auto row = results.begin();
return Strings::ToUnsignedInt(row[0]);
}
std::string Database::GetGroupLeaderForLogin(std::string character_name) {
uint32 group_id = 0;
auto query = fmt::format(
"SELECT `groupid` FROM `group_id` WHERE `name` = '{}'",
character_name
GroupIdRepository::DeleteWhere(
*this,
fmt::format(
"`group_id` = {}",
group_id
)
);
auto results = QueryDatabase(query);
}
if (results.Success() && results.RowCount()) {
auto row = results.begin();
group_id = Strings::ToUnsignedInt(row[0]);
uint32 Database::GetGroupID(const std::string& name)
{
const auto& l = GroupIdRepository::GetWhere(
*this,
fmt::format(
"`name` = '{}'",
Strings::Escape(name)
)
);
if (l.empty()) {
return 0;
}
if (!group_id) {
auto e = l.front();
return e.group_id;
}
std::string Database::GetGroupLeaderForLogin(const std::string& character_name)
{
const auto& g = GroupIdRepository::GetWhere(
*this,
fmt::format(
"`name` = '{}'",
Strings::Escape(character_name)
)
);
if (g.empty()) {
return std::string();
}
query = fmt::format(
"SELECT `leadername` FROM `group_leaders` WHERE `gid` = {} LIMIT 1",
group_id
);
results = QueryDatabase(query);
auto group = g.front();
if (results.Success() && results.RowCount()) {
auto row = results.begin();
return row[0];
}
const uint32 group_id = group.group_id;
return std::string();
const auto& e = GroupLeadersRepository::FindOne(*this, group_id);
return e.gid ? e.leadername : std::string();
}
void Database::SetGroupLeaderName(uint32 gid, const char* name) {
+3 -4
View File
@@ -202,16 +202,15 @@ public:
/* Groups */
std::string GetGroupLeaderForLogin(std::string character_name);
std::string GetGroupLeaderForLogin(const std::string& character_name);
char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr);
std::string GetGroupLeaderName(uint32 group_id);
uint32 GetGroupID(const char* name);
uint32 GetGroupID(const std::string& name);
void ClearGroup(uint32 gid = 0);
void ClearGroup(uint32 group_id = 0);
void ClearGroupLeader(uint32 gid = 0);
void SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc = false);
void SetGroupLeaderName(uint32 gid, const char* name);
/* Raids */
@@ -5433,6 +5433,25 @@ ADD PRIMARY KEY (`id`);
ALTER TABLE `rule_values`
MODIFY COLUMN `rule_value` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `rule_name`;
)"
},
ManifestEntry{
.version = 9267,
.description = "2024_02_18_group_id_bot_id.sql",
.check = "SHOW COLUMNS FROM `group_id` LIKE 'bot_id'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `group_id`
CHANGE COLUMN `groupid` `group_id` int(11) UNSIGNED NOT NULL DEFAULT 0 FIRST,
CHANGE COLUMN `charid` `character_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `group_id`,
CHANGE COLUMN `ismerc` `merc_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `name`,
ADD COLUMN `bot_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `character_id`,
MODIFY COLUMN `name` varchar(64) NOT NULL DEFAULT '' AFTER `character_id`,
DROP PRIMARY KEY,
ADD PRIMARY KEY (`group_id`, `character_id`, `bot_id`, `merc_id`) USING BTREE;
ALTER TABLE `group_id`
MODIFY COLUMN `character_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `name`;
)"
}
// -- template; copy/paste this when you need to create a new entry
// ManifestEntry{
+9 -4
View File
@@ -421,20 +421,25 @@ void Database::AssignGroupToInstance(uint32 group_id, uint32 instance_id)
auto zone_id = GetInstanceZoneID(instance_id);
auto version = GetInstanceVersion(instance_id);
auto l = GroupIdRepository::GetWhere(
const auto& l = GroupIdRepository::GetWhere(
*this,
fmt::format(
"groupid = {}",
"`group_id` = {}",
group_id
)
);
if (l.empty()) {
return;
}
for (const auto& e : l) {
if (!GetInstanceID(zone_id, e.charid, version)) {
AddClientToInstance(instance_id, e.charid);
if (!e.character_id) {
continue;
}
if (!GetInstanceID(zone_id, e.character_id, version)) {
AddClientToInstance(instance_id, e.character_id);
}
}
}
@@ -19,34 +19,37 @@
class BaseGroupIdRepository {
public:
struct GroupId {
int32_t groupid;
int32_t charid;
uint32_t group_id;
std::string name;
int8_t ismerc;
uint32_t character_id;
uint32_t bot_id;
uint32_t merc_id;
};
static std::string PrimaryKey()
{
return std::string("groupid");
return std::string("group_id");
}
static std::vector<std::string> Columns()
{
return {
"groupid",
"charid",
"group_id",
"name",
"ismerc",
"character_id",
"bot_id",
"merc_id",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"groupid",
"charid",
"group_id",
"name",
"ismerc",
"character_id",
"bot_id",
"merc_id",
};
}
@@ -87,10 +90,11 @@ public:
{
GroupId e{};
e.groupid = 0;
e.charid = 0;
e.name = "";
e.ismerc = 0;
e.group_id = 0;
e.name = "";
e.character_id = 0;
e.bot_id = 0;
e.merc_id = 0;
return e;
}
@@ -101,7 +105,7 @@ public:
)
{
for (auto &group_id : group_ids) {
if (group_id.groupid == group_id_id) {
if (group_id.group_id == group_id_id) {
return group_id;
}
}
@@ -127,10 +131,11 @@ public:
if (results.RowCount() == 1) {
GroupId e{};
e.groupid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.charid = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.name = row[2] ? row[2] : "";
e.ismerc = row[3] ? static_cast<int8_t>(atoi(row[3])) : 0;
e.group_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.name = row[1] ? row[1] : "";
e.character_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.bot_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.merc_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
return e;
}
@@ -164,10 +169,11 @@ public:
auto columns = Columns();
v.push_back(columns[0] + " = " + std::to_string(e.groupid));
v.push_back(columns[1] + " = " + std::to_string(e.charid));
v.push_back(columns[2] + " = '" + Strings::Escape(e.name) + "'");
v.push_back(columns[3] + " = " + std::to_string(e.ismerc));
v.push_back(columns[0] + " = " + std::to_string(e.group_id));
v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'");
v.push_back(columns[2] + " = " + std::to_string(e.character_id));
v.push_back(columns[3] + " = " + std::to_string(e.bot_id));
v.push_back(columns[4] + " = " + std::to_string(e.merc_id));
auto results = db.QueryDatabase(
fmt::format(
@@ -175,7 +181,7 @@ public:
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.groupid
e.group_id
)
);
@@ -189,10 +195,11 @@ public:
{
std::vector<std::string> v;
v.push_back(std::to_string(e.groupid));
v.push_back(std::to_string(e.charid));
v.push_back(std::to_string(e.group_id));
v.push_back("'" + Strings::Escape(e.name) + "'");
v.push_back(std::to_string(e.ismerc));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.merc_id));
auto results = db.QueryDatabase(
fmt::format(
@@ -203,7 +210,7 @@ public:
);
if (results.Success()) {
e.groupid = results.LastInsertedID();
e.group_id = results.LastInsertedID();
return e;
}
@@ -222,10 +229,11 @@ public:
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.groupid));
v.push_back(std::to_string(e.charid));
v.push_back(std::to_string(e.group_id));
v.push_back("'" + Strings::Escape(e.name) + "'");
v.push_back(std::to_string(e.ismerc));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.merc_id));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -259,10 +267,11 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
GroupId e{};
e.groupid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.charid = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.name = row[2] ? row[2] : "";
e.ismerc = row[3] ? static_cast<int8_t>(atoi(row[3])) : 0;
e.group_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.name = row[1] ? row[1] : "";
e.character_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.bot_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.merc_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
all_entries.push_back(e);
}
@@ -287,10 +296,11 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
GroupId e{};
e.groupid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.charid = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.name = row[2] ? row[2] : "";
e.ismerc = row[3] ? static_cast<int8_t>(atoi(row[3])) : 0;
e.group_id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.name = row[1] ? row[1] : "";
e.character_id = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.bot_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.merc_id = row[4] ? static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) : 0;
all_entries.push_back(e);
}
@@ -365,10 +375,11 @@ public:
{
std::vector<std::string> v;
v.push_back(std::to_string(e.groupid));
v.push_back(std::to_string(e.charid));
v.push_back(std::to_string(e.group_id));
v.push_back("'" + Strings::Escape(e.name) + "'");
v.push_back(std::to_string(e.ismerc));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.merc_id));
auto results = db.QueryDatabase(
fmt::format(
@@ -391,10 +402,11 @@ public:
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.groupid));
v.push_back(std::to_string(e.charid));
v.push_back(std::to_string(e.group_id));
v.push_back("'" + Strings::Escape(e.name) + "'");
v.push_back(std::to_string(e.ismerc));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.merc_id));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -105,7 +105,7 @@ public:
e.gid = 0;
e.leadername = "";
e.marknpc = "";
e.leadershipaa = 0;
e.leadershipaa = "";
e.maintank = "";
e.assist = "";
e.puller = "";
@@ -150,7 +150,7 @@ public:
e.gid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.leadername = row[1] ? row[1] : "";
e.marknpc = row[2] ? row[2] : "";
e.leadershipaa = row[3] ? row[3] : 0;
e.leadershipaa = row[3] ? row[3] : "";
e.maintank = row[4] ? row[4] : "";
e.assist = row[5] ? row[5] : "";
e.puller = row[6] ? row[6] : "";
@@ -302,7 +302,7 @@ public:
e.gid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.leadername = row[1] ? row[1] : "";
e.marknpc = row[2] ? row[2] : "";
e.leadershipaa = row[3] ? row[3] : 0;
e.leadershipaa = row[3] ? row[3] : "";
e.maintank = row[4] ? row[4] : "";
e.assist = row[5] ? row[5] : "";
e.puller = row[6] ? row[6] : "";
@@ -335,7 +335,7 @@ public:
e.gid = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.leadername = row[1] ? row[1] : "";
e.marknpc = row[2] ? row[2] : "";
e.leadershipaa = row[3] ? row[3] : 0;
e.leadershipaa = row[3] ? row[3] : "";
e.maintank = row[4] ? row[4] : "";
e.assist = row[5] ? row[5] : "";
e.puller = row[6] ? row[6] : "";
+1 -1
View File
@@ -60,7 +60,7 @@ SharedTaskRequest SharedTask::GetRequestCharacters(Database &db, uint32_t reques
request.group_type = SharedTaskRequestGroupType::Group;
auto characters = CharacterDataRepository::GetWhere(
db, fmt::format(
"id IN (select charid from group_id where groupid = (select groupid from group_id where charid = {}))",
"id IN (select charid from group_id where group_id = (select group_id from group_id where charid = {}))",
requested_character_id
)
);
+1 -1
View File
@@ -42,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9266
#define CURRENT_BINARY_DATABASE_VERSION 9267
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9043
#endif