From c13ec5a06dfc00d74e3a8f61e50a7c261ebc715f Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Mon, 19 Feb 2024 21:45:18 -0500 Subject: [PATCH] [Repositories] Cleanup and Convert Character Creation to Repositories (#4053) * [Repositories] Cleanup and Convert Character Creation to Repositories # Notes - Converts `Database::GetCharacterID()`, `Database::SaveCharacterCreate()`, and `Client::OPCharCreate` to repositories. - Cleanup a spot we were doing a queries in a loop. * Cleanup * Update database.cpp * Update database.cpp --- common/database.cpp | 507 +++++++++++----------------------- common/database.h | 2 +- common/eq_constants.h | 4 + world/adventure.cpp | 10 +- world/client.cpp | 255 ++++++++--------- zone/expedition.cpp | 6 +- zone/expedition_request.cpp | 2 +- zone/gm_commands/instance.cpp | 4 +- zone/gm_commands/movechar.cpp | 2 +- zone/gm_commands/summon.cpp | 2 +- 10 files changed, 303 insertions(+), 491 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 79fff8128..d80b6d0dc 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -30,6 +30,11 @@ #include #include "../common/repositories/account_repository.h" +#include "../common/repositories/character_bind_repository.h" +#include "../common/repositories/character_data_repository.h" +#include "../common/repositories/character_languages_repository.h" +#include "../common/repositories/character_leadership_abilities_repository.h" +#include "../common/repositories/character_skills_repository.h" // Disgrace: for windows compile #ifdef _WINDOWS @@ -454,363 +459,185 @@ bool Database::DeleteCharacter(char *character_name) bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct *pp) { - std::string query = StringFormat( - "REPLACE INTO `character_data` (" - "id," - "account_id," - "`name`," - "last_name," - "gender," - "race," - "class," - "`level`," - "deity," - "birthday," - "last_login," - "time_played," - "pvp_status," - "level2," - "anon," - "gm," - "intoxication," - "hair_color," - "beard_color," - "eye_color_1," - "eye_color_2," - "hair_style," - "beard," - "ability_time_seconds," - "ability_number," - "ability_time_minutes," - "ability_time_hours," - "title," - "suffix," - "exp," - "points," - "mana," - "cur_hp," - "str," - "sta," - "cha," - "dex," - "`int`," - "agi," - "wis," - "face," - "y," - "x," - "z," - "heading," - "pvp2," - "pvp_type," - "autosplit_enabled," - "zone_change_count," - "drakkin_heritage," - "drakkin_tattoo," - "drakkin_details," - "toxicity," - "hunger_level," - "thirst_level," - "ability_up," - "zone_id," - "zone_instance," - "leadership_exp_on," - "ldon_points_guk," - "ldon_points_mir," - "ldon_points_mmc," - "ldon_points_ruj," - "ldon_points_tak," - "ldon_points_available," - "tribute_time_remaining," - "show_helm," - "career_tribute_points," - "tribute_points," - "tribute_active," - "endurance," - "group_leadership_exp," - "raid_leadership_exp," - "group_leadership_points," - "raid_leadership_points," - "air_remaining," - "pvp_kills," - "pvp_deaths," - "pvp_current_points," - "pvp_career_points," - "pvp_best_kill_streak," - "pvp_worst_death_streak," - "pvp_current_kill_streak," - "aa_points_spent," - "aa_exp," - "aa_points," - "group_auto_consent," - "raid_auto_consent," - "guild_auto_consent," - "RestTimer) " - "VALUES (" - "%u," // id - "%u," // account_id - "'%s'," // `name` - "'%s'," // last_name - "%u," // gender - "%u," // race - "%u," // class - "%u," // `level` - "%u," // deity - "%u," // birthday - "%u," // last_login - "%u," // time_played - "%u," // pvp_status - "%u," // level2 - "%u," // anon - "%u," // gm - "%u," // intoxication - "%u," // hair_color - "%u," // beard_color - "%u," // eye_color_1 - "%u," // eye_color_2 - "%u," // hair_style - "%u," // beard - "%u," // ability_time_seconds - "%u," // ability_number - "%u," // ability_time_minutes - "%u," // ability_time_hours - "'%s'," // title - "'%s'," // suffix - "%u," // exp - "%u," // points - "%u," // mana - "%u," // cur_hp - "%u," // str - "%u," // sta - "%u," // cha - "%u," // dex - "%u," // `int` - "%u," // agi - "%u," // wis - "%u," // face - "%f," // y - "%f," // x - "%f," // z - "%f," // heading - "%u," // pvp2 - "%u," // pvp_type - "%u," // autosplit_enabled - "%u," // zone_change_count - "%u," // drakkin_heritage - "%u," // drakkin_tattoo - "%u," // drakkin_details - "%i," // toxicity - "%i," // hunger_level - "%i," // thirst_level - "%u," // ability_up - "%u," // zone_id - "%u," // zone_instance - "%u," // leadership_exp_on - "%u," // ldon_points_guk - "%u," // ldon_points_mir - "%u," // ldon_points_mmc - "%u," // ldon_points_ruj - "%u," // ldon_points_tak - "%u," // ldon_points_available - "%u," // tribute_time_remaining - "%u," // show_helm - "%u," // career_tribute_points - "%u," // tribute_points - "%u," // tribute_active - "%u," // endurance - "%u," // group_leadership_exp - "%u," // raid_leadership_exp - "%u," // group_leadership_point - "%u," // raid_leadership_points - "%u," // air_remaining - "%u," // pvp_kills - "%u," // pvp_deaths - "%u," // pvp_current_points - "%u," // pvp_career_points - "%u," // pvp_best_kill_streak - "%u," // pvp_worst_death_streak - "%u," // pvp_current_kill_strea - "%u," // aa_points_spent - "%u," // aa_exp - "%u," // aa_points - "%u," // group_auto_consent - "%u," // raid_auto_consent - "%u," // guild_auto_consent - "%u" // RestTimer - ")", - character_id, // " id, " - account_id, // " account_id, " - Strings::Escape(pp->name).c_str(), // " `name`, " - Strings::Escape(pp->last_name).c_str(), // " last_name, " - pp->gender, // " gender, " - pp->race, // " race, " - pp->class_, // " class, " - pp->level, // " `level`, " - pp->deity, // " deity, " - pp->birthday, // " birthday, " - pp->lastlogin, // " last_login, " - pp->timePlayedMin, // " time_played, " - pp->pvp, // " pvp_status, " - pp->level2, // " level2, " - pp->anon, // " anon, " - pp->gm, // " gm, " - pp->intoxication, // " intoxication, " - pp->haircolor, // " hair_color, " - pp->beardcolor, // " beard_color, " - pp->eyecolor1, // " eye_color_1, " - pp->eyecolor2, // " eye_color_2, " - pp->hairstyle, // " hair_style, " - pp->beard, // " beard, " - pp->ability_time_seconds, // " ability_time_seconds, " - pp->ability_number, // " ability_number, " - pp->ability_time_minutes, // " ability_time_minutes, " - pp->ability_time_hours, // " ability_time_hours, " - Strings::Escape(pp->title).c_str(), // " title, " - Strings::Escape(pp->suffix).c_str(), // " suffix, " - pp->exp, // " exp, " - pp->points, // " points, " - pp->mana, // " mana, " - pp->cur_hp, // " cur_hp, " - pp->STR, // " str, " - pp->STA, // " sta, " - pp->CHA, // " cha, " - pp->DEX, // " dex, " - pp->INT, // " `int`, " - pp->AGI, // " agi, " - pp->WIS, // " wis, " - pp->face, // " face, " - pp->y, // " y, " - pp->x, // " x, " - pp->z, // " z, " - pp->heading, // " heading, " - pp->pvp2, // " pvp2, " - pp->pvptype, // " pvp_type, " - pp->autosplit, // " autosplit_enabled, " - pp->zone_change_count, // " zone_change_count, " - pp->drakkin_heritage, // " drakkin_heritage, " - pp->drakkin_tattoo, // " drakkin_tattoo, " - pp->drakkin_details, // " drakkin_details, " - pp->toxicity, // " toxicity, " - pp->hunger_level, // " hunger_level, " - pp->thirst_level, // " thirst_level, " - pp->ability_up, // " ability_up, " - pp->zone_id, // " zone_id, " - pp->zoneInstance, // " zone_instance, " - pp->leadAAActive, // " leadership_exp_on, " - pp->ldon_points_guk, // " ldon_points_guk, " - pp->ldon_points_mir, // " ldon_points_mir, " - pp->ldon_points_mmc, // " ldon_points_mmc, " - pp->ldon_points_ruj, // " ldon_points_ruj, " - pp->ldon_points_tak, // " ldon_points_tak, " - pp->ldon_points_available, // " ldon_points_available, " - pp->tribute_time_remaining, // " tribute_time_remaining, " - pp->showhelm, // " show_helm, " - pp->career_tribute_points, // " career_tribute_points, " - pp->tribute_points, // " tribute_points, " - pp->tribute_active, // " tribute_active, " - pp->endurance, // " endurance, " - pp->group_leadership_exp, // " group_leadership_exp, " - pp->raid_leadership_exp, // " raid_leadership_exp, " - pp->group_leadership_points, // " group_leadership_points, " - pp->raid_leadership_points, // " raid_leadership_points, " - pp->air_remaining, // " air_remaining, " - pp->PVPKills, // " pvp_kills, " - pp->PVPDeaths, // " pvp_deaths, " - pp->PVPCurrentPoints, // " pvp_current_points, " - pp->PVPCareerPoints, // " pvp_career_points, " - pp->PVPBestKillStreak, // " pvp_best_kill_streak, " - pp->PVPWorstDeathStreak, // " pvp_worst_death_streak, " - pp->PVPCurrentKillStreak, // " pvp_current_kill_streak, " - pp->aapoints_spent, // " aa_points_spent, " - pp->expAA, // " aa_exp, " - pp->aapoints, // " aa_points, " - pp->groupAutoconsent, // " group_auto_consent, " - pp->raidAutoconsent, // " raid_auto_consent, " - pp->guildAutoconsent, // " guild_auto_consent, " - pp->RestTimer // " RestTimer) " - ); - QueryDatabase(query); + auto c = CharacterDataRepository::NewEntity(); - /* Save Bind Points */ - query = StringFormat( - "REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)" - " VALUES (%u, %u, %u, %f, %f, %f, %f, %i), " - "(%u, %u, %u, %f, %f, %f, %f, %i), " - "(%u, %u, %u, %f, %f, %f, %f, %i), " - "(%u, %u, %u, %f, %f, %f, %f, %i), " - "(%u, %u, %u, %f, %f, %f, %f, %i)", - character_id, pp->binds[0].zone_id, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading, 0, - character_id, pp->binds[1].zone_id, 0, pp->binds[1].x, pp->binds[1].y, pp->binds[1].z, pp->binds[1].heading, 1, - character_id, pp->binds[2].zone_id, 0, pp->binds[2].x, pp->binds[2].y, pp->binds[2].z, pp->binds[2].heading, 2, - character_id, pp->binds[3].zone_id, 0, pp->binds[3].x, pp->binds[3].y, pp->binds[3].z, pp->binds[3].heading, 3, - character_id, pp->binds[4].zone_id, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading, 4 - ); - QueryDatabase(query); + c.id = character_id; + c.account_id = account_id; + c.name = pp->name; + c.last_name = pp->last_name; + c.gender = pp->gender; + c.race = pp->race; + c.class_ = pp->class_; + c.level = pp->level; + c.deity = pp->deity; + c.birthday = pp->birthday; + c.last_login = pp->lastlogin; + c.time_played = pp->timePlayedMin; + c.pvp_status = pp->pvp; + c.level2 = pp->level2; + c.anon = pp->anon; + c.gm = pp->gm; + c.intoxication = pp->intoxication; + c.hair_color = pp->haircolor; + c.beard_color = pp->beardcolor; + c.eye_color_1 = pp->eyecolor1; + c.eye_color_2 = pp->eyecolor2; + c.hair_style = pp->hairstyle; + c.beard = pp->beard; + c.ability_time_seconds = pp->ability_time_seconds; + c.ability_number = pp->ability_number; + c.ability_time_minutes = pp->ability_time_minutes; + c.ability_time_hours = pp->ability_time_hours; + c.title = pp->title; + c.suffix = pp->suffix; + c.exp = pp->exp; + c.points = pp->points; + c.mana = pp->mana; + c.cur_hp = pp->cur_hp; + c.str = pp->STR; + c.sta = pp->STA; + c.cha = pp->CHA; + c.dex = pp->DEX; + c.int_ = pp->INT; + c.agi = pp->AGI; + c.wis = pp->WIS; + c.face = pp->face; + c.y = pp->y; + c.x = pp->x; + c.z = pp->z; + c.heading = pp->heading; + c.pvp2 = pp->pvp2; + c.pvp_type = pp->pvptype; + c.autosplit_enabled = pp->autosplit; + c.zone_change_count = pp->zone_change_count; + c.drakkin_heritage = pp->drakkin_heritage; + c.drakkin_tattoo = pp->drakkin_tattoo; + c.drakkin_details = pp->drakkin_details; + c.toxicity = pp->toxicity; + c.hunger_level = pp->hunger_level; + c.thirst_level = pp->thirst_level; + c.ability_up = pp->ability_up; + c.zone_id = pp->zone_id; + c.zone_instance = pp->zoneInstance; + c.leadership_exp_on = pp->leadAAActive; + c.ldon_points_guk = pp->ldon_points_guk; + c.ldon_points_mir = pp->ldon_points_mir; + c.ldon_points_mmc = pp->ldon_points_mmc; + c.ldon_points_ruj = pp->ldon_points_ruj; + c.ldon_points_tak = pp->ldon_points_tak; + c.ldon_points_available = pp->ldon_points_available; + c.tribute_time_remaining = pp->tribute_time_remaining; + c.show_helm = pp->showhelm; + c.career_tribute_points = pp->career_tribute_points; + c.tribute_points = pp->tribute_points; + c.tribute_active = pp->tribute_active; + c.endurance = pp->endurance; + c.group_leadership_exp = pp->group_leadership_exp; + c.raid_leadership_exp = pp->raid_leadership_exp; + c.group_leadership_points = pp->group_leadership_points; + c.raid_leadership_points = pp->raid_leadership_points; + c.air_remaining = pp->air_remaining; + c.pvp_kills = pp->PVPKills; + c.pvp_deaths = pp->PVPDeaths; + c.pvp_current_points = pp->PVPCurrentPoints; + c.pvp_career_points = pp->PVPCareerPoints; + c.pvp_best_kill_streak = pp->PVPBestKillStreak; + c.pvp_worst_death_streak = pp->PVPWorstDeathStreak; + c.pvp_current_kill_streak = pp->PVPCurrentKillStreak; + c.aa_points_spent = pp->aapoints_spent; + c.aa_exp = pp->expAA; + c.aa_points = pp->aapoints; + c.group_auto_consent = pp->groupAutoconsent; + c.raid_auto_consent = pp->raidAutoconsent; + c.guild_auto_consent = pp->guildAutoconsent; + c.RestTimer = pp->RestTimer; + + CharacterDataRepository::ReplaceOne(*this, c); + + std::vector character_binds; + + character_binds.reserve(5); + + auto b = CharacterBindRepository::NewEntity(); + + b.id = character_id; + + for (uint8 slot_id = 0; slot_id < 5; slot_id++) { + b.zone_id = pp->binds[slot_id].zone_id; + b.x = pp->binds[slot_id].x; + b.y = pp->binds[slot_id].y; + b.z = pp->binds[slot_id].z; + b.heading = pp->binds[slot_id].heading; + b.slot = slot_id; + + character_binds.emplace_back(b); + } + + CharacterBindRepository::ReplaceMany(*this, character_binds); - /* HoTT Ability */ if (RuleB(Character, GrantHoTTOnCreate)) { - query = StringFormat( - "INSERT INTO `character_leadership_abilities` (id, slot, `rank`) VALUES (%u, %i, %i)", - character_id, - 14, - 1 + CharacterLeadershipAbilitiesRepository::InsertOne( + *this, + CharacterLeadershipAbilitiesRepository::CharacterLeadershipAbilities{ + .id = character_id, + .slot = LeadershipAbilitySlot::HealthOfTargetsTarget, + .rank_ = 1 + } ); - QueryDatabase(query); } - /* Save Skills */ - int firstquery = 0; - for (int i = 0; i < MAX_PP_SKILL; i++) { - if (pp->skills[i] > 0) { - if (firstquery != 1) { - firstquery = 1; - query = StringFormat( - "REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", - character_id, - i, - pp->skills[i] - ); - } else { - query = query + StringFormat(", (%u, %u, %u)", character_id, i, pp->skills[i]); - } - } - } - QueryDatabase(query); + std::vector character_skills; - /* Save Language */ - firstquery = 0; - for (int i = 0; i < MAX_PP_LANGUAGE; i++) { - if (pp->languages[i] > 0) { - if (firstquery != 1) { - firstquery = 1; - query = StringFormat( - "REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", - character_id, - i, - pp->languages[i] - ); - } else { - query = query + StringFormat(", (%u, %u, %u)", character_id, i, pp->languages[i]); + character_skills.reserve(MAX_PP_SKILL); + + for (uint16 slot_id = 0; slot_id < MAX_PP_SKILL; slot_id++) { + character_skills.emplace_back( + CharacterSkillsRepository::CharacterSkills{ + .id = character_id, + .skill_id = slot_id, + .value = static_cast(pp->skills[slot_id]) } - } + ); } - QueryDatabase(query); + + CharacterSkillsRepository::ReplaceMany(*this, character_skills); + + std::vector character_languages; + + character_languages.reserve(MAX_PP_LANGUAGE); + + for (uint16 slot_id = 0; slot_id < MAX_PP_LANGUAGE; slot_id++) { + character_languages.emplace_back( + CharacterLanguagesRepository::CharacterLanguages{ + .id = character_id, + .lang_id = slot_id, + .value = static_cast(pp->languages[slot_id]) + } + ); + } + + CharacterLanguagesRepository::ReplaceMany(*this, character_languages); return true; } -uint32 Database::GetCharacterID(const char *name) { - const auto query = fmt::format( - "SELECT `id` FROM `character_data` WHERE `name` = '{}'", - Strings::Escape(name) +uint32 Database::GetCharacterID(const std::string& name) +{ + const auto& l = CharacterDataRepository::GetWhere( + *this, + fmt::format( + "`name` = '{}'", + Strings::Escape(name) + ) ); - auto results = QueryDatabase(query); - if (!results.Success() || !results.RowCount()) { + + if (l.empty()) { return 0; } - auto row = results.begin(); - return Strings::ToUnsignedInt(row[0]); + auto e = l.front(); + + return e.id; } /* diff --git a/common/database.h b/common/database.h index 4e5613a48..1ab16f180 100644 --- a/common/database.h +++ b/common/database.h @@ -125,7 +125,7 @@ public: uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0); uint32 GetAccountIDByChar(uint32 char_id); uint32 GetAccountIDByName(std::string account_name, std::string loginserver, int16* status = 0, uint32* lsid = 0); - uint32 GetCharacterID(const char *name); + uint32 GetCharacterID(const std::string& name); uint32 GetCharacterInfo(std::string character_name, uint32 *account_id, uint32 *zone_id, uint32 *instance_id); uint32 GetGuildIDByCharID(uint32 char_id); uint32 GetGroupIDByCharID(uint32 char_id); diff --git a/common/eq_constants.h b/common/eq_constants.h index b3ad218aa..31c02aaa3 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -1127,4 +1127,8 @@ namespace RaidLootType { constexpr uint32 EntireRaid = 4; } +namespace LeadershipAbilitySlot { + constexpr uint16 HealthOfTargetsTarget = 14; +} + #endif /*COMMON_EQ_CONSTANTS_H*/ diff --git a/world/adventure.cpp b/world/adventure.cpp index 8f571fdb0..3efece3ec 100644 --- a/world/adventure.cpp +++ b/world/adventure.cpp @@ -56,7 +56,7 @@ void Adventure::AddPlayer(std::string character_name, bool add_client_to_instanc { if(!PlayerExists(character_name)) { - int32 character_id = database.GetCharacterID(character_name.c_str()); + int32 character_id = database.GetCharacterID(character_name); if(character_id && add_client_to_instance) { database.AddClientToInstance(instance_id, character_id); @@ -72,7 +72,7 @@ void Adventure::RemovePlayer(std::string character_name) { if((*iter).compare(character_name) == 0) { - int32 character_id = database.GetCharacterID(character_name.c_str()); + int32 character_id = database.GetCharacterID(character_name); if (character_id) { database.RemoveClientFromInstance(instance_id, character_id); @@ -312,7 +312,7 @@ void Adventure::Finished(AdventureWinStatus ws) } zoneserver_list.SendPacket(current->zone(), current->instance(), pack); - database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter).c_str()), GetTemplate()->theme, (ws != AWS_Lose) ? true : false); + database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter)), GetTemplate()->theme, (ws != AWS_Lose) ? true : false); delete pack; } else @@ -337,7 +337,7 @@ void Adventure::Finished(AdventureWinStatus ws) afe.points = 0; } adventure_manager.AddFinishedEvent(afe); - database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter).c_str()), GetTemplate()->theme, (ws != AWS_Lose) ? true : false); + database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter)), GetTemplate()->theme, (ws != AWS_Lose) ? true : false); } } else @@ -363,7 +363,7 @@ void Adventure::Finished(AdventureWinStatus ws) } adventure_manager.AddFinishedEvent(afe); - database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter).c_str()), GetTemplate()->theme, (ws != AWS_Lose) ? true : false); + database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter)), GetTemplate()->theme, (ws != AWS_Lose) ? true : false); } ++iter; } diff --git a/world/client.cpp b/world/client.cpp index 838139208..31fd36ffe 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -50,6 +50,7 @@ #include "../common/zone_store.h" #include "../common/repositories/account_repository.h" #include "../common/repositories/player_event_logs_repository.h" +#include "../common/repositories/inventory_repository.h" #include "../common/events/player_event_logs.h" #include @@ -1613,10 +1614,18 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) inv.SetInventoryVersion(EQ::versions::ConvertClientVersionBitToClientVersion(m_ClientVersionBit)); inv.SetGMInventory(false); // character cannot have gm flag at this point - time_t bday = time(nullptr); + time_t bday = time(nullptr); in_addr in; - int stats_sum = cc->STR + cc->STA + cc->AGI + cc->DEX + cc->WIS + cc->INT + cc->CHA; + const uint32 stats_sum = ( + cc->AGI + + cc->CHA + + cc->DEX + + cc->INT + + cc->STA + + cc->STR + + cc->WIS + ); in.s_addr = GetIP(); @@ -1629,7 +1638,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) ); LogInfo("Name [{}]", name); LogInfo( - "Race [{}] Class [{}] Gender [{}] Deity [{}] Start zone [{}] Tutorial [{}]", + "race [{}] class [{}] gender [{}] deity [{}] start_zone [{}] tutorial [{}]", cc->race, cc->class_, cc->gender, @@ -1637,21 +1646,20 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) cc->start_zone, cc->tutorial ? "true" : "false" ); - LogInfo("STR STA AGI DEX WIS INT CHA Total"); LogInfo( - " [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}]", - cc->STR, - cc->STA, + "AGI [{}] CHA [{}] DEX [{}] INT [{}] STA [{}] STR [{}] WIS [{}] Total [{}]", cc->AGI, - cc->DEX, - cc->WIS, - cc->INT, cc->CHA, + cc->DEX, + cc->INT, + cc->STA, + cc->STR, + cc->WIS, stats_sum ); - LogInfo("Face [{}] Eye colors [{}] [{}]", cc->face, cc->eyecolor1, cc->eyecolor2); - LogInfo("Hairstyle [{}] Haircolor [{}]", cc->hairstyle, cc->haircolor); - LogInfo("Beard [{}] Beardcolor [{}]", cc->beard, cc->beardcolor); + LogInfo("Face [{}] Eye Colors [{}] [{}]", cc->face, cc->eyecolor1, cc->eyecolor2); + LogInfo("Hair [{}] Hair Color [{}]", cc->hairstyle, cc->haircolor); + LogInfo("Beard [{}] Beard Color [{}]", cc->beard, cc->beardcolor); /* Validate the char creation struct */ if (m_ClientVersionBit & EQ::versions::maskSoFAndLater) { @@ -1669,39 +1677,39 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) /* Convert incoming cc_s to the new PlayerProfile_Struct */ memset(&pp, 0, sizeof(PlayerProfile_Struct)); // start building the profile - strn0cpy(pp.name, name, 63); + strn0cpy(pp.name, name, sizeof(pp.name)); - pp.race = cc->race; - pp.class_ = cc->class_; - pp.gender = cc->gender; - pp.deity = cc->deity; - pp.STR = cc->STR; - pp.STA = cc->STA; - pp.AGI = cc->AGI; - pp.DEX = cc->DEX; - pp.WIS = cc->WIS; - pp.INT = cc->INT; - pp.CHA = cc->CHA; - pp.face = cc->face; - pp.eyecolor1 = cc->eyecolor1; - pp.eyecolor2 = cc->eyecolor2; - pp.hairstyle = cc->hairstyle; - pp.haircolor = cc->haircolor; - pp.beard = cc->beard; - pp.beardcolor = cc->beardcolor; - pp.drakkin_heritage = cc->drakkin_heritage; - pp.drakkin_tattoo = cc->drakkin_tattoo; - pp.drakkin_details = cc->drakkin_details; - pp.birthday = bday; - pp.lastlogin = bday; - pp.level = 1; - pp.points = 5; - pp.cur_hp = 1000; // 1k hp during dev only - pp.hunger_level = 6000; - pp.thirst_level = 6000; + pp.race = cc->race; + pp.class_ = cc->class_; + pp.gender = cc->gender; + pp.deity = cc->deity; + pp.STR = cc->STR; + pp.STA = cc->STA; + pp.AGI = cc->AGI; + pp.DEX = cc->DEX; + pp.WIS = cc->WIS; + pp.INT = cc->INT; + pp.CHA = cc->CHA; + pp.face = cc->face; + pp.eyecolor1 = cc->eyecolor1; + pp.eyecolor2 = cc->eyecolor2; + pp.hairstyle = cc->hairstyle; + pp.haircolor = cc->haircolor; + pp.beard = cc->beard; + pp.beardcolor = cc->beardcolor; + pp.drakkin_heritage = cc->drakkin_heritage; + pp.drakkin_tattoo = cc->drakkin_tattoo; + pp.drakkin_details = cc->drakkin_details; + pp.birthday = bday; + pp.lastlogin = bday; + pp.level = 1; + pp.points = 5; + pp.cur_hp = 1000; + pp.hunger_level = 6000; + pp.thirst_level = 6000; /* Set default skills for everybody */ - pp.skills[EQ::skills::SkillSwimming] = RuleI(Skills, SwimmingStartValue); + pp.skills[EQ::skills::SkillSwimming] = RuleI(Skills, SwimmingStartValue); pp.skills[EQ::skills::SkillSenseHeading] = RuleI(Skills, SenseHeadingStartValue); /* Set Racial and Class specific language and skills */ @@ -1710,13 +1718,12 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) SetClassStartingSkills(&pp); SetClassLanguages(&pp); -// strcpy(pp.servername, WorldConfig::get()->ShortName.c_str()); + memset(pp.spell_book, std::numeric_limits::max(), (sizeof(uint32) * EQ::spells::SPELLBOOK_SIZE)); + memset(pp.mem_spells, std::numeric_limits::max(), (sizeof(uint32) * EQ::spells::SPELL_GEM_COUNT)); - memset(pp.spell_book, 0xFF, (sizeof(uint32) * EQ::spells::SPELLBOOK_SIZE)); - memset(pp.mem_spells, 0xFF, (sizeof(uint32) * EQ::spells::SPELL_GEM_COUNT)); - - for (auto& buff : pp.buffs) - buff.spellid = 0xFFFF; + for (auto& b : pp.buffs) { + b.spellid = std::numeric_limits::max(); + } /* If server is PVP by default, make all character set to it. */ pp.pvp = database.GetServerType() == 1 ? 1 : 0; @@ -1728,56 +1735,38 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) pp.zone_id = RuleI(World, SoFStartZoneID); cc->start_zone = pp.zone_id; } - } - else { + } else { LogInfo("Found [TitaniumStartZoneID] rule setting [{}]", RuleI(World, TitaniumStartZoneID)); if (RuleI(World, TitaniumStartZoneID) > 0) { /* if there's a startzone variable put them in there */ - - pp.zone_id = RuleI(World, TitaniumStartZoneID); + pp.zone_id = RuleI(World, TitaniumStartZoneID); cc->start_zone = pp.zone_id; } } - /* use normal starting zone logic to either get defaults, or if startzone was set, load that from the db table.*/ - bool ValidStartZone = content_db.GetStartZone(&pp, cc, m_ClientVersionBit & EQ::versions::maskTitaniumAndEarlier); - if (!ValidStartZone){ + /* use normal starting zone logic to either get defaults, or if startzone was set, load that from the db table.*/ + const bool is_valid_start_zone = content_db.GetStartZone(&pp, cc, m_ClientVersionBit & EQ::versions::maskTitaniumAndEarlier); + if (!is_valid_start_zone){ return false; } - /* just in case */ if (!pp.zone_id) { - pp.zone_id = 1; // qeynos + pp.zone_id = Zones::QEYNOS; + pp.x = pp.y = pp.z = -1; } - /* Set Home Binds -- yep, all of them */ - pp.binds[1].zone_id = pp.zone_id; - pp.binds[1].x = pp.x; - pp.binds[1].y = pp.y; - pp.binds[1].z = pp.z; - pp.binds[1].heading = pp.heading; - - pp.binds[2].zone_id = pp.zone_id; - pp.binds[2].x = pp.x; - pp.binds[2].y = pp.y; - pp.binds[2].z = pp.z; - pp.binds[2].heading = pp.heading; - - pp.binds[3].zone_id = pp.zone_id; - pp.binds[3].x = pp.x; - pp.binds[3].y = pp.y; - pp.binds[3].z = pp.z; - pp.binds[3].heading = pp.heading; - - pp.binds[4].zone_id = pp.zone_id; - pp.binds[4].x = pp.x; - pp.binds[4].y = pp.y; - pp.binds[4].z = pp.z; - pp.binds[4].heading = pp.heading; + for (uint8 slot_id = 1; slot_id < 5; slot_id++) { + pp.binds[slot_id].zone_id = pp.zone_id; + pp.binds[slot_id].x = pp.x; + pp.binds[slot_id].y = pp.y; + pp.binds[slot_id].z = pp.z; + pp.binds[slot_id].heading = pp.heading; + } /* Overrides if we have the tutorial flag set! */ if (cc->tutorial && RuleB(World, EnableTutorialButton)) { pp.zone_id = RuleI(World, TutorialZoneID); + auto z = GetZone(pp.zone_id); if (z) { pp.x = z->safe_x; @@ -1787,17 +1776,17 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) } /* Will either be the same as home or tutorial if enabled. */ - if(RuleB(World, StartZoneSameAsBindOnCreation)) { + if (RuleB(World, StartZoneSameAsBindOnCreation)) { pp.binds[0].zone_id = pp.zone_id; - pp.binds[0].x = pp.x; - pp.binds[0].y = pp.y; - pp.binds[0].z = pp.z; + pp.binds[0].x = pp.x; + pp.binds[0].y = pp.y; + pp.binds[0].z = pp.z; pp.binds[0].heading = pp.heading; } if (GetZone(pp.zone_id)) { LogInfo( - "Current location [{}] [{}] [{:.2f}] [{:.2f}] [{:.2f}] [{:.2f}]", + "Current location zone_short_name [{}] zone_id [{}] x [{:.2f}] y [{:.2f}] z [{:.2f}] heading [{:.2f}]", ZoneName(pp.zone_id), pp.zone_id, pp.x, @@ -1809,37 +1798,34 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) if (GetZone(pp.binds[0].zone_id)) { LogInfo( - "Bind location [{}] [{}] [{:.2f}] [{:.2f}] [{:.2f}]", + "Bind location zone_short_name [{}] zone_id [{}] x [{:.2f}] y [{:.2f}] z [{:.2f}] heading [{:.2f}]", ZoneName(pp.binds[0].zone_id), pp.binds[0].zone_id, pp.binds[0].x, pp.binds[0].y, - pp.binds[0].z + pp.binds[0].z, + pp.binds[4].heading ); } if (GetZone(pp.binds[4].zone_id)) { LogInfo( - "Home location [{}] [{}] [{:.2f}] [{:.2f}] [{:.2f}]", + "Home location zone_short_name [{}] zone_id [{}] x [{:.2f}] y [{:.2f}] z [{:.2f}] heading [{:.2f}]", ZoneName(pp.binds[4].zone_id), pp.binds[4].zone_id, pp.binds[4].x, pp.binds[4].y, - pp.binds[4].z + pp.binds[4].z, + pp.binds[4].heading ); } - /* Starting Items inventory */ content_db.SetStartingItems(&pp, &inv, pp.race, pp.class_, pp.deity, pp.zone_id, pp.name, GetAdmin()); - // now we give the pp and the inv we made to StoreCharacter - // to see if we can store it - if (!StoreCharacter(GetAccountID(), &pp, &inv)) { - LogInfo("Character creation failed: [{}]", pp.name); - return false; - } - LogInfo("Character creation successful: [{}]", pp.name); - return true; + const bool success = StoreCharacter(GetAccountID(), &pp, &inv); + + LogInfo("Character creation {} for [{}]", success ? "succeeded" : "failed", pp.name); + return success; } // returns true if the request is ok, false if there's an error @@ -2312,56 +2298,51 @@ bool Client::StoreCharacter( EQ::InventoryProfile *p_inventory_profile ) { - uint32 character_id = 0; - char zone[50]; - character_id = database.GetCharacterID(p_player_profile_struct->name); - + const uint32 character_id = database.GetCharacterID(p_player_profile_struct->name); if (!character_id) { - LogError("StoreCharacter: no character id"); return false; } - const char *zone_name = ZoneName(p_player_profile_struct->zone_id); - if (zone_name == nullptr) { - /* Zone not in the DB, something to prevent crash... */ - strn0cpy(zone, "qeynos", 49); - p_player_profile_struct->zone_id = 1; - } - else { - strn0cpy(zone, zone_name, 49); + const std::string& zone_name = zone_store.GetZoneName(p_player_profile_struct->zone_id, true); + if (Strings::EqualFold(zone_name, "UNKNOWN")) { + p_player_profile_struct->zone_id = Zones::QEYNOS; } database.SaveCharacterCreate(character_id, account_id, p_player_profile_struct); - std::string invquery; - for (int16 i = EQ::invslot::EQUIPMENT_BEGIN; i <= EQ::invbag::BANK_BAGS_END;) { - const EQ::ItemInstance *new_inventory_item = p_inventory_profile->GetItem(i); - if (new_inventory_item) { - invquery = StringFormat( - "INSERT INTO `inventory` (charid, slotid, itemid, charges, color) VALUES (%u, %i, %u, %i, %u)", - character_id, - i, - new_inventory_item->GetItem()->ID, - new_inventory_item->GetCharges(), - new_inventory_item->GetColor() - ); + std::vector v; - auto results = database.QueryDatabase(invquery); + auto e = InventoryRepository::NewEntity(); + + e.charid = character_id; + + for (int16 slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invbag::BANK_BAGS_END;) { + const auto inst = p_inventory_profile->GetItem(slot_id); + if (inst) { + e.slotid = slot_id; + e.itemid = inst->GetItem()->ID; + e.charges = inst->GetCharges(); + e.color = inst->GetColor(); + + v.emplace_back(e); } - if (i == EQ::invslot::slotCursor) { - i = EQ::invbag::GENERAL_BAGS_BEGIN; + if (slot_id == EQ::invslot::slotCursor) { + slot_id = EQ::invbag::GENERAL_BAGS_BEGIN; + continue; + } else if (slot_id == EQ::invbag::CURSOR_BAG_END) { + slot_id = EQ::invslot::BANK_BEGIN; + continue; + } else if (slot_id == EQ::invslot::BANK_END) { + slot_id = EQ::invbag::BANK_BAGS_BEGIN; continue; } - else if (i == EQ::invbag::CURSOR_BAG_END) { - i = EQ::invslot::BANK_BEGIN; - continue; - } - else if (i == EQ::invslot::BANK_END) { - i = EQ::invbag::BANK_BAGS_BEGIN; - continue; - } - i++; + + slot_id++; + } + + if (!v.empty()) { + InventoryRepository::InsertMany(database, v); } return true; diff --git a/zone/expedition.cpp b/zone/expedition.cpp index 3e2b7c2e8..436601126 100644 --- a/zone/expedition.cpp +++ b/zone/expedition.cpp @@ -1161,7 +1161,7 @@ void Expedition::AddLockoutByCharacterName( { if (!character_name.empty()) { - uint32_t character_id = database.GetCharacterID(character_name.c_str()); + uint32_t character_id = database.GetCharacterID(character_name); AddLockoutByCharacterID(character_id, expedition_name, event_name, seconds, uuid); } } @@ -1180,7 +1180,7 @@ bool Expedition::HasLockoutByCharacterName( { if (!character_name.empty()) { - uint32_t character_id = database.GetCharacterID(character_name.c_str()); + uint32_t character_id = database.GetCharacterID(character_name); return HasLockoutByCharacterID(character_id, expedition_name, event_name); } return false; @@ -1214,7 +1214,7 @@ void Expedition::RemoveLockoutsByCharacterName( { if (!character_name.empty()) { - uint32_t character_id = database.GetCharacterID(character_name.c_str()); + uint32_t character_id = database.GetCharacterID(character_name); RemoveLockoutsByCharacterID(character_id, expedition_name, event_name); } } diff --git a/zone/expedition_request.cpp b/zone/expedition_request.cpp index e74697144..0fbf90af9 100644 --- a/zone/expedition_request.cpp +++ b/zone/expedition_request.cpp @@ -126,7 +126,7 @@ bool ExpeditionRequest::CanGroupRequest(Group* group) // Group::GetLeaderName() is broken if group formed across zones, ask database instead m_leader_name = m_leader ? m_leader->GetName() : GetGroupLeaderName(group->GetID()); // group->GetLeaderName(); - m_leader_id = m_leader ? m_leader->CharacterID() : database.GetCharacterID(m_leader_name.c_str()); + m_leader_id = m_leader ? m_leader->CharacterID() : database.GetCharacterID(m_leader_name); std::vector member_names; member_names.emplace_back(m_leader_name); // leader always added first diff --git a/zone/gm_commands/instance.cpp b/zone/gm_commands/instance.cpp index 413eeebed..060bbcb81 100755 --- a/zone/gm_commands/instance.cpp +++ b/zone/gm_commands/instance.cpp @@ -80,7 +80,7 @@ void command_instance(Client *c, const Seperator *sep) std::string character_name = sep->arg[3]; uint16 instance_id = static_cast(Strings::ToUnsignedInt(sep->arg[2])); - uint32 character_id = database.GetCharacterID(character_name.c_str()); + uint32 character_id = database.GetCharacterID(character_name); if (instance_id <= 0 || character_id <= 0) { c->Message(Chat::White, "You must enter a valid Instance ID and player name."); return; @@ -270,7 +270,7 @@ void command_instance(Client *c, const Seperator *sep) std::string character_name = sep->arg[3]; uint16 instance_id = static_cast(Strings::ToUnsignedInt(sep->arg[2])); - uint32 character_id = database.GetCharacterID(character_name.c_str()); + uint32 character_id = database.GetCharacterID(character_name); if (instance_id <= 0 || character_id <= 0) { c->Message(Chat::White, "You must enter a valid Instance ID and player name."); return; diff --git a/zone/gm_commands/movechar.cpp b/zone/gm_commands/movechar.cpp index e6102cedd..b157d2316 100755 --- a/zone/gm_commands/movechar.cpp +++ b/zone/gm_commands/movechar.cpp @@ -13,7 +13,7 @@ void command_movechar(Client *c, const Seperator *sep) database.GetCharNameByID(Strings::ToUnsignedInt(sep->arg[1])) : sep->arg[1] ); - const uint32 character_id = database.GetCharacterID(character_name.c_str()); + const uint32 character_id = database.GetCharacterID(character_name); if (!character_id) { c->Message( Chat::White, diff --git a/zone/gm_commands/summon.cpp b/zone/gm_commands/summon.cpp index 97bf512b5..710aea67c 100755 --- a/zone/gm_commands/summon.cpp +++ b/zone/gm_commands/summon.cpp @@ -16,7 +16,7 @@ void command_summon(Client *c, const Seperator *sep) if (arguments == 1) { std::string character_name = sep->arg[1]; - auto character_id = database.GetCharacterID(character_name.c_str()); + auto character_id = database.GetCharacterID(character_name); if (!character_id) { c->Message( Chat::White,