diff --git a/common/repositories/base/base_character_disciplines_repository.h b/common/repositories/base/base_character_disciplines_repository.h index 882c32165..23796c2a3 100644 --- a/common/repositories/base/base_character_disciplines_repository.h +++ b/common/repositories/base/base_character_disciplines_repository.h @@ -6,7 +6,7 @@ * Any modifications to base repositories are to be made by the generator only * * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories + * @docs https://docs.eqemu.io/developer/repositories */ #ifndef EQEMU_BASE_CHARACTER_DISCIPLINES_REPOSITORY_H @@ -16,6 +16,7 @@ #include "../../strings.h" #include + class BaseCharacterDisciplinesRepository { public: struct CharacterDisciplines { @@ -112,8 +113,9 @@ public: { auto results = db.QueryDatabase( fmt::format( - "{} WHERE id = {} LIMIT 1", + "{} WHERE {} = {} LIMIT 1", BaseSelect(), + PrimaryKey(), character_disciplines_id ) ); @@ -338,6 +340,66 @@ public: return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); } + static std::string BaseReplace() + { + return fmt::format( + "REPLACE INTO {} ({}) ", + TableName(), + ColumnsRaw() + ); + } + + static int ReplaceOne( + Database& db, + const CharacterDisciplines &e + ) + { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.disc_id)); + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseReplace(), + Strings::Implode(",", v) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int ReplaceMany( + Database& db, + const std::vector &entries + ) + { + std::vector insert_chunks; + + for (auto &e: entries) { + std::vector v; + + v.push_back(std::to_string(e.id)); + v.push_back(std::to_string(e.slot_id)); + v.push_back(std::to_string(e.disc_id)); + + insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); + } + + std::vector v; + + auto results = db.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseReplace(), + Strings::Implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } }; #endif //EQEMU_BASE_CHARACTER_DISCIPLINES_REPOSITORY_H diff --git a/zone/client.cpp b/zone/client.cpp index ea41f637d..b8bbf3619 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -10742,22 +10742,22 @@ void Client::SaveSpells() void Client::SaveDisciplines() { - std::vector character_discs = {}; + std::vector v; - for (int index = 0; index < MAX_PP_DISCIPLINES; index++) { - if (IsValidSpell(m_pp.disciplines.values[index])) { - auto discipline = CharacterDisciplinesRepository::NewEntity(); - discipline.id = CharacterID(); - discipline.slot_id = index; - discipline.disc_id = m_pp.disciplines.values[index]; - character_discs.emplace_back(discipline); + for (int slot_id = 0; slot_id < MAX_PP_DISCIPLINES; slot_id++) { + if (IsValidSpell(m_pp.disciplines.values[slot_id])) { + auto e = CharacterDisciplinesRepository::NewEntity(); + + e.id = CharacterID(); + e.slot_id = slot_id; + e.disc_id = m_pp.disciplines.values[slot_id]; + + v.emplace_back(e); } } - CharacterDisciplinesRepository::DeleteWhere(database, fmt::format("id = {}", CharacterID())); - - if (!character_discs.empty()) { - CharacterDisciplinesRepository::InsertMany(database, character_discs); + if (!v.empty()) { + CharacterDisciplinesRepository::ReplaceMany(database, v); } } diff --git a/zone/effects.cpp b/zone/effects.cpp index 254551d70..b1b126f75 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -690,7 +690,7 @@ bool Client::TrainDiscipline(uint32 itemid) { return false; } else if (m_pp.disciplines.values[r] == 0) { m_pp.disciplines.values[r] = spell_id; - database.SaveCharacterDisc(CharacterID(), r, spell_id); + database.SaveCharacterDiscipline(CharacterID(), r, spell_id); SendDisciplineUpdate(); Message(Chat::White, "You have learned a new discipline!"); return true; @@ -789,7 +789,7 @@ void Client::TrainDiscBySpellID(int32 spell_id) for(i = 0; i < MAX_PP_DISCIPLINES; i++) { if(m_pp.disciplines.values[i] == 0) { m_pp.disciplines.values[i] = spell_id; - database.SaveCharacterDisc(CharacterID(), i, spell_id); + database.SaveCharacterDiscipline(CharacterID(), i, spell_id); SendDisciplineUpdate(); Message(Chat::Yellow, "You have learned a new combat ability!"); return; diff --git a/zone/spells.cpp b/zone/spells.cpp index 04d1a9397..dd867b2a2 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5761,7 +5761,7 @@ void Client::UntrainDisc(int slot, bool update_client, bool defer_save) m_pp.disciplines.values[slot] = 0; if (!defer_save) { - database.DeleteCharacterDisc(CharacterID(), slot); + database.DeleteCharacterDiscipline(CharacterID(), slot); } if (update_client) { diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 17eb306b4..c146d61b3 100755 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -766,24 +766,27 @@ bool ZoneDatabase::LoadCharacterLeadershipAbilities(uint32 character_id, PlayerP bool ZoneDatabase::LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp){ - auto character_disciplines = CharacterDisciplinesRepository::GetWhere( + const auto& l = CharacterDisciplinesRepository::GetWhere( database, fmt::format( "`id` = {} ORDER BY `slot_id`", character_id ) ); - if (character_disciplines.empty()) { + if (l.empty()) { return false; } - /* Initialize Disciplines */ - memset(pp->disciplines.values, 0, (sizeof(pp->disciplines.values[0]) * MAX_PP_DISCIPLINES)); - for (auto& row : character_disciplines) { - if (row.slot_id < MAX_PP_DISCIPLINES && IsValidSpell(row.disc_id)) { - pp->disciplines.values[row.slot_id] = row.disc_id; + for (int slot_id = 0; slot_id < MAX_PP_DISCIPLINES; slot_id++) { // Initialize Disciplines + pp->disciplines.values[slot_id] = 0; + } + + for (const auto& e : l) { + if (IsValidSpell(e.disc_id) && e.slot_id < MAX_PP_DISCIPLINES) { + pp->disciplines.values[e.slot_id] = e.disc_id; } } + return true; } @@ -1018,11 +1021,16 @@ bool ZoneDatabase::SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint ); } -bool ZoneDatabase::SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id){ - std::string query = StringFormat("REPLACE INTO `character_disciplines` (id, slot_id, disc_id) VALUES (%u, %u, %u)", character_id, slot_id, disc_id); - auto results = QueryDatabase(query); - LogDebug("ZoneDatabase::SaveCharacterDisc for character ID: [{}], slot:[{}] disc_id:[{}] done", character_id, slot_id, disc_id); - return true; +bool ZoneDatabase::SaveCharacterDiscipline(uint32 character_id, uint32 slot_id, uint32 disc_id) +{ + return CharacterDisciplinesRepository::ReplaceOne( + *this, + CharacterDisciplinesRepository::CharacterDisciplines{ + .id = character_id, + .slot_id = static_cast(slot_id), + .disc_id = static_cast(disc_id) + } + ); } void ZoneDatabase::SaveCharacterTribute(Client* c) @@ -1316,10 +1324,16 @@ bool ZoneDatabase::DeleteCharacterSpell(uint32 character_id, uint32 slot_id) ); } -bool ZoneDatabase::DeleteCharacterDisc(uint32 character_id, uint32 slot_id){ - std::string query = StringFormat("DELETE FROM `character_disciplines` WHERE `slot_id` = %u AND `id` = %u", slot_id, character_id); - QueryDatabase(query); - return true; +bool ZoneDatabase::DeleteCharacterDiscipline(uint32 character_id, uint32 slot_id) +{ + return CharacterDisciplinesRepository::DeleteWhere( + *this, + fmt::format( + "`id` = {} AND `slot_id` = {}", + character_id, + slot_id + ) + ); } bool ZoneDatabase::DeleteCharacterBandolier(uint32 character_id, uint32 bandolier_id) diff --git a/zone/zonedb.h b/zone/zonedb.h index 849e703c9..f436dd17c 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -424,7 +424,7 @@ public: bool DeleteCharacterAAs(uint32 character_id); bool DeleteCharacterBandolier(uint32 character_id, uint32 bandolier_id); - bool DeleteCharacterDisc(uint32 character_id, uint32 slot_id); + bool DeleteCharacterDiscipline(uint32 character_id, uint32 slot_id); bool DeleteCharacterMaterialColor(uint32 character_id); bool DeleteCharacterLeadershipAbilities(uint32 character_id); bool DeleteCharacterMemorizedSpell(uint32 character_id, uint32 slot_id); @@ -447,7 +447,7 @@ public: bool SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name); bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); bool SaveCharacterData(Client* c, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp); - bool SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id); + bool SaveCharacterDiscipline(uint32 character_id, uint32 slot_id, uint32 disc_id); bool SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value); bool SaveCharacterLeadershipAbilities(uint32 character_id, PlayerProfile_Struct* pp); bool SaveCharacterMaterialColor(uint32 character_id, uint8 slot_id, uint32 color);