diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index 7faa0466a..6ca189093 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -5469,6 +5469,17 @@ ADD PRIMARY KEY (`id`) USING BTREE, ADD INDEX `level_skill_cap`(`skill_id`, `class_id`, `level`, `cap`); )", .content_schema_update = true, + }, + ManifestEntry{ + .version = 9269, + .description = "2024_03_27_account_auto_login_charname.sql", + .check = "SHOW COLUMNS FROM `account` LIKE 'auto_login_charname'", + .condition = "empty", + .match = "", + .sql = R"( +ALTER TABLE `account` +ADD COLUMN `auto_login_charname` varchar(64) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '' AFTER `charname`; +)" } // -- template; copy/paste this when you need to create a new entry // ManifestEntry{ diff --git a/common/repositories/account_repository.h b/common/repositories/account_repository.h index 3689e7f2b..5f2b08581 100644 --- a/common/repositories/account_repository.h +++ b/common/repositories/account_repository.h @@ -89,6 +89,24 @@ public: return results.Success(); } + + static std::string GetAutoLoginCharacterNameByAccountID(Database& db, const uint32 account_id) + { + return AccountRepository::FindOne(db, account_id).auto_login_charname; + } + + static bool SetAutoLoginCharacterNameByAccountID(Database& db, const uint32 account_id, const std::string& character_name) + { + auto e = AccountRepository::FindOne(db, account_id); + + if (!e.id) { + return false; + } + + e.auto_login_charname = character_name; + + return AccountRepository::UpdateOne(db, e); + } }; #endif //EQEMU_ACCOUNT_REPOSITORY_H diff --git a/common/repositories/base/base_account_repository.h b/common/repositories/base/base_account_repository.h index 4e7797b50..33b198f0e 100644 --- a/common/repositories/base/base_account_repository.h +++ b/common/repositories/base/base_account_repository.h @@ -22,6 +22,7 @@ public: int32_t id; std::string name; std::string charname; + std::string auto_login_charname; uint32_t sharedplat; std::string password; int32_t status; @@ -56,6 +57,7 @@ public: "id", "name", "charname", + "auto_login_charname", "sharedplat", "password", "status", @@ -86,6 +88,7 @@ public: "id", "name", "charname", + "auto_login_charname", "sharedplat", "password", "status", @@ -147,30 +150,31 @@ public: { Account e{}; - e.id = 0; - e.name = ""; - e.charname = ""; - e.sharedplat = 0; - e.password = ""; - e.status = 0; - e.ls_id = "eqemu"; - e.lsaccount_id = 0; - e.gmspeed = 0; - e.invulnerable = 0; - e.flymode = 0; - e.ignore_tells = 0; - e.revoked = 0; - e.karma = 0; - e.minilogin_ip = ""; - e.hideme = 0; - e.rulesflag = 0; - e.suspendeduntil = 0; - e.time_creation = 0; - e.ban_reason = ""; - e.suspend_reason = ""; - e.crc_eqgame = ""; - e.crc_skillcaps = ""; - e.crc_basedata = ""; + e.id = 0; + e.name = ""; + e.charname = ""; + e.auto_login_charname = ""; + e.sharedplat = 0; + e.password = ""; + e.status = 0; + e.ls_id = "eqemu"; + e.lsaccount_id = 0; + e.gmspeed = 0; + e.invulnerable = 0; + e.flymode = 0; + e.ignore_tells = 0; + e.revoked = 0; + e.karma = 0; + e.minilogin_ip = ""; + e.hideme = 0; + e.rulesflag = 0; + e.suspendeduntil = 0; + e.time_creation = 0; + e.ban_reason = ""; + e.suspend_reason = ""; + e.crc_eqgame = ""; + e.crc_skillcaps = ""; + e.crc_basedata = ""; return e; } @@ -207,30 +211,31 @@ public: if (results.RowCount() == 1) { Account e{}; - e.id = row[0] ? static_cast(atoi(row[0])) : 0; - e.name = row[1] ? row[1] : ""; - e.charname = row[2] ? row[2] : ""; - e.sharedplat = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; - e.password = row[4] ? row[4] : ""; - e.status = row[5] ? static_cast(atoi(row[5])) : 0; - e.ls_id = row[6] ? row[6] : "eqemu"; - e.lsaccount_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; - e.gmspeed = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; - e.invulnerable = row[9] ? static_cast(atoi(row[9])) : 0; - e.flymode = row[10] ? static_cast(atoi(row[10])) : 0; - e.ignore_tells = row[11] ? static_cast(atoi(row[11])) : 0; - e.revoked = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; - e.karma = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; - e.minilogin_ip = row[14] ? row[14] : ""; - e.hideme = row[15] ? static_cast(atoi(row[15])) : 0; - e.rulesflag = row[16] ? static_cast(strtoul(row[16], nullptr, 10)) : 0; - e.suspendeduntil = strtoll(row[17] ? row[17] : "-1", nullptr, 10); - e.time_creation = row[18] ? static_cast(strtoul(row[18], nullptr, 10)) : 0; - e.ban_reason = row[19] ? row[19] : ""; - e.suspend_reason = row[20] ? row[20] : ""; - e.crc_eqgame = row[21] ? row[21] : ""; - e.crc_skillcaps = row[22] ? row[22] : ""; - e.crc_basedata = row[23] ? row[23] : ""; + e.id = row[0] ? static_cast(atoi(row[0])) : 0; + e.name = row[1] ? row[1] : ""; + e.charname = row[2] ? row[2] : ""; + e.auto_login_charname = row[3] ? row[3] : ""; + e.sharedplat = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.password = row[5] ? row[5] : ""; + e.status = row[6] ? static_cast(atoi(row[6])) : 0; + e.ls_id = row[7] ? row[7] : "eqemu"; + e.lsaccount_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.gmspeed = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.invulnerable = row[10] ? static_cast(atoi(row[10])) : 0; + e.flymode = row[11] ? static_cast(atoi(row[11])) : 0; + e.ignore_tells = row[12] ? static_cast(atoi(row[12])) : 0; + e.revoked = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; + e.karma = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; + e.minilogin_ip = row[15] ? row[15] : ""; + e.hideme = row[16] ? static_cast(atoi(row[16])) : 0; + e.rulesflag = row[17] ? static_cast(strtoul(row[17], nullptr, 10)) : 0; + e.suspendeduntil = strtoll(row[18] ? row[18] : "-1", nullptr, 10); + e.time_creation = row[19] ? static_cast(strtoul(row[19], nullptr, 10)) : 0; + e.ban_reason = row[20] ? row[20] : ""; + e.suspend_reason = row[21] ? row[21] : ""; + e.crc_eqgame = row[22] ? row[22] : ""; + e.crc_skillcaps = row[23] ? row[23] : ""; + e.crc_basedata = row[24] ? row[24] : ""; return e; } @@ -266,27 +271,28 @@ public: v.push_back(columns[1] + " = '" + Strings::Escape(e.name) + "'"); v.push_back(columns[2] + " = '" + Strings::Escape(e.charname) + "'"); - v.push_back(columns[3] + " = " + std::to_string(e.sharedplat)); - v.push_back(columns[4] + " = '" + Strings::Escape(e.password) + "'"); - v.push_back(columns[5] + " = " + std::to_string(e.status)); - v.push_back(columns[6] + " = '" + Strings::Escape(e.ls_id) + "'"); - v.push_back(columns[7] + " = " + std::to_string(e.lsaccount_id)); - v.push_back(columns[8] + " = " + std::to_string(e.gmspeed)); - v.push_back(columns[9] + " = " + std::to_string(e.invulnerable)); - v.push_back(columns[10] + " = " + std::to_string(e.flymode)); - v.push_back(columns[11] + " = " + std::to_string(e.ignore_tells)); - v.push_back(columns[12] + " = " + std::to_string(e.revoked)); - v.push_back(columns[13] + " = " + std::to_string(e.karma)); - v.push_back(columns[14] + " = '" + Strings::Escape(e.minilogin_ip) + "'"); - v.push_back(columns[15] + " = " + std::to_string(e.hideme)); - v.push_back(columns[16] + " = " + std::to_string(e.rulesflag)); - v.push_back(columns[17] + " = FROM_UNIXTIME(" + (e.suspendeduntil > 0 ? std::to_string(e.suspendeduntil) : "null") + ")"); - v.push_back(columns[18] + " = " + std::to_string(e.time_creation)); - v.push_back(columns[19] + " = '" + Strings::Escape(e.ban_reason) + "'"); - v.push_back(columns[20] + " = '" + Strings::Escape(e.suspend_reason) + "'"); - v.push_back(columns[21] + " = '" + Strings::Escape(e.crc_eqgame) + "'"); - v.push_back(columns[22] + " = '" + Strings::Escape(e.crc_skillcaps) + "'"); - v.push_back(columns[23] + " = '" + Strings::Escape(e.crc_basedata) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.auto_login_charname) + "'"); + v.push_back(columns[4] + " = " + std::to_string(e.sharedplat)); + v.push_back(columns[5] + " = '" + Strings::Escape(e.password) + "'"); + v.push_back(columns[6] + " = " + std::to_string(e.status)); + v.push_back(columns[7] + " = '" + Strings::Escape(e.ls_id) + "'"); + v.push_back(columns[8] + " = " + std::to_string(e.lsaccount_id)); + v.push_back(columns[9] + " = " + std::to_string(e.gmspeed)); + v.push_back(columns[10] + " = " + std::to_string(e.invulnerable)); + v.push_back(columns[11] + " = " + std::to_string(e.flymode)); + v.push_back(columns[12] + " = " + std::to_string(e.ignore_tells)); + v.push_back(columns[13] + " = " + std::to_string(e.revoked)); + v.push_back(columns[14] + " = " + std::to_string(e.karma)); + v.push_back(columns[15] + " = '" + Strings::Escape(e.minilogin_ip) + "'"); + v.push_back(columns[16] + " = " + std::to_string(e.hideme)); + v.push_back(columns[17] + " = " + std::to_string(e.rulesflag)); + v.push_back(columns[18] + " = FROM_UNIXTIME(" + (e.suspendeduntil > 0 ? std::to_string(e.suspendeduntil) : "null") + ")"); + v.push_back(columns[19] + " = " + std::to_string(e.time_creation)); + v.push_back(columns[20] + " = '" + Strings::Escape(e.ban_reason) + "'"); + v.push_back(columns[21] + " = '" + Strings::Escape(e.suspend_reason) + "'"); + v.push_back(columns[22] + " = '" + Strings::Escape(e.crc_eqgame) + "'"); + v.push_back(columns[23] + " = '" + Strings::Escape(e.crc_skillcaps) + "'"); + v.push_back(columns[24] + " = '" + Strings::Escape(e.crc_basedata) + "'"); auto results = db.QueryDatabase( fmt::format( @@ -311,6 +317,7 @@ public: v.push_back(std::to_string(e.id)); v.push_back("'" + Strings::Escape(e.name) + "'"); v.push_back("'" + Strings::Escape(e.charname) + "'"); + v.push_back("'" + Strings::Escape(e.auto_login_charname) + "'"); v.push_back(std::to_string(e.sharedplat)); v.push_back("'" + Strings::Escape(e.password) + "'"); v.push_back(std::to_string(e.status)); @@ -364,6 +371,7 @@ public: v.push_back(std::to_string(e.id)); v.push_back("'" + Strings::Escape(e.name) + "'"); v.push_back("'" + Strings::Escape(e.charname) + "'"); + v.push_back("'" + Strings::Escape(e.auto_login_charname) + "'"); v.push_back(std::to_string(e.sharedplat)); v.push_back("'" + Strings::Escape(e.password) + "'"); v.push_back(std::to_string(e.status)); @@ -418,30 +426,31 @@ public: for (auto row = results.begin(); row != results.end(); ++row) { Account e{}; - e.id = row[0] ? static_cast(atoi(row[0])) : 0; - e.name = row[1] ? row[1] : ""; - e.charname = row[2] ? row[2] : ""; - e.sharedplat = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; - e.password = row[4] ? row[4] : ""; - e.status = row[5] ? static_cast(atoi(row[5])) : 0; - e.ls_id = row[6] ? row[6] : "eqemu"; - e.lsaccount_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; - e.gmspeed = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; - e.invulnerable = row[9] ? static_cast(atoi(row[9])) : 0; - e.flymode = row[10] ? static_cast(atoi(row[10])) : 0; - e.ignore_tells = row[11] ? static_cast(atoi(row[11])) : 0; - e.revoked = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; - e.karma = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; - e.minilogin_ip = row[14] ? row[14] : ""; - e.hideme = row[15] ? static_cast(atoi(row[15])) : 0; - e.rulesflag = row[16] ? static_cast(strtoul(row[16], nullptr, 10)) : 0; - e.suspendeduntil = strtoll(row[17] ? row[17] : "-1", nullptr, 10); - e.time_creation = row[18] ? static_cast(strtoul(row[18], nullptr, 10)) : 0; - e.ban_reason = row[19] ? row[19] : ""; - e.suspend_reason = row[20] ? row[20] : ""; - e.crc_eqgame = row[21] ? row[21] : ""; - e.crc_skillcaps = row[22] ? row[22] : ""; - e.crc_basedata = row[23] ? row[23] : ""; + e.id = row[0] ? static_cast(atoi(row[0])) : 0; + e.name = row[1] ? row[1] : ""; + e.charname = row[2] ? row[2] : ""; + e.auto_login_charname = row[3] ? row[3] : ""; + e.sharedplat = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.password = row[5] ? row[5] : ""; + e.status = row[6] ? static_cast(atoi(row[6])) : 0; + e.ls_id = row[7] ? row[7] : "eqemu"; + e.lsaccount_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.gmspeed = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.invulnerable = row[10] ? static_cast(atoi(row[10])) : 0; + e.flymode = row[11] ? static_cast(atoi(row[11])) : 0; + e.ignore_tells = row[12] ? static_cast(atoi(row[12])) : 0; + e.revoked = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; + e.karma = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; + e.minilogin_ip = row[15] ? row[15] : ""; + e.hideme = row[16] ? static_cast(atoi(row[16])) : 0; + e.rulesflag = row[17] ? static_cast(strtoul(row[17], nullptr, 10)) : 0; + e.suspendeduntil = strtoll(row[18] ? row[18] : "-1", nullptr, 10); + e.time_creation = row[19] ? static_cast(strtoul(row[19], nullptr, 10)) : 0; + e.ban_reason = row[20] ? row[20] : ""; + e.suspend_reason = row[21] ? row[21] : ""; + e.crc_eqgame = row[22] ? row[22] : ""; + e.crc_skillcaps = row[23] ? row[23] : ""; + e.crc_basedata = row[24] ? row[24] : ""; all_entries.push_back(e); } @@ -466,30 +475,31 @@ public: for (auto row = results.begin(); row != results.end(); ++row) { Account e{}; - e.id = row[0] ? static_cast(atoi(row[0])) : 0; - e.name = row[1] ? row[1] : ""; - e.charname = row[2] ? row[2] : ""; - e.sharedplat = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; - e.password = row[4] ? row[4] : ""; - e.status = row[5] ? static_cast(atoi(row[5])) : 0; - e.ls_id = row[6] ? row[6] : "eqemu"; - e.lsaccount_id = row[7] ? static_cast(strtoul(row[7], nullptr, 10)) : 0; - e.gmspeed = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; - e.invulnerable = row[9] ? static_cast(atoi(row[9])) : 0; - e.flymode = row[10] ? static_cast(atoi(row[10])) : 0; - e.ignore_tells = row[11] ? static_cast(atoi(row[11])) : 0; - e.revoked = row[12] ? static_cast(strtoul(row[12], nullptr, 10)) : 0; - e.karma = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; - e.minilogin_ip = row[14] ? row[14] : ""; - e.hideme = row[15] ? static_cast(atoi(row[15])) : 0; - e.rulesflag = row[16] ? static_cast(strtoul(row[16], nullptr, 10)) : 0; - e.suspendeduntil = strtoll(row[17] ? row[17] : "-1", nullptr, 10); - e.time_creation = row[18] ? static_cast(strtoul(row[18], nullptr, 10)) : 0; - e.ban_reason = row[19] ? row[19] : ""; - e.suspend_reason = row[20] ? row[20] : ""; - e.crc_eqgame = row[21] ? row[21] : ""; - e.crc_skillcaps = row[22] ? row[22] : ""; - e.crc_basedata = row[23] ? row[23] : ""; + e.id = row[0] ? static_cast(atoi(row[0])) : 0; + e.name = row[1] ? row[1] : ""; + e.charname = row[2] ? row[2] : ""; + e.auto_login_charname = row[3] ? row[3] : ""; + e.sharedplat = row[4] ? static_cast(strtoul(row[4], nullptr, 10)) : 0; + e.password = row[5] ? row[5] : ""; + e.status = row[6] ? static_cast(atoi(row[6])) : 0; + e.ls_id = row[7] ? row[7] : "eqemu"; + e.lsaccount_id = row[8] ? static_cast(strtoul(row[8], nullptr, 10)) : 0; + e.gmspeed = row[9] ? static_cast(strtoul(row[9], nullptr, 10)) : 0; + e.invulnerable = row[10] ? static_cast(atoi(row[10])) : 0; + e.flymode = row[11] ? static_cast(atoi(row[11])) : 0; + e.ignore_tells = row[12] ? static_cast(atoi(row[12])) : 0; + e.revoked = row[13] ? static_cast(strtoul(row[13], nullptr, 10)) : 0; + e.karma = row[14] ? static_cast(strtoul(row[14], nullptr, 10)) : 0; + e.minilogin_ip = row[15] ? row[15] : ""; + e.hideme = row[16] ? static_cast(atoi(row[16])) : 0; + e.rulesflag = row[17] ? static_cast(strtoul(row[17], nullptr, 10)) : 0; + e.suspendeduntil = strtoll(row[18] ? row[18] : "-1", nullptr, 10); + e.time_creation = row[19] ? static_cast(strtoul(row[19], nullptr, 10)) : 0; + e.ban_reason = row[20] ? row[20] : ""; + e.suspend_reason = row[21] ? row[21] : ""; + e.crc_eqgame = row[22] ? row[22] : ""; + e.crc_skillcaps = row[23] ? row[23] : ""; + e.crc_basedata = row[24] ? row[24] : ""; all_entries.push_back(e); } @@ -567,6 +577,7 @@ public: v.push_back(std::to_string(e.id)); v.push_back("'" + Strings::Escape(e.name) + "'"); v.push_back("'" + Strings::Escape(e.charname) + "'"); + v.push_back("'" + Strings::Escape(e.auto_login_charname) + "'"); v.push_back(std::to_string(e.sharedplat)); v.push_back("'" + Strings::Escape(e.password) + "'"); v.push_back(std::to_string(e.status)); @@ -613,6 +624,7 @@ public: v.push_back(std::to_string(e.id)); v.push_back("'" + Strings::Escape(e.name) + "'"); v.push_back("'" + Strings::Escape(e.charname) + "'"); + v.push_back("'" + Strings::Escape(e.auto_login_charname) + "'"); v.push_back(std::to_string(e.sharedplat)); v.push_back("'" + Strings::Escape(e.password) + "'"); v.push_back(std::to_string(e.status)); diff --git a/common/repositories/command_subsettings_repository.h b/common/repositories/command_subsettings_repository.h index 1eece3df4..45e34cfe2 100644 --- a/common/repositories/command_subsettings_repository.h +++ b/common/repositories/command_subsettings_repository.h @@ -70,6 +70,7 @@ public: {.parent_command = "set", .sub_command = "alternate_currency", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setaltcurrency"}, {.parent_command = "set", .sub_command = "animation", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setanim"}, {.parent_command = "set", .sub_command = "anon", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setanon"}, + {.parent_command = "set", .sub_command = "auto_login", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "setautologin"}, {.parent_command = "set", .sub_command = "bind", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "bind"}, {.parent_command = "set", .sub_command = "checksum", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "updatechecksum"}, {.parent_command = "set", .sub_command = "class_permanent", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "permaclass"}, @@ -122,6 +123,7 @@ public: {.parent_command = "set", .sub_command = "zone", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "zclip|zcolor|zheader|zonelock|zsafecoords|zsky|zunderworld"}, {.parent_command = "show", .sub_command = "aas", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showaas"}, {.parent_command = "show", .sub_command = "aa_points", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showaapoints|showaapts"}, + {.parent_command = "show", .sub_command = "auto_login", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showautologin"}, {.parent_command = "show", .sub_command = "aggro", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "aggro"}, {.parent_command = "show", .sub_command = "buffs", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "showbuffs"}, {.parent_command = "show", .sub_command = "buried_corpse_count", .access_level = AccountStatus::QuestTroupe, .top_level_aliases = "getplayerburiedcorpsecount"}, diff --git a/common/ruletypes.h b/common/ruletypes.h index f506a8b64..2eb1821b2 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -330,6 +330,7 @@ RULE_BOOL(World, UseOldShadowKnightClassExport, true, "Disable to have Shadowkni RULE_STRING(World, IPExemptionZones, "", "Comma-delimited list of zones to exclude from IP-limit checks. Empty string to disable.") RULE_STRING(World, MOTD, "", "Server MOTD sent on login, change from empty to have this be used instead of variables table 'motd' value") RULE_STRING(World, Rules, "", "Server Rules, change from empty to have this be used instead of variables table 'rules' value, lines are pipe (|) separated, example: A|B|C") +RULE_BOOL(World, EnableAutoLogin, false, "Enables or disables auto login of characters, allowing people to log characters in directly from loginserver to ingame") RULE_CATEGORY_END() RULE_CATEGORY(Zone) diff --git a/common/version.h b/common/version.h index 102887b44..3b68eacdd 100644 --- a/common/version.h +++ b/common/version.h @@ -42,7 +42,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9268 +#define CURRENT_BINARY_DATABASE_VERSION 9269 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9043 #endif diff --git a/world/client.cpp b/world/client.cpp index bbafcface..84cc158da 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -194,14 +194,20 @@ bool Client::CanTradeFVNoDropItem() void Client::SendEnterWorld(std::string name) { std::string live_name {}; + if (is_player_zoning) { live_name = database.GetLiveChar(GetAccountID()); - if(database.GetAccountIDByChar(live_name) != GetAccountID()) { + if (database.GetAccountIDByChar(live_name) != GetAccountID()) { eqs->Close(); return; - } else { - LogInfo("Telling client to continue session"); } + + LogInfo("Zoning with live_name [{}] account_id [{}]", live_name, GetAccountID()); + } + + if (RuleB(World, EnableAutoLogin)) { + live_name = AccountRepository::GetAutoLoginCharacterNameByAccountID(database, GetAccountID()); + LogInfo("Attempting to auto login with live_name [{}] account_id [{}]", live_name, GetAccountID()); } auto outapp = new EQApplicationPacket(OP_EnterWorld, live_name.length() + 1); diff --git a/zone/client.h b/zone/client.h index cb122084b..b16e5d55e 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1130,6 +1130,9 @@ public: const bool GetGMInvul() const { return gminvul; } bool CanUseReport; + const std::string GetAutoLoginCharacterName(); + bool SetAutoLoginCharacterName(const std::string& character_name); + //This is used to later set the buff duration of the spell, in slot to duration. //Doesn't appear to work directly after the client recieves an action packet. void SendBuffDurationPacket(Buffs_Struct &buff, int slot); diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 61e5b7293..1a5ad027d 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -5855,6 +5855,16 @@ uint16 Perl__get_race_bitmask(uint16 race_id) return GetPlayerRaceBit(race_id); } +std::string Perl__GetAutoLoginCharacterNameByAccountID(uint32 account_id) +{ + return quest_manager.GetAutoLoginCharacterNameByAccountID(account_id); +} + +bool Perl__SetAutoLoginCharacterNameByAccountID(uint32 account_id, std::string character_name) +{ + return quest_manager.SetAutoLoginCharacterNameByAccountID(account_id, character_name); +} + void perl_register_quest() { perl::interpreter perl(PERL_GET_THX); @@ -5885,6 +5895,7 @@ void perl_register_quest() package.add("FlagInstanceByGroupLeader", &Perl__FlagInstanceByGroupLeader); package.add("FlagInstanceByRaidLeader", &Perl__FlagInstanceByRaidLeader); package.add("FlyMode", &Perl__FlyMode); + package.add("GetAutoLoginCharacterNameByAccountID", &Perl__GetAutoLoginCharacterNameByAccountID); package.add("GetBotClassByID", &Perl__GetBotClassByID); package.add("GetBotGenderByID", &Perl__GetBotGenderByID); package.add("GetBotIDsByCharacterID", (perl::array(*)(uint32))&Perl__GetBotIDsByCharacterID); @@ -6159,6 +6170,7 @@ void perl_register_quest() package.add("RemoveFromInstanceByCharID", &Perl__RemoveFromInstanceByCharID); package.add("CheckInstanceByCharID", &Perl__CheckInstanceByCharID); package.add("SendMail", &Perl__SendMail); + package.add("SetAutoLoginCharacterNameByAccountID", &Perl__SetAutoLoginCharacterNameByAccountID); package.add("SetRunning", &Perl__SetRunning); package.add("activespeakactivity", &Perl__activespeakactivity); package.add("activespeaktask", &Perl__activespeaktask); diff --git a/zone/gm_commands/set.cpp b/zone/gm_commands/set.cpp index 0f70d4061..654cab281 100644 --- a/zone/gm_commands/set.cpp +++ b/zone/gm_commands/set.cpp @@ -5,6 +5,7 @@ #include "set/alternate_currency.cpp" #include "set/animation.cpp" #include "set/anon.cpp" +#include "set/auto_login.cpp" #include "set/bind_point.cpp" #include "set/checksum.cpp" #include "set/class_permanent.cpp" @@ -71,6 +72,7 @@ void command_set(Client *c, const Seperator *sep) Cmd{.cmd = "alternate_currency", .u = "alternate_currency [Currency ID] [Amount]", .fn = SetAlternateCurrency, .a = {"#setaltcurrency"}}, Cmd{.cmd = "animation", .u = "animation [Animation ID]", .fn = SetAnimation, .a = {"#setanim"}}, Cmd{.cmd = "anon", .u = "anon [Character ID] [Anonymous Flag] or #set anon [Anonymous Flag]", .fn = SetAnon, .a = {"#setanon"}}, + Cmd{.cmd = "auto_login", .u = "auto_login [0|1]", .fn = SetAutoLogin, .a = {"#setautologin"}}, Cmd{.cmd = "bind_point", .u = "bind_point", .fn = SetBindPoint, .a = {"#setbind"}}, Cmd{.cmd = "checksum", .u = "checksum", .fn = SetChecksum, .a = {"#updatechecksum"}}, Cmd{.cmd = "class_permanent", .u = "class_permanent [Class ID]", .fn = SetClassPermanent, .a = {"#permaclass"}}, diff --git a/zone/gm_commands/set/auto_login.cpp b/zone/gm_commands/set/auto_login.cpp new file mode 100755 index 000000000..4cf219fe8 --- /dev/null +++ b/zone/gm_commands/set/auto_login.cpp @@ -0,0 +1,54 @@ +#include "../../client.h" +#include "../../groups.h" +#include "../../raids.h" +#include "../../raids.h" +#include "../../common/repositories/account_repository.h" + +void SetAutoLogin(Client* c, const Seperator* sep) +{ + if (!RuleB(World, EnableAutoLogin)) { + c->Message(Chat::White, "Auto login is disabled."); + return; + } + + const uint16 arguments = sep->argnum; + if (arguments < 2 || !sep->IsNumber(2)) { + c->Message(Chat::White, "Usage: #set auto_login [0|1]"); + c->Message(Chat::White, "0 = Disable auto login for your account"); + c->Message(Chat::White, "1 = Set auto login character to your current character"); + return; + } + + Client* t = c; + if (c->GetGM() && c->GetTarget() && c->GetTarget()->IsClient()) { + t = c->GetTarget()->CastToClient(); + } + + auto e = AccountRepository::FindOne(database, t->AccountID()); + + if (!e.id) { + c->Message( + Chat::White, + fmt::format( + "Failed to find an account entry for {}.", + c->GetTargetDescription(t) + ).c_str() + ); + return; + } + + const bool set_login = Strings::ToBool(sep->arg[2]); + + e.auto_login_charname = set_login ? t->GetCleanName() : std::string(); + + AccountRepository::UpdateOne(database, e); + + c->Message( + Chat::White, + fmt::format( + "Auto login character has been set to '{}' for {}.", + e.auto_login_charname, + c->GetTargetDescription(t) + ).c_str() + ); +} diff --git a/zone/gm_commands/show.cpp b/zone/gm_commands/show.cpp index 5676be69b..342eaae46 100755 --- a/zone/gm_commands/show.cpp +++ b/zone/gm_commands/show.cpp @@ -2,6 +2,7 @@ #include "show/aas.cpp" #include "show/aa_points.cpp" #include "show/aggro.cpp" +#include "show/auto_login.cpp" #include "show/buffs.cpp" #include "show/buried_corpse_count.cpp" #include "show/client_version_summary.cpp" @@ -62,6 +63,7 @@ void command_show(Client *c, const Seperator *sep) Cmd{.cmd = "aas", .u = "aas", .fn = ShowAAs, .a = {"#showaas"}}, Cmd{.cmd = "aa_points", .u = "aa_points", .fn = ShowAAPoints, .a = {"#showaapoints", "#showaapts"}}, Cmd{.cmd = "aggro", .u = "aggro [Distance] [-v] (-v is verbose Faction Information)", .fn = ShowAggro, .a = {"#aggro"}}, + Cmd{.cmd = "auto_login", .u = "auto_login", .fn = ShowAutoLogin, .a = {"#showautologin"}}, Cmd{.cmd = "buffs", .u = "buffs", .fn = ShowBuffs, .a = {"#showbuffs"}}, Cmd{.cmd = "buried_corpse_count", .u = "buried_corpse_count", .fn = ShowBuriedCorpseCount, .a = {"#getplayerburiedcorpsecount"}}, Cmd{.cmd = "client_version_summary", .u = "client_version_summary", .fn = ShowClientVersionSummary, .a = {"#cvs"}}, diff --git a/zone/gm_commands/show/auto_login.cpp b/zone/gm_commands/show/auto_login.cpp new file mode 100644 index 000000000..3a39230a5 --- /dev/null +++ b/zone/gm_commands/show/auto_login.cpp @@ -0,0 +1,37 @@ +#include "../../client.h" +#include "../../common/repositories/account_repository.h" + +void ShowAutoLogin(Client* c, const Seperator* sep) +{ + if (!RuleB(World, EnableAutoLogin)) { + c->Message(Chat::White, "Auto login is disabled."); + return; + } + + Client* t = c; + if (c->GetGM() && c->GetTarget() && c->GetTarget()->IsClient()) { + t = c->GetTarget()->CastToClient(); + } + + const auto& e = AccountRepository::FindOne(database, t->AccountID()); + + if (!e.id) { + c->Message( + Chat::White, + fmt::format( + "Failed to find an account entry for {}.", + c->GetTargetDescription(t) + ).c_str() + ); + return; + } + + c->Message( + Chat::White, + fmt::format( + "Auto login character for {} is set to '{}'.", + c->GetTargetDescription(t), + e.auto_login_charname + ).c_str() + ); +} diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index a4268f44c..b12b04456 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -3345,6 +3345,24 @@ luabind::object Lua_Client::GetRaidOrGroupOrSelf(lua_State* L, bool clients_only return t; } +std::string Lua_Client::GetAutoLoginCharacterName() +{ + Lua_Safe_Call_String(); + return quest_manager.GetAutoLoginCharacterNameByAccountID(self->AccountID()); +} + +bool Lua_Client::SetAutoLoginCharacterName() +{ + Lua_Safe_Call_Bool(); + return quest_manager.SetAutoLoginCharacterNameByAccountID(self->AccountID(), self->GetCleanName()); +} + +bool Lua_Client::SetAutoLoginCharacterName(std::string character_name) +{ + Lua_Safe_Call_Bool(); + return quest_manager.SetAutoLoginCharacterNameByAccountID(self->AccountID(), character_name); +} + luabind::scope lua_register_client() { return luabind::class_("Client") .def(luabind::constructor<>()) @@ -3481,6 +3499,7 @@ luabind::scope lua_register_client() { .def("GetAnon", (int(Lua_Client::*)(void))&Lua_Client::GetAnon) .def("GetAugmentIDAt", (int(Lua_Client::*)(int,int))&Lua_Client::GetAugmentIDAt) .def("GetAugmentIDsBySlotID", (luabind::object(Lua_Client::*)(lua_State* L,int16))&Lua_Client::GetAugmentIDsBySlotID) + .def("GetAutoLoginCharacterName", (std::string(Lua_Client::*)(void))&Lua_Client::GetAutoLoginCharacterName) .def("GetBaseAGI", (int(Lua_Client::*)(void))&Lua_Client::GetBaseAGI) .def("GetBaseCHA", (int(Lua_Client::*)(void))&Lua_Client::GetBaseCHA) .def("GetBaseDEX", (int(Lua_Client::*)(void))&Lua_Client::GetBaseDEX) @@ -3774,6 +3793,8 @@ luabind::scope lua_register_client() { .def("SetAccountFlag", (void(Lua_Client::*)(const std::string&,const std::string&))&Lua_Client::SetAccountFlag) .def("SetAlternateCurrencyValue", (void(Lua_Client::*)(uint32,uint32))&Lua_Client::SetAlternateCurrencyValue) .def("SetAnon", (void(Lua_Client::*)(uint8))&Lua_Client::SetAnon) + .def("SetAutoLoginCharacterName", (bool(Lua_Client::*)(void))&Lua_Client::SetAutoLoginCharacterName) + .def("SetAutoLoginCharacterName", (bool(Lua_Client::*)(std::string))&Lua_Client::SetAutoLoginCharacterName) .def("SetBaseClass", (void(Lua_Client::*)(int))&Lua_Client::SetBaseClass) .def("SetBaseGender", (void(Lua_Client::*)(int))&Lua_Client::SetBaseGender) .def("SetBaseRace", (void(Lua_Client::*)(int))&Lua_Client::SetBaseRace) diff --git a/zone/lua_client.h b/zone/lua_client.h index 89d4be016..1e9ba7844 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -499,6 +499,9 @@ public: bool IsInAGuild(); luabind::object GetRaidOrGroupOrSelf(lua_State* L); luabind::object GetRaidOrGroupOrSelf(lua_State* L, bool clients_only); + std::string GetAutoLoginCharacterName(); + bool SetAutoLoginCharacterName(); + bool SetAutoLoginCharacterName(std::string character_name); void ApplySpell(int spell_id); void ApplySpell(int spell_id, int duration); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 75534c696..09ae74b43 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -5488,6 +5488,14 @@ uint16 lua_get_race_bitmask(uint16 race_id) { return GetPlayerRaceBit(race_id); } +std::string lua_get_auto_login_character_name_by_account_id(uint32 account_id) { + return quest_manager.GetAutoLoginCharacterNameByAccountID(account_id); +} + +bool lua_set_auto_login_character_name_by_account_id(uint32 account_id, std::string character_name) { + return quest_manager.SetAutoLoginCharacterNameByAccountID(account_id, character_name); +} + #define LuaCreateNPCParse(name, c_type, default_value) do { \ cur = table[#name]; \ if(luabind::type(cur) != LUA_TNIL) { \ @@ -6287,6 +6295,8 @@ luabind::scope lua_register_general() { luabind::def("get_class_bitmask", &lua_get_class_bitmask), luabind::def("get_deity_bitmask", &lua_get_deity_bitmask), luabind::def("get_race_bitmask", &lua_get_race_bitmask), + luabind::def("get_auto_login_character_name_by_account_id", &lua_get_auto_login_character_name_by_account_id), + luabind::def("set_auto_login_character_name_by_account_id", &lua_set_auto_login_character_name_by_account_id), /* Cross Zone */ diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index f98655a29..5267292ee 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -3148,6 +3148,21 @@ perl::array Perl_Client_GetRaidOrGroupOrSelf(Client* self, bool clients_only) return result; } +std::string Perl_Client_GetAutoLoginCharacterName(Client* self) +{ + return quest_manager.GetAutoLoginCharacterNameByAccountID(self->AccountID()); +} + +bool Perl_Client_SetAutoLoginCharacterName(Client* self) +{ + return quest_manager.SetAutoLoginCharacterNameByAccountID(self->AccountID(), self->GetCleanName()); +} + +bool Perl_Client_SetAutoLoginCharacterName(Client* self, std::string character_name) +{ + return quest_manager.SetAutoLoginCharacterNameByAccountID(self->AccountID(), character_name); +} + void perl_register_client() { perl::interpreter perl(PERL_GET_THX); @@ -3280,6 +3295,7 @@ void perl_register_client() package.add("GetAugmentAt", &Perl_Client_GetAugmentAt); package.add("GetAugmentIDAt", &Perl_Client_GetAugmentIDAt); package.add("GetAugmentIDsBySlotID", &Perl_Client_GetAugmentIDsBySlotID); + package.add("GetAutoLoginCharacterName", &Perl_Client_GetAutoLoginCharacterName); package.add("GetBaseAGI", &Perl_Client_GetBaseAGI); package.add("GetBaseCHA", &Perl_Client_GetBaseCHA); package.add("GetBaseDEX", &Perl_Client_GetBaseDEX); @@ -3572,6 +3588,8 @@ void perl_register_client() package.add("SetAccountFlag", &Perl_Client_SetAccountFlag); package.add("SetAlternateCurrencyValue", &Perl_Client_SetAlternateCurrencyValue); package.add("SetAnon", &Perl_Client_SetAnon); + package.add("SetAutoLoginCharacterName", (bool(*)(Client*))&Perl_Client_SetAutoLoginCharacterName); + package.add("SetAutoLoginCharacterName", (bool(*)(Client*, std::string))&Perl_Client_SetAutoLoginCharacterName); package.add("SetBaseClass", &Perl_Client_SetBaseClass); package.add("SetBaseGender", &Perl_Client_SetBaseGender); package.add("SetBaseRace", &Perl_Client_SetBaseRace); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index cb144b367..bbd408e1c 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -39,6 +39,7 @@ #include "zonedb.h" #include "dialogue_window.h" +#include "../common/repositories/account_repository.h" #include "../common/repositories/tradeskill_recipe_repository.h" #include "../common/repositories/instance_list_repository.h" #include "../common/repositories/grid_entries_repository.h" @@ -4893,3 +4894,13 @@ void QuestManager::SendPlayerHandinEvent() { RecordPlayerEventLogWithClient(initiator, PlayerEvent::NPC_HANDIN, e); } } + +std::string QuestManager::GetAutoLoginCharacterNameByAccountID(uint32 account_id) +{ + return AccountRepository::GetAutoLoginCharacterNameByAccountID(database, account_id); +} + +bool QuestManager::SetAutoLoginCharacterNameByAccountID(uint32 account_id, const std::string& character_name) +{ + return AccountRepository::SetAutoLoginCharacterNameByAccountID(database, account_id, character_name); +} diff --git a/zone/questmgr.h b/zone/questmgr.h index c44a50e06..f230ef2c7 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -353,6 +353,8 @@ public: void SendChannelMessage(uint8 channel_number, uint32 guild_id, uint8 language_id, uint8 language_skill, const char* message); void SendChannelMessage(Client* from, uint8 channel_number, uint32 guild_id, uint8 language_id, uint8 language_skill, const char* message); void SendChannelMessage(Client* from, const char* to, uint8 channel_number, uint32 guild_id, uint8 language_id, uint8 language_skill, const char* message); + std::string GetAutoLoginCharacterNameByAccountID(uint32 account_id); + bool SetAutoLoginCharacterNameByAccountID(uint32 account_id, const std::string& character_name); Bot *GetBot() const; Client *GetInitiator() const;