diff --git a/zone/client.cpp b/zone/client.cpp index 37adaec76..04e2a0b8f 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -656,10 +656,10 @@ bool Client::Save(uint8 iCommitNow) { /* Save Character Currency */ database.SaveCharacterCurrency(CharacterID(), &m_pp); - /* Save Current Bind Points */ - for (int i = 0; i < 5; i++) - if (m_pp.binds[i].zone_id) - database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[i], i); + // save character binds + // this may not need to be called in Save() but it's here for now + // to maintain the current behavior + database.SaveCharacterBinds(this); /* Save Character Buffs */ database.SaveBuffs(this); diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 416167b27..192f5a8b1 100755 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -13,6 +13,7 @@ #include "aura.h" #include "../common/repositories/character_disciplines_repository.h" #include "../common/repositories/npc_types_repository.h" +#include "../common/repositories/character_bind_repository.h" #include #include @@ -1030,25 +1031,6 @@ bool ZoneDatabase::SaveCharacterLanguage(uint32 character_id, uint32 lang_id, ui return true; } -bool ZoneDatabase::SaveCharacterBindPoint(uint32 character_id, const BindStruct &bind, uint32 bind_num) -{ - /* Save Home Bind Point */ - std::string 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)", - character_id, bind.zone_id, bind.instance_id, bind.x, bind.y, bind.z, bind.heading, bind_num); - - LogDebug("ZoneDatabase::SaveCharacterBindPoint for character ID: [{}] zone_id: [{}] instance_id: [{}] position: [{}] [{}] [{}] [{}] bind_num: [{}]", - character_id, bind.zone_id, bind.instance_id, bind.x, bind.y, bind.z, bind.heading, bind_num); - - auto results = QueryDatabase(query); - if (!results.RowsAffected()) - LogDebug("ERROR Bind Home Save: [{}]. [{}]", results.ErrorMessage().c_str(), - query.c_str()); - - return true; -} - bool ZoneDatabase::SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color){ uint8 red = (color & 0x00FF0000) >> 16; uint8 green = (color & 0x0000FF00) >> 8; @@ -4518,3 +4500,52 @@ void ZoneDatabase::UpdateGMStatus(uint32 accID, int newStatus) database.QueryDatabase(query); } } + +void ZoneDatabase::SaveCharacterBinds(Client *c) +{ + // bulk save character binds + std::vector binds = {}; + CharacterBindRepository::CharacterBind bind = {}; + + // count character binds + int bind_count = 0; + for (auto & b : c->GetPP().binds) { + if (b.zone_id) { + bind_count++; + } + } + + LogInfo("bind count is [{}]", bind_count); + + // allocate memory for binds + binds.reserve(bind_count); + + // copy binds to vector + int i = 0; + for (auto &b: c->GetPP().binds) { + if (b.zone_id) { + // copy bind data + bind.id = c->CharacterID(); + bind.zone_id = b.zone_id; + bind.instance_id = b.instance_id; + bind.x = b.x; + bind.y = b.y; + bind.z = b.z; + bind.heading = b.heading; + bind.slot = i; + + // add bind to vector + binds.emplace_back(bind); + + i++; + } + } + + // save binds + if (bind_count > 0) { + // delete old binds + CharacterBindRepository::DeleteWhere(database, fmt::format("id = {}", c->CharacterID())); + // save new binds + CharacterBindRepository::InsertMany(database, binds); + } +} diff --git a/zone/zonedb.h b/zone/zonedb.h index 23309128c..c39e75e4b 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -304,7 +304,7 @@ struct CharacterCorpseItemEntry uint32 ornament_hero_model; }; -struct CharacterCorpseEntry +struct CharacterCorpseEntry { bool locked; uint32 exp; @@ -446,7 +446,6 @@ public: bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level, uint32 charges); bool SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name); - bool SaveCharacterBindPoint(uint32 character_id, const BindStruct &bind, uint32 bind_number); 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); @@ -666,6 +665,7 @@ public: // bot database add-on to eliminate the need for a second database connection BotDatabase botdb; + static void SaveCharacterBinds(Client *c); protected: void ZDBInitVars(); diff --git a/zone/zoning.cpp b/zone/zoning.cpp index f31f5a8a4..1f9375ef1 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -890,23 +890,28 @@ void NPC::Gate(uint8 bind_number) { void Client::SetBindPoint(int bind_number, int to_zone, int to_instance, const glm::vec3 &location) { - if (bind_number < 0 || bind_number >= 4) + if (bind_number < 0 || bind_number >= 4) { bind_number = 0; + } if (to_zone == -1) { - m_pp.binds[bind_number].zone_id = zone->GetZoneID(); - m_pp.binds[bind_number].instance_id = (zone->GetInstanceID() != 0 && zone->IsInstancePersistent()) ? zone->GetInstanceID() : 0; - m_pp.binds[bind_number].x = m_Position.x; - m_pp.binds[bind_number].y = m_Position.y; - m_pp.binds[bind_number].z = m_Position.z; - } else { - m_pp.binds[bind_number].zone_id = to_zone; - m_pp.binds[bind_number].instance_id = to_instance; - m_pp.binds[bind_number].x = location.x; - m_pp.binds[bind_number].y = location.y; - m_pp.binds[bind_number].z = location.z; + m_pp.binds[bind_number].zone_id = zone->GetZoneID(); + m_pp.binds[bind_number].instance_id = (zone->GetInstanceID() != 0 && zone->IsInstancePersistent())? zone->GetInstanceID() : 0; + m_pp.binds[bind_number].x = m_Position.x; + m_pp.binds[bind_number].y = m_Position.y; + m_pp.binds[bind_number].z = m_Position.z; + m_pp.binds[bind_number].heading = GetHeading(); } - database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[bind_number], bind_number); + else { + m_pp.binds[bind_number].zone_id = to_zone; + m_pp.binds[bind_number].instance_id = to_instance; + m_pp.binds[bind_number].x = location.x; + m_pp.binds[bind_number].y = location.y; + m_pp.binds[bind_number].z = location.z; + m_pp.binds[bind_number].heading = GetHeading(); + } + + database.SaveCharacterBinds(this); } void Client::SetBindPoint2(int bind_number, int to_zone, int to_instance, const glm::vec4 &location) @@ -929,7 +934,8 @@ void Client::SetBindPoint2(int bind_number, int to_zone, int to_instance, const m_pp.binds[bind_number].z = location.z; m_pp.binds[bind_number].heading = location.w; } - database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[bind_number], bind_number); + + database.SaveCharacterBinds(this); } void Client::GoToBind(uint8 bind_number) {