diff options
| author | Machiavelli <machiavelli.trinity@gmail.com> | 2011-11-25 15:12:57 +0100 |
|---|---|---|
| committer | Machiavelli <machiavelli.trinity@gmail.com> | 2011-11-25 15:14:00 +0100 |
| commit | 72675d55d821e0648c53d53d78a1690276103c8c (patch) | |
| tree | ec9ea9de8b0fd3ad8392465018f6d1c53dfa79d4 /src/server/game | |
| parent | 4f738fe75a894d08d69c2d106025b13af74f1f19 (diff) | |
Core/DBLayer: Use prepared statements in Player::SaveToDB. Also split the function up between an INSERT part (new character creation) and UPDATE part (existing character).
Diffstat (limited to 'src/server/game')
| -rwxr-xr-x | src/server/game/Entities/Player/Player.cpp | 352 | ||||
| -rwxr-xr-x | src/server/game/Entities/Player/Player.h | 2 | ||||
| -rwxr-xr-x | src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp | 2 |
3 files changed, 215 insertions, 141 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index fce50bc37d2..2fe2cb4de61 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -279,10 +279,8 @@ uint32 PlayerTaxi::GetCurrentTaxiPath() const std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi) { - ss << '\''; for (uint8 i = 0; i < TaxiMaskSize; ++i) ss << taxi.m_taximask[i] << ' '; - ss << '\''; return ss; } @@ -18256,7 +18254,7 @@ bool Player::_LoadHomeBind(PreparedQueryResult result) /*** SAVE SYSTEM ***/ /*********************************************************/ -void Player::SaveToDB() +void Player::SaveToDB(bool create /*=false*/) { // delay auto save at any saves (manual, in code, or autosave) m_nextSave = sWorld->getIntConfig(CONFIG_INTERVAL_SAVE); @@ -18274,156 +18272,232 @@ void Player::SaveToDB() sLog->outDebug(LOG_FILTER_UNITS, "The value of player %s at save: ", m_name.c_str()); outDebugValues(); - std::string sql_name = m_name; - CharacterDatabase.EscapeString(sql_name); + PreparedStatement* stmt = NULL; + uint16 index = 0; - std::ostringstream ss; - ss << "REPLACE INTO characters (guid, account, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, " - "map, instance_id, instance_mode_mask, position_x, position_y, position_z, orientation, " - "taximask, online, cinematic, " - "totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, " - "trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, " - "death_expire_time, taxi_path, arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, " - "todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk, health, power1, power2, power3, " - "power4, power5, power6, power7, latency, speccount, activespec, exploredZones, equipmentCache, ammoId, knownTitles, actionBars, grantableLevels) VALUES (" - << GetGUIDLow() << ',' - << GetSession()->GetAccountId() << ", '" - << sql_name << "', " - << uint32(getRace()) << ',' - << uint32(getClass()) << ',' - << uint32(getGender()) << ',' - << uint32(getLevel()) << ',' - << GetUInt32Value(PLAYER_XP) << ',' - << GetMoney() << ',' - << GetUInt32Value(PLAYER_BYTES) << ',' - << GetUInt32Value(PLAYER_BYTES_2) << ',' - << GetUInt32Value(PLAYER_FLAGS) << ','; - - if (!IsBeingTeleported()) - { - ss << GetMapId() << ',' - << (uint32)GetInstanceId() << ',' - << uint32(uint8(GetDungeonDifficulty()) | uint8(GetRaidDifficulty()) << 4) << ',' - << finiteAlways(GetPositionX()) << ',' - << finiteAlways(GetPositionY()) << ',' - << finiteAlways(GetPositionZ()) << ',' - << finiteAlways(GetOrientation()) << ','; - } - else + if (create) { - ss << GetTeleportDest().GetMapId() << ',' - << (uint32)0 << ',' - << uint32(uint8(GetDungeonDifficulty()) | uint8(GetRaidDifficulty()) << 4) << ',' - << finiteAlways(GetTeleportDest().GetPositionX()) << ',' - << finiteAlways(GetTeleportDest().GetPositionY()) << ',' - << finiteAlways(GetTeleportDest().GetPositionZ()) << ',' - << finiteAlways(GetTeleportDest().GetOrientation()) << ','; - } - - ss << m_taxi << ','; // string with TaxiMaskSize numbers - - ss << (IsInWorld() ? 1 : 0) << ','; - - ss << uint32(m_cinematic) << ','; + //! Insert query + //! TO DO: Filter out more redundant fields that can take their default value at player create + stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_CHARACTER); + stmt->setUInt32(index++, GetGUIDLow()); + stmt->setUInt32(index++, GetSession()->GetAccountId()); + stmt->setString(index++, GetName()); + stmt->setUInt8(index++, getRace()); + stmt->setUInt8(index++, getClass()); + stmt->setUInt8(index++, getGender()); + stmt->setUInt8(index++, getLevel()); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_XP)); + stmt->setUInt32(index++, GetMoney()); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_BYTES)); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_BYTES_2)); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_FLAGS)); + stmt->setUInt16(index++, (uint16)GetMapId()); + stmt->setUInt32(index++ , (uint32)GetInstanceId()); + stmt->setUInt8(index++, (uint8(GetDungeonDifficulty()) | uint8(GetRaidDifficulty()) << 4)); + stmt->setFloat(index++, finiteAlways(GetPositionX())); + stmt->setFloat(index++, finiteAlways(GetPositionY())); + stmt->setFloat(index++, finiteAlways(GetPositionZ())); + stmt->setFloat(index++, finiteAlways(GetOrientation())); + + std::ostringstream ss; + ss << m_taxi; + stmt->setString(index++, ss.str()); + stmt->setUInt8(index++, m_cinematic); + stmt->setUInt32(index++, m_Played_time[PLAYED_TIME_TOTAL]); + stmt->setUInt32(index++, m_Played_time[PLAYED_TIME_LEVEL]); + stmt->setFloat(index++, finiteAlways(m_rest_bonus)); + stmt->setUInt32(index++, uint32(time(NULL))); + stmt->setUInt8(index++, (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0)); + //save, far from tavern/city + //save, but in tavern/city + stmt->setUInt32(index++, m_resetTalentsCost); + stmt->setUInt32(index++, m_resetTalentsTime); + stmt->setUInt16(index++, (uint16)m_ExtraFlags); + stmt->setUInt8(index++, m_stableSlots); + stmt->setUInt16(index++, (uint16)m_atLoginFlags); + stmt->setUInt16(index++, GetZoneId()); + stmt->setUInt32(index++, m_deathExpireTime); + + ss.str().clear(); + ss << m_taxi.SaveTaxiDestinationsToString(); + + stmt->setString(index++, ss.str()); + stmt->setUInt32(index++, GetArenaPoints()); + stmt->setUInt32(index++, GetHonorPoints()); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION)); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION)); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS)); + stmt->setUInt16(index++, GetUInt16Value(PLAYER_FIELD_KILLS, 0)); + stmt->setUInt16(index++, GetUInt16Value(PLAYER_FIELD_KILLS, 1)); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_CHOSEN_TITLE)); + stmt->setUInt64(index++, GetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES)); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX)); + stmt->setUInt16(index++, (uint16)(GetUInt32Value(PLAYER_BYTES_3) & 0xFFFE)); + stmt->setUInt32(index++, GetHealth()); + + for (uint32 i = 0; i < MAX_POWERS; ++i) + stmt->setUInt32(index++, GetPower(Powers(i))); + + stmt->setUInt32(index++, GetSession()->GetLatency()); + + stmt->setUInt8(index++, m_specsCount); + stmt->setUInt8(index++, m_activeSpec); + + ss.str().clear(); + for (uint32 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i) + ss << GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + i) << ' '; + stmt->setString(index++, ss.str()); + + ss.str().clear(); + // cache equipment... + for (uint32 i = 0; i < EQUIPMENT_SLOT_END * 2; ++i) + ss << GetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + i) << ' '; + stmt->setString(index++, ss.str()); + + ss.str().clear(); + // ...and bags for enum opcode + for (uint32 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) + { + if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) + ss << item->GetEntry(); + else + ss << '0'; + ss << " 0 "; + } - ss << m_Played_time[PLAYED_TIME_TOTAL] << ','; - ss << m_Played_time[PLAYED_TIME_LEVEL] << ','; + stmt->setString(index++, ss.str()); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_AMMO_ID)); - ss << finiteAlways(m_rest_bonus) << ','; - ss << uint32(time(NULL)) << ','; - ss << (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0) << ','; - //save, far from tavern/city - //save, but in tavern/city - ss << m_resetTalentsCost << ','; - ss << uint32(m_resetTalentsTime) << ','; + ss.str().clear(); + for (uint32 i = 0; i < KNOWN_TITLES_SIZE*2; ++i) + ss << GetUInt32Value(PLAYER__FIELD_KNOWN_TITLES + i); - ss << finiteAlways(m_movementInfo.t_pos.GetPositionX()) << ','; - ss << finiteAlways(m_movementInfo.t_pos.GetPositionY()) << ','; - ss << finiteAlways(m_movementInfo.t_pos.GetPositionZ()) << ','; - ss << finiteAlways(m_movementInfo.t_pos.GetOrientation()) << ','; - if (m_transport) - ss << m_transport->GetGUIDLow(); + stmt->setString(index++, ss.str()); + stmt->setUInt8(index++, GetByteValue(PLAYER_FIELD_BYTES, 2)); + stmt->setUInt32(index++, m_grantableLevels); + } else - ss << '0'; - ss << ','; - - ss << m_ExtraFlags << ','; - - ss << uint32(m_stableSlots) << ','; // to prevent save uint8 as char - - ss << uint32(m_atLoginFlags) << ','; - - ss << GetZoneId() << ','; - - ss << uint32(m_deathExpireTime) << ", '"; - - ss << m_taxi.SaveTaxiDestinationsToString() << "', "; - - ss << GetArenaPoints() << ','; - - ss << GetHonorPoints() << ','; - - ss << GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION) << ','; - - ss << GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION) << ','; - - ss << GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS) << ','; - - ss << GetUInt16Value(PLAYER_FIELD_KILLS, 0) << ','; - - ss << GetUInt16Value(PLAYER_FIELD_KILLS, 1) << ','; - - ss << GetUInt32Value(PLAYER_CHOSEN_TITLE) << ','; - - ss << GetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES) << ','; - - ss << GetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX) << ','; - - ss << (uint16)(GetUInt32Value(PLAYER_BYTES_3) & 0xFFFE) << ','; - - ss << GetHealth(); - - for (uint32 i = 0; i < MAX_POWERS; ++i) - ss << ',' << GetPower(Powers(i)); - ss << ','; - ss << GetSession()->GetLatency(); - ss << ','; - ss << uint32(m_specsCount); - ss << ','; - ss << uint32(m_activeSpec) << ", '"; - for (uint32 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i) - ss << GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + i) << ' '; - - // cache equipment... - ss << "', '"; - for (uint32 i = 0; i < EQUIPMENT_SLOT_END * 2; ++i) - ss << GetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + i) << ' '; - - // ...and bags for enum opcode - for (uint32 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) { - if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) - ss << item->GetEntry(); + // Update query + stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHARACTER); + stmt->setString(index++, GetName()); + stmt->setUInt8(index++, getRace()); + stmt->setUInt8(index++, getClass()); + stmt->setUInt8(index++, getGender()); + stmt->setUInt8(index++, getLevel()); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_XP)); + stmt->setUInt32(index++, GetMoney()); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_BYTES)); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_BYTES_2)); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_FLAGS)); + + if (!IsBeingTeleported()) + { + stmt->setUInt16(index++, (uint16)GetMapId()); + stmt->setUInt32(index++, (uint32)GetInstanceId()); + stmt->setUInt8(index++, (uint8(GetDungeonDifficulty()) | uint8(GetRaidDifficulty()) << 4)); + stmt->setFloat(index++, finiteAlways(GetPositionX())); + stmt->setFloat(index++, finiteAlways(GetPositionY())); + stmt->setFloat(index++, finiteAlways(GetPositionZ())); + stmt->setFloat(index++, finiteAlways(GetOrientation())); + } else - ss << '0'; - ss << " 0 "; - } + { + stmt->setUInt16(index++, (uint16)GetTeleportDest().GetMapId()); + stmt->setUInt32(index++, (uint32)0); + stmt->setUInt8(index++, (uint8(GetDungeonDifficulty()) | uint8(GetRaidDifficulty()) << 4)); + stmt->setFloat(index++, finiteAlways(GetTeleportDest().GetPositionX())); + stmt->setFloat(index++, finiteAlways(GetTeleportDest().GetPositionY())); + stmt->setFloat(index++, finiteAlways(GetTeleportDest().GetPositionZ())); + stmt->setFloat(index++, finiteAlways(GetTeleportDest().GetOrientation())); + } + + std::ostringstream ss; + ss << m_taxi; + stmt->setString(index++, ss.str()); + stmt->setUInt8(index++, m_cinematic); + stmt->setUInt32(index++, m_Played_time[PLAYED_TIME_TOTAL]); + stmt->setUInt32(index++, m_Played_time[PLAYED_TIME_LEVEL]); + stmt->setFloat(index++, finiteAlways(m_rest_bonus)); + stmt->setUInt32(index++, uint32(time(NULL))); + stmt->setUInt8(index++, (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0)); + //save, far from tavern/city + //save, but in tavern/city + stmt->setUInt32(index++, m_resetTalentsCost); + stmt->setUInt32(index++, m_resetTalentsTime); + stmt->setUInt16(index++, (uint16)m_ExtraFlags); + stmt->setUInt8(index++, m_stableSlots); + stmt->setUInt16(index++, (uint16)m_atLoginFlags); + stmt->setUInt16(index++, GetZoneId()); + stmt->setUInt32(index++, m_deathExpireTime); + + ss.str().clear(); + ss << m_taxi.SaveTaxiDestinationsToString(); + + stmt->setString(index++, ss.str()); + stmt->setUInt32(index++, GetArenaPoints()); + stmt->setUInt32(index++, GetHonorPoints()); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION)); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION)); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS)); + stmt->setUInt16(index++, GetUInt16Value(PLAYER_FIELD_KILLS, 0)); + stmt->setUInt16(index++, GetUInt16Value(PLAYER_FIELD_KILLS, 1)); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_CHOSEN_TITLE)); + stmt->setUInt64(index++, GetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES)); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX)); + stmt->setUInt16(index++, (uint16)(GetUInt32Value(PLAYER_BYTES_3) & 0xFFFE)); + stmt->setUInt32(index++, GetHealth()); + + for (uint32 i = 0; i < MAX_POWERS; ++i) + stmt->setUInt32(index++, GetPower(Powers(i))); + + stmt->setUInt32(index++, GetSession()->GetLatency()); + + stmt->setUInt8(index++, m_specsCount); + stmt->setUInt8(index++, m_activeSpec); + + ss.str().clear(); + for (uint32 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i) + ss << GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + i) << ' '; + stmt->setString(index++, ss.str()); + + ss.str().clear(); + // cache equipment... + for (uint32 i = 0; i < EQUIPMENT_SLOT_END * 2; ++i) + ss << GetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + i) << ' '; + stmt->setString(index++, ss.str()); + + ss.str().clear(); + // ...and bags for enum opcode + for (uint32 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) + { + if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) + ss << item->GetEntry(); + else + ss << '0'; + ss << " 0 "; + } - ss << "',"; + stmt->setString(index++, ss.str()); + stmt->setUInt32(index++, GetUInt32Value(PLAYER_AMMO_ID)); - ss << GetUInt32Value(PLAYER_AMMO_ID) << ", '"; - for (uint32 i = 0; i < KNOWN_TITLES_SIZE*2; ++i) - ss << GetUInt32Value(PLAYER__FIELD_KNOWN_TITLES + i) << ' '; + ss.str().clear(); + for (uint32 i = 0; i < KNOWN_TITLES_SIZE*2; ++i) + ss << GetUInt32Value(PLAYER__FIELD_KNOWN_TITLES + i); - ss << "',"; - ss << uint32(GetByteValue(PLAYER_FIELD_BYTES, 2)); - ss << ","; - ss << uint32(m_grantableLevels); - ss << ')'; + stmt->setString(index++, ss.str()); + stmt->setUInt8(index++, GetByteValue(PLAYER_FIELD_BYTES, 2)); + stmt->setUInt32(index++, m_grantableLevels); + + stmt->setUInt8(index++, IsInWorld() ? 1 : 0); + // Index + stmt->setUInt32(index++, GetGUIDLow()); + } SQLTransaction trans = CharacterDatabase.BeginTransaction(); - trans->Append(ss.str().c_str()); + trans->Append(stmt); if (m_mailsUpdated) //save mails only when needed _SaveMail(trans); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index da58a7dadbf..3d8b561c1d9 100755 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1531,7 +1531,7 @@ class Player : public Unit, public GridObject<Player> /*** SAVE SYSTEM ***/ /*********************************************************/ - void SaveToDB(); + void SaveToDB(bool create = false); void SaveInventoryAndGoldToDB(SQLTransaction& trans); // fast save function for item/money cheating preventing void SaveGoldToDB(SQLTransaction& trans); diff --git a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp index 1037bf1e9f2..83b9ab048ad 100755 --- a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp @@ -658,7 +658,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte newChar.SetAtLoginFlag(AT_LOGIN_FIRST); // First login // Player created, save it now - newChar.SaveToDB(); + newChar.SaveToDB(true); createInfo->CharCount += 1; SQLTransaction trans = LoginDatabase.BeginTransaction(); |
