diff options
-rw-r--r-- | src/server/game/Entities/Object/ObjectGuid.cpp | 80 | ||||
-rw-r--r-- | src/server/game/Entities/Object/ObjectGuid.h | 34 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.cpp | 12 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_npc.cpp | 2 |
4 files changed, 108 insertions, 20 deletions
diff --git a/src/server/game/Entities/Object/ObjectGuid.cpp b/src/server/game/Entities/Object/ObjectGuid.cpp index 9a8bd07fe76..959be366409 100644 --- a/src/server/game/Entities/Object/ObjectGuid.cpp +++ b/src/server/game/Entities/Object/ObjectGuid.cpp @@ -17,14 +17,76 @@ #include "ObjectGuid.h" #include "ByteBuffer.h" +#include "Errors.h" #include "Log.h" +#include "Util.h" #include "World.h" -#include <sstream> -#include <iomanip> +#include <charconv> ObjectGuid const ObjectGuid::Empty = ObjectGuid(); -char const* ObjectGuid::GetTypeName(HighGuid high) +namespace +{ +struct ObjectGuidInfo +{ + struct FormatPadding { std::ptrdiff_t Value; constexpr operator std::ptrdiff_t() const { return Value; } }; + + template <std::ptrdiff_t Width> + static constexpr inline FormatPadding padding{ .Value = Width }; + static constexpr inline FormatPadding no_padding{ .Value = 0 }; + + struct FormatBase { int32 Value; constexpr operator int32() const { return Value; } }; + + static constexpr inline FormatBase dec{ 10 }; + static constexpr inline FormatBase hex{ 16 }; + + static fmt::appender AppendTypeName(fmt::format_context& ctx, std::string_view type) + { + return std::copy(type.begin(), type.end(), ctx.out()); + } + + template <FormatPadding Width, FormatBase Base> + static fmt::appender AppendComponent(fmt::format_context& ctx, uint64 component) + { + std::array<char, 20> buf; + auto [end, err] = std::to_chars(buf.data(), buf.data() + buf.size(), component, Base); + + ASSERT(err == std::errc(), "Failed to convert guid part to string"); + + if constexpr (Width != 0) + { + if (std::distance(buf.data(), end) < Width) + std::fill_n(ctx.out(), Width - std::distance(buf.data(), end), '0'); + } + + if constexpr (Base > 10) + return std::transform(buf.data(), end, ctx.out(), charToUpper); + else + return std::copy(buf.data(), end, ctx.out()); + } +}; +} + +template <typename FormatContext> +auto fmt::formatter<ObjectGuid>::format(ObjectGuid const& guid, FormatContext& ctx) const -> decltype(ctx.out()) +{ + ctx.advance_to(ObjectGuidInfo::AppendTypeName(ctx, "GUID Full: 0x")); + ctx.advance_to(ObjectGuidInfo::AppendComponent<ObjectGuidInfo::padding<16>, ObjectGuidInfo::hex>(ctx, guid.GetRawValue())); + ctx.advance_to(ObjectGuidInfo::AppendTypeName(ctx, " Type: ")); + ctx.advance_to(ObjectGuidInfo::AppendTypeName(ctx, guid.GetTypeName())); + if (uint32 entry = guid.GetEntry()) + { + ctx.advance_to(ObjectGuidInfo::AppendTypeName(ctx, guid.IsPet() ? " Pet number: " : " Entry: ")); + ctx.advance_to(ObjectGuidInfo::AppendComponent<ObjectGuidInfo::no_padding, ObjectGuidInfo::dec>(ctx, entry)); + } + ctx.advance_to(ObjectGuidInfo::AppendTypeName(ctx, " Low: ")); + ctx.advance_to(ObjectGuidInfo::AppendComponent<ObjectGuidInfo::no_padding, ObjectGuidInfo::dec>(ctx, guid.GetCounter())); + return ctx.out(); +} + +template TC_GAME_API fmt::appender fmt::formatter<ObjectGuid>::format<fmt::format_context>(ObjectGuid const&, format_context&) const; + +std::string_view ObjectGuid::GetTypeName(HighGuid high) { switch (high) { @@ -47,14 +109,12 @@ char const* ObjectGuid::GetTypeName(HighGuid high) std::string ObjectGuid::ToString() const { - std::ostringstream str; - str << "GUID Full: 0x" << std::hex << std::setw(16) << std::setfill('0') << _guid << std::dec; - str << " Type: " << GetTypeName(); - if (HasEntry()) - str << (IsPet() ? " Pet number: " : " Entry: ") << GetEntry() << " "; + return Trinity::StringFormat("{}", *this); +} - str << " Low: " << GetCounter(); - return str.str(); +std::string ObjectGuid::ToHexString() const +{ + return Trinity::StringFormat("0x{:016X}", _guid); } ObjectGuid ObjectGuid::Global(HighGuid type, LowType counter) diff --git a/src/server/game/Entities/Object/ObjectGuid.h b/src/server/game/Entities/Object/ObjectGuid.h index 9c09e75c56e..18fc2590554 100644 --- a/src/server/game/Entities/Object/ObjectGuid.h +++ b/src/server/game/Entities/Object/ObjectGuid.h @@ -24,6 +24,7 @@ #include <list> #include <memory> #include <set> +#include <stdexcept> #include <string> #include <type_traits> #include <unordered_set> @@ -216,9 +217,10 @@ class TC_GAME_API ObjectGuid bool operator==(ObjectGuid const& right) const = default; std::strong_ordering operator<=>(ObjectGuid const& right) const = default; - static char const* GetTypeName(HighGuid high); - char const* GetTypeName() const { return !IsEmpty() ? GetTypeName(GetHigh()) : "None"; } + static std::string_view GetTypeName(HighGuid high); + std::string_view GetTypeName() const { return !IsEmpty() ? GetTypeName(GetHigh()) : "None"; } std::string ToString() const; + std::string ToHexString() const; private: static bool HasEntry(HighGuid high) @@ -318,4 +320,32 @@ namespace std }; } +namespace fmt +{ +inline namespace v9 +{ +template <typename T, typename Char, typename Enable> +struct formatter; + +template <> +struct formatter<ObjectGuid, char, void> +{ + template <typename ParseContext> + constexpr auto parse(ParseContext& ctx) -> decltype(ctx.begin()) + { + auto begin = ctx.begin(), end = ctx.end(); + if (begin == end) + return begin; + + if (*begin != '}') + throw std::invalid_argument("invalid type specifier"); + + return begin; + } + + template <typename FormatContext> + auto format(ObjectGuid const& guid, FormatContext& ctx) const -> decltype(ctx.out()); +}; +} +} #endif // ObjectGuid_h__ diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 2950b72ce8e..15cb8e3830d 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -189,15 +189,13 @@ std::string const & WorldSession::GetPlayerName() const std::string WorldSession::GetPlayerInfo() const { - std::ostringstream ss; - - ss << "[Player: "; - if (!m_playerLoading && _player) - ss << _player->GetName() << ' ' << _player->GetGUID().ToString() << ", "; + if (_player) + return Trinity::StringFormat("[Player: {} {}, Account: {}]", _player->GetName(), _player->GetGUID(), GetAccountId()); - ss << "Account: " << GetAccountId() << "]"; + if (m_playerLoading) + return Trinity::StringFormat("[Player: Logging in, Account: {}]", GetAccountId()); - return ss.str(); + return Trinity::StringFormat("[Player: Account: {}]", GetAccountId()); } /// Get player guid if available. Use for logging purposes only diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index e85636f282d..9e8529f1cb8 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -1122,7 +1122,7 @@ public: continue; ObjectGuid guid = ObjectGuid::Create<HighGuid::Player>(pair.first); Player const* player = ObjectAccessor::FindConnectedPlayer(guid); - handler->PSendSysMessage(LANG_COMMAND_NPC_SHOWLOOT_SUBLABEL, player ? player->GetName() : Trinity::StringFormat("Offline player (GuidLow 0x{:08X})", pair.first), pair.second->size()); + handler->PSendSysMessage(LANG_COMMAND_NPC_SHOWLOOT_SUBLABEL, player ? player->GetName() : Trinity::StringFormat("Offline player ({})", pair.first.ToString()), pair.second->size()); for (auto it = pair.second->cbegin(); it != pair.second->cend(); ++it) { |