From 1f25a0ff92288e8ca18f995ebe5d23e649806c26 Mon Sep 17 00:00:00 2001 From: Shauren Date: Sun, 14 Jul 2024 13:45:05 +0200 Subject: Core/Entities: Make ObjectGuid formattable with fmt without using ToString() --- src/server/game/Entities/Object/ObjectGuid.cpp | 80 ++++++++++++++++++++++---- src/server/game/Entities/Object/ObjectGuid.h | 34 ++++++++++- src/server/game/Server/WorldSession.cpp | 12 ++-- src/server/scripts/Commands/cs_npc.cpp | 2 +- 4 files changed, 108 insertions(+), 20 deletions(-) (limited to 'src') 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 -#include +#include 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 + 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 + static fmt::appender AppendComponent(fmt::format_context& ctx, uint64 component) + { + std::array 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 +auto fmt::formatter::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::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(ctx, entry)); + } + ctx.advance_to(ObjectGuidInfo::AppendTypeName(ctx, " Low: ")); + ctx.advance_to(ObjectGuidInfo::AppendComponent(ctx, guid.GetCounter())); + return ctx.out(); +} + +template TC_GAME_API fmt::appender fmt::formatter::format(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 #include #include +#include #include #include #include @@ -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 +struct formatter; + +template <> +struct formatter +{ + template + 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 + 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(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) { -- cgit v1.2.3