/*
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
#include "ObjectGuid.h"
#include "ByteBuffer.h"
#include "Errors.h"
#include "Hash.h"
#include "RealmList.h"
#include "StringFormat.h"
#include "Util.h"
#include
static_assert(sizeof(ObjectGuid) == sizeof(uint64) * 2, "ObjectGuid must be exactly 16 bytes");
namespace
{
struct ObjectGuidInfo
{
using FormatFunction = fmt::appender(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid);
using ParseFunction = ObjectGuid(HighGuid type, std::string_view guidString);
std::string_view Names[AsUnderlyingType(HighGuid::Count)];
std::array ClientFormatFunction;
std::array ClientParseFunction;
static std::string Format(ObjectGuid const& guid)
{
return Trinity::StringFormat("{}", guid);
}
ObjectGuid Parse(std::string_view guidString) const
{
std::size_t typeEnd = guidString.find('-');
if (typeEnd == std::string::npos)
{
if (guidString == "0000000000000000")
return ObjectGuid::Empty;
return ObjectGuid::FromStringFailed;
}
std::string_view typeStr = guidString.substr(0, typeEnd);
guidString.remove_prefix(typeEnd + 1);
// find correct parser for type name
for (int32 type = 0; type < AsUnderlyingType(HighGuid::Count); ++type)
if (typeStr == Names[type])
return ClientParseFunction[type](HighGuid(type), guidString);
return ObjectGuid::FromStringFailed;
}
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::ranges::copy(type, ctx.out()).out;
}
template
static fmt::appender AppendComponent(fmt::format_context& ctx, uint64 component)
{
*ctx.out() = '-';
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::ptrdiff_t written = std::distance(buf.data(), end); written < Width)
std::ranges::fill_n(ctx.out(), Width - written, '0');
}
if constexpr (Base > 10)
return std::ranges::transform(buf.data(), end, ctx.out(), charToUpper).out;
else
return std::ranges::copy(buf.data(), end, ctx.out()).out;
}
static fmt::appender AppendComponent(fmt::format_context& ctx, std::string_view component)
{
*ctx.out() = '-';
return std::ranges::copy(component, ctx.out()).out;
}
template
static bool ParseComponent(std::string_view& input, T* component)
{
auto [end, err] = std::from_chars(input.data(), input.data() + input.length(), *component, Base);
if (err != std::errc())
return false;
input.remove_prefix(end - input.data());
if (!input.empty())
{
if (input[0] != '-')
return false;
input.remove_prefix(1);
}
return true;
}
static bool ParseDone(std::string_view const& sv) { return sv.empty(); }
static fmt::appender FormatNull(fmt::format_context& ctx, std::string_view /*typeName*/, ObjectGuid const& /*guid*/)
{
return std::ranges::fill_n(ctx.out(), 16, '0');
}
static ObjectGuid ParseNull(HighGuid, std::string_view)
{
return ObjectGuid::Empty;
}
static constexpr std::array UniqNames =
{
"",
"WOWGUID_UNIQUE_PROBED_DELETE",
"WOWGUID_UNIQUE_JAM_TEMP",
"WOWGUID_TO_STRING_FAILED",
"WOWGUID_FROM_STRING_FAILED",
"WOWGUID_UNIQUE_SERVER_SELF",
"WOWGUID_UNIQUE_MAGIC_SELF",
"WOWGUID_UNIQUE_MAGIC_PET",
"WOWGUID_UNIQUE_INVALID_TRANSPORT",
"WOWGUID_UNIQUE_AMMO_ID",
"WOWGUID_SPELL_TARGET_TRADE_ITEM",
"WOWGUID_SCRIPT_TARGET_INVALID",
"WOWGUID_SCRIPT_TARGET_NONE",
"",
"WOWGUID_FAKE_MODERATOR",
"",
"",
"WOWGUID_UNIQUE_ACCOUNT_OBJ_INITIALIZATION",
"",
"WOWGUID_PENDING_PERMANENT_CHARACTER_ASSIGNMENT"
};
static fmt::appender FormatUniq(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid)
{
ObjectGuid::LowType id = guid.GetCounter();
if (id >= UniqNames.size() || UniqNames[id].empty())
id = 3;
ctx.advance_to(AppendTypeName(ctx, typeName));
ctx.advance_to(AppendComponent(ctx, UniqNames[id]));
return ctx.out();
}
static ObjectGuid ParseUniq(HighGuid /*type*/, std::string_view guidString)
{
for (std::size_t id = 0; id < UniqNames.size(); ++id)
{
if (UniqNames[id].empty())
continue;
if (guidString == UniqNames[id])
return ObjectGuidFactory::CreateUniq(id);
}
return ObjectGuid::FromStringFailed;
}
static fmt::appender FormatPlayer(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid)
{
ctx.advance_to(AppendTypeName(ctx, typeName));
ctx.advance_to(AppendComponent(ctx, guid.GetRealmId()));
ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0)));
return ctx.out();
}
static ObjectGuid ParsePlayer(HighGuid /*type*/, std::string_view guidString)
{
uint32 realmId = 0;
uint64 dbId = UI64LIT(0);
if (!ParseComponent(guidString, &realmId)
|| !ParseComponent(guidString, &dbId)
|| !ParseDone(guidString))
return ObjectGuid::FromStringFailed;
return ObjectGuidFactory::CreatePlayer(realmId, dbId);
}
static fmt::appender FormatItem(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid)
{
ctx.advance_to(AppendTypeName(ctx, typeName));
ctx.advance_to(AppendComponent(ctx, guid.GetRealmId()));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 18 & 0xFFFFFF));
ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0)));
return ctx.out();
}
static ObjectGuid ParseItem(HighGuid /*type*/, std::string_view guidString)
{
uint32 realmId = 0;
uint32 arg1 = 0;
uint64 dbId = UI64LIT(0);
if (!ParseComponent(guidString, &realmId)
|| !ParseComponent(guidString, &arg1)
|| !ParseComponent(guidString, &dbId)
|| !ParseDone(guidString))
return ObjectGuid::FromStringFailed;
return ObjectGuidFactory::CreateItem(realmId, dbId);
}
static fmt::appender FormatWorldObject(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid)
{
ctx.advance_to(AppendTypeName(ctx, typeName));
ctx.advance_to(AppendComponent(ctx, guid.GetSubType()));
ctx.advance_to(AppendComponent(ctx, guid.GetRealmId()));
ctx.advance_to(AppendComponent(ctx, guid.GetMapId()));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(0) >> 40 & 0xFFFFFF));
ctx.advance_to(AppendComponent(ctx, guid.GetEntry()));
ctx.advance_to(AppendComponent, hex>(ctx, guid.GetCounter()));
return ctx.out();
}
static ObjectGuid ParseWorldObject(HighGuid type, std::string_view guidString)
{
uint8 subType = 0;
uint32 realmId = 0;
uint16 mapId = 0;
uint32 serverId = 0;
uint32 id = 0;
uint64 counter = UI64LIT(0);
if (!ParseComponent(guidString, &subType)
|| !ParseComponent(guidString, &realmId)
|| !ParseComponent(guidString, &mapId)
|| !ParseComponent(guidString, &serverId)
|| !ParseComponent(guidString, &id)
|| !ParseComponent(guidString, &counter)
|| !ParseDone(guidString))
return ObjectGuid::FromStringFailed;
return ObjectGuidFactory::CreateWorldObject(type, subType, realmId, mapId, serverId, id, counter);
}
static fmt::appender FormatTransport(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid)
{
ctx.advance_to(AppendTypeName(ctx, typeName));
ctx.advance_to(AppendComponent(ctx, guid.GetEntry()));
ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0)));
return ctx.out();
}
static ObjectGuid ParseTransport(HighGuid type, std::string_view guidString)
{
uint32 id = 0;
uint32 counter = 0;
if (!ParseComponent(guidString, &id)
|| !ParseComponent(guidString, &counter)
|| !ParseDone(guidString))
return ObjectGuid::FromStringFailed;
return ObjectGuidFactory::CreateTransport(type, counter);
}
static fmt::appender FormatClientActor(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid)
{
ctx.advance_to(AppendTypeName(ctx, typeName));
ctx.advance_to(AppendComponent(ctx, guid.GetRealmId()));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 26 & 0xFFFFFF));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(0) & 0xFFFFFFFF));
return ctx.out();
}
static ObjectGuid ParseClientActor(HighGuid /*type*/, std::string_view guidString)
{
uint16 ownerType = 0;
uint16 ownerId = 0;
uint32 counter = 0;
if (!ParseComponent(guidString, &ownerType)
|| !ParseComponent(guidString, &ownerId)
|| !ParseComponent(guidString, &counter)
|| !ParseDone(guidString))
return ObjectGuid::FromStringFailed;
return ObjectGuidFactory::CreateClientActor(ownerType, ownerId, counter);
}
static fmt::appender FormatChatChannel(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid)
{
uint32 builtIn = (guid.GetRawValue(1) >> 25) & 0x1;
uint32 trade = (guid.GetRawValue(1) >> 24) & 0x1;
uint32 zoneId = (guid.GetRawValue(1) >> 10) & 0x3FFF;
uint32 factionGroupMask = (guid.GetRawValue(1) >> 4) & 0x3F;
ctx.advance_to(AppendTypeName(ctx, typeName));
ctx.advance_to(AppendComponent(ctx, guid.GetRealmId()));
ctx.advance_to(AppendComponent(ctx, builtIn));
ctx.advance_to(AppendComponent(ctx, trade));
ctx.advance_to(AppendComponent(ctx, zoneId));
ctx.advance_to(AppendComponent(ctx, factionGroupMask));
ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0)));
return ctx.out();
}
static ObjectGuid ParseChatChannel(HighGuid /*type*/, std::string_view guidString)
{
uint32 realmId = 0;
uint32 builtIn = 0;
uint32 trade = 0;
uint16 zoneId = 0;
uint8 factionGroupMask = 0;
uint64 id = UI64LIT(0);
if (!ParseComponent(guidString, &realmId)
|| !ParseComponent(guidString, &builtIn)
|| !ParseComponent(guidString, &trade)
|| !ParseComponent(guidString, &zoneId)
|| !ParseComponent(guidString, &factionGroupMask)
|| !ParseComponent(guidString, &id)
|| !ParseDone(guidString))
return ObjectGuid::FromStringFailed;
return ObjectGuidFactory::CreateChatChannel(realmId, builtIn != 0, trade != 0, zoneId, factionGroupMask, id);
}
static fmt::appender FormatGlobal(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid)
{
ctx.advance_to(AppendTypeName(ctx, typeName));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) & 0x3FFFFFFFFFFFFFF));
ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0)));
return ctx.out();
}
static ObjectGuid ParseGlobal(HighGuid type, std::string_view guidString)
{
uint64 dbIdHigh = UI64LIT(0);
uint64 dbIdLow = UI64LIT(0);
if (!ParseComponent(guidString, &dbIdHigh)
|| !ParseComponent(guidString, &dbIdLow)
|| !ParseDone(guidString))
return ObjectGuid::FromStringFailed;
return ObjectGuidFactory::CreateGlobal(type, dbIdHigh, dbIdLow);
}
static fmt::appender FormatGuild(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid)
{
ctx.advance_to(AppendTypeName(ctx, typeName));
ctx.advance_to(AppendComponent(ctx, guid.GetRealmId()));
ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0)));
return ctx.out();
}
static ObjectGuid ParseGuild(HighGuid type, std::string_view guidString)
{
uint32 realmId = 0;
uint64 dbId = UI64LIT(0);
if (!ParseComponent(guidString, &realmId)
|| !ParseComponent(guidString, &dbId)
|| !ParseDone(guidString))
return ObjectGuid::FromStringFailed;
return ObjectGuidFactory::CreateGuild(type, realmId, dbId);
}
static fmt::appender FormatMobileSession(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid)
{
ctx.advance_to(AppendTypeName(ctx, typeName));
ctx.advance_to(AppendComponent(ctx, guid.GetRealmId()));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 33 & 0x1FF));
ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0)));
return ctx.out();
}
static ObjectGuid ParseMobileSession(HighGuid /*type*/, std::string_view guidString)
{
uint32 realmId = 0;
uint16 arg1 = 0;
uint64 counter = UI64LIT(0);
if (!ParseComponent(guidString, &realmId)
|| !ParseComponent(guidString, &arg1)
|| !ParseComponent(guidString, &counter)
|| !ParseDone(guidString))
return ObjectGuid::FromStringFailed;
return ObjectGuidFactory::CreateMobileSession(realmId, arg1, counter);
}
static fmt::appender FormatWebObj(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid)
{
ctx.advance_to(AppendTypeName(ctx, typeName));
ctx.advance_to(AppendComponent(ctx, guid.GetRealmId()));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 37 & 0x1F));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 35 & 0x3));
ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0)));
return ctx.out();
}
static ObjectGuid ParseWebObj(HighGuid /*type*/, std::string_view guidString)
{
uint32 realmId = 0;
uint8 arg1 = 0;
uint8 arg2 = 0;
uint64 counter = UI64LIT(0);
if (!ParseComponent(guidString, &realmId)
|| !ParseComponent(guidString, &arg1)
|| !ParseComponent(guidString, &arg2)
|| !ParseComponent(guidString, &counter)
|| !ParseDone(guidString))
return ObjectGuid::FromStringFailed;
return ObjectGuidFactory::CreateWebObj(realmId, arg1, arg2, counter);
}
static fmt::appender FormatLFGObject(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid)
{
ctx.advance_to(AppendTypeName(ctx, typeName));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 54 & 0xF));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 50 & 0xF));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 46 & 0xF));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 38 & 0xFF));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 37 & 0x1));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 35 & 0x3));
ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0)));
return ctx.out();
}
static ObjectGuid ParseLFGObject(HighGuid /*type*/, std::string_view guidString)
{
uint8 arg1 = 0;
uint8 arg2 = 0;
uint8 arg3 = 0;
uint8 arg4 = 0;
uint8 arg5 = 0;
uint8 arg6 = 0;
uint64 counter = UI64LIT(0);
if (!ParseComponent(guidString, &arg1)
|| !ParseComponent(guidString, &arg2)
|| !ParseComponent(guidString, &arg3)
|| !ParseComponent(guidString, &arg4)
|| !ParseComponent(guidString, &arg5)
|| !ParseComponent(guidString, &arg6)
|| !ParseComponent(guidString, &counter)
|| !ParseDone(guidString))
return ObjectGuid::FromStringFailed;
return ObjectGuidFactory::CreateLFGObject(arg1, arg2, arg3, arg4, arg5 != 0, arg6, counter);
}
static fmt::appender FormatLFGList(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid)
{
ctx.advance_to(AppendTypeName(ctx, typeName));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 54 & 0xF));
ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0)));
return ctx.out();
}
static ObjectGuid ParseLFGList(HighGuid /*type*/, std::string_view guidString)
{
uint8 arg1 = 0;
uint64 counter = UI64LIT(0);
if (!ParseComponent(guidString, &arg1)
|| !ParseComponent(guidString, &counter)
|| !ParseDone(guidString))
return ObjectGuid::FromStringFailed;
return ObjectGuidFactory::CreateLFGList(arg1, counter);
}
static fmt::appender FormatClient(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid)
{
ctx.advance_to(AppendTypeName(ctx, typeName));
ctx.advance_to(AppendComponent(ctx, guid.GetRealmId()));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) >> 10 & 0xFFFFFFFF));
ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0)));
return ctx.out();
}
static ObjectGuid ParseClient(HighGuid type, std::string_view guidString)
{
uint32 realmId = 0;
uint32 arg1 = 0;
uint64 counter = UI64LIT(0);
if (!ParseComponent(guidString, &realmId)
|| !ParseComponent(guidString, &arg1)
|| !ParseComponent(guidString, &counter)
|| !ParseDone(guidString))
return ObjectGuid::FromStringFailed;
return ObjectGuidFactory::CreateClient(type, realmId, arg1, counter);
}
static fmt::appender FormatClubFinder(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid)
{
uint32 type = uint32(guid.GetRawValue(1) >> 33) & 0xFF;
uint32 clubFinderId = uint32(guid.GetRawValue(1)) & 0xFFFFFFFF;
ctx.advance_to(AppendTypeName(ctx, typeName));
ctx.advance_to(AppendComponent(ctx, type));
ctx.advance_to(AppendComponent(ctx, clubFinderId));
switch (type)
{
case 0: // club
ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0))); // clubId
break;
case 1: // guild
ctx.advance_to(AppendComponent(ctx, guid.GetRealmId()));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(0))); // guildId
break;
default:
break;
}
return ctx.out();
}
static ObjectGuid ParseClubFinder(HighGuid /*type*/, std::string_view guidString)
{
uint8 type = 0;
uint32 clubFinderId = 0;
uint32 realmId = 0;
uint64 dbId = UI64LIT(0);
if (!ParseComponent(guidString, &type)
|| !ParseComponent(guidString, &clubFinderId))
return ObjectGuid::FromStringFailed;
switch (type)
{
case 0: // club
if (!ParseComponent(guidString, &dbId))
return ObjectGuid::FromStringFailed;
break;
case 1: // guild
if (!ParseComponent(guidString, &realmId)
|| !ParseComponent(guidString, &dbId))
return ObjectGuid::FromStringFailed;
break;
default:
return ObjectGuid::FromStringFailed;
}
if (!ParseDone(guidString))
return ObjectGuid::FromStringFailed;
return ObjectGuidFactory::CreateClubFinder(realmId, type, clubFinderId, dbId);
}
static fmt::appender FormatToolsClient(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid)
{
ctx.advance_to(AppendTypeName(ctx, typeName));
ctx.advance_to(AppendComponent(ctx, guid.GetMapId()));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(0) >> 40 & 0xFFFFFF));
ctx.advance_to(AppendComponent, hex>(ctx, guid.GetCounter()));
return ctx.out();
}
static ObjectGuid ParseToolsClient(HighGuid /*type*/, std::string_view guidString)
{
uint16 mapId = 0;
uint32 serverId = 0;
uint64 counter = UI64LIT(0);
if (!ParseComponent(guidString, &mapId)
|| !ParseComponent(guidString, &serverId)
|| !ParseComponent(guidString, &counter)
|| !ParseDone(guidString))
return ObjectGuid::FromStringFailed;
return ObjectGuidFactory::CreateToolsClient(mapId, serverId, counter);
}
static fmt::appender FormatWorldLayer(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid)
{
ctx.advance_to(AppendTypeName(ctx, typeName));
ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(1) >> 10 & 0xFFFFFFFF));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(1) & 0x1FF));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(0) >> 24 & 0xFF));
ctx.advance_to(AppendComponent(ctx, guid.GetRawValue(0) & 0x7FFFFF));
return ctx.out();
}
static ObjectGuid ParseWorldLayer(HighGuid /*type*/, std::string_view guidString)
{
uint32 arg1 = 0;
uint16 arg2 = 0;
uint8 arg3 = 0;
uint32 arg4 = 0;
if (!ParseComponent(guidString, &arg1)
|| !ParseComponent(guidString, &arg2)
|| !ParseComponent(guidString, &arg3)
|| !ParseComponent(guidString, &arg4)
|| !ParseDone(guidString))
return ObjectGuid::FromStringFailed;
return ObjectGuidFactory::CreateWorldLayer(arg1, arg2, arg3, arg4);
}
static fmt::appender FormatLMMLobby(fmt::format_context& ctx, std::string_view typeName, ObjectGuid const& guid)
{
ctx.advance_to(AppendTypeName(ctx, typeName));
ctx.advance_to(AppendComponent(ctx, guid.GetRealmId()));
ctx.advance_to(AppendComponent(ctx, uint32(guid.GetRawValue(1) >> 26) & 0xFFFFFF));
ctx.advance_to(AppendComponent(ctx, uint32(guid.GetRawValue(1) >> 18) & 0xFF));
ctx.advance_to(AppendComponent(ctx, uint32(guid.GetRawValue(1) >> 10) & 0xFF));
ctx.advance_to(AppendComponent, hex>(ctx, guid.GetRawValue(0)));
return ctx.out();
}
static ObjectGuid ParseLMMLobby(HighGuid /*type*/, std::string_view guidString)
{
uint32 realmId = 0;
uint32 arg2 = 0;
uint8 arg3 = 0;
uint8 arg4 = 0;
uint64 arg5 = 0;
if (!ParseComponent(guidString, &realmId)
|| !ParseComponent(guidString, &arg2)
|| !ParseComponent(guidString, &arg3)
|| !ParseComponent(guidString, &arg4)
|| !ParseComponent(guidString, &arg5)
|| !ParseDone(guidString))
return ObjectGuid::FromStringFailed;
return ObjectGuidFactory::CreateLMMLobby(realmId, arg2, arg3, arg4, arg5);
}
ObjectGuidInfo();
} Info;
ObjectGuidInfo::ObjectGuidInfo()
{
#define SET_GUID_INFO(type, format, parse) \
Names[AsUnderlyingType(HighGuid::type)] = #type ## sv;\
ClientFormatFunction[AsUnderlyingType(HighGuid::type)] = &ObjectGuidInfo::format;\
ClientParseFunction[AsUnderlyingType(HighGuid::type)] = &ObjectGuidInfo::parse
SET_GUID_INFO(Null, FormatNull, ParseNull);
SET_GUID_INFO(Uniq, FormatUniq, ParseUniq);
SET_GUID_INFO(Player, FormatPlayer, ParsePlayer);
SET_GUID_INFO(Item, FormatItem, ParseItem);
SET_GUID_INFO(WorldTransaction, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(StaticDoor, FormatTransport, ParseTransport);
SET_GUID_INFO(Transport, FormatTransport, ParseTransport);
SET_GUID_INFO(Conversation, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(Creature, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(Vehicle, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(Pet, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(GameObject, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(DynamicObject, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(AreaTrigger, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(Corpse, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(LootObject, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(SceneObject, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(Scenario, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(AIGroup, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(DynamicDoor, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(ClientActor, FormatClientActor, ParseClientActor);
SET_GUID_INFO(Vignette, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(CallForHelp, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(AIResource, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(AILock, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(AILockTicket, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(ChatChannel, FormatChatChannel, ParseChatChannel);
SET_GUID_INFO(Party, FormatGlobal, ParseGlobal);
SET_GUID_INFO(Guild, FormatGuild, ParseGuild);
SET_GUID_INFO(WowAccount, FormatGlobal, ParseGlobal);
SET_GUID_INFO(BNetAccount, FormatGlobal, ParseGlobal);
SET_GUID_INFO(GMTask, FormatGlobal, ParseGlobal);
SET_GUID_INFO(MobileSession, FormatMobileSession, ParseMobileSession);
SET_GUID_INFO(RaidGroup, FormatGlobal, ParseGlobal);
SET_GUID_INFO(Spell, FormatGlobal, ParseGlobal);
SET_GUID_INFO(Mail, FormatGlobal, ParseGlobal);
SET_GUID_INFO(WebObj, FormatWebObj, ParseWebObj);
SET_GUID_INFO(LFGObject, FormatLFGObject, ParseLFGObject);
SET_GUID_INFO(LFGList, FormatLFGList, ParseLFGList);
SET_GUID_INFO(UserRouter, FormatGlobal, ParseGlobal);
SET_GUID_INFO(PVPQueueGroup, FormatGlobal, ParseGlobal);
SET_GUID_INFO(UserClient, FormatGlobal, ParseGlobal);
SET_GUID_INFO(PetBattle, FormatClient, ParseClient);
SET_GUID_INFO(UniqUserClient, FormatClient, ParseClient);
SET_GUID_INFO(BattlePet, FormatGlobal, ParseGlobal);
SET_GUID_INFO(CommerceObj, FormatGlobal, ParseGlobal);
SET_GUID_INFO(ClientSession, FormatClient, ParseClient);
SET_GUID_INFO(Cast, FormatWorldObject, ParseWorldObject);
SET_GUID_INFO(ClientConnection, FormatClient, ParseClient);
SET_GUID_INFO(ClubFinder, FormatClubFinder, ParseClubFinder);
SET_GUID_INFO(ToolsClient, FormatToolsClient, ParseToolsClient);
SET_GUID_INFO(WorldLayer, FormatWorldLayer, ParseWorldLayer);
SET_GUID_INFO(ArenaTeam, FormatGuild, ParseGuild);
SET_GUID_INFO(LMMParty, FormatClient, ParseClient);
SET_GUID_INFO(LMMLobby, FormatLMMLobby, ParseLMMLobby);
#undef SET_GUID_INFO
}
}
template
auto fmt::formatter::format(ObjectGuid const& guid, FormatContext& ctx) const -> decltype(ctx.out())
{
if (guid.GetHigh() >= HighGuid::Count)
return this->format(ObjectGuid::ToStringFailed, ctx);
int32 type = AsUnderlyingType(guid.GetHigh());
if (!Info.ClientFormatFunction[type])
return this->format(ObjectGuid::ToStringFailed, ctx);
return Info.ClientFormatFunction[type](ctx, Info.Names[type], guid);
}
template TC_GAME_API fmt::appender fmt::formatter::format(ObjectGuid const&, format_context&) const;
std::string_view ObjectGuid::GetTypeName(HighGuid high)
{
if (high >= HighGuid::Count)
return "";
return Info.Names[uint32(high)];
}
std::string ObjectGuid::ToString() const
{
return ObjectGuidInfo::Format(*this);
}
std::string ObjectGuid::ToHexString() const
{
return Trinity::StringFormat("0x{:016X}{:016X}", _data[1], _data[0]);
}
ObjectGuid ObjectGuid::FromString(std::string_view guidString)
{
return Info.Parse(guidString);
}
std::size_t ObjectGuid::GetHash() const
{
std::size_t hashVal = 0;
Trinity::hash_combine(hashVal, _data[0]);
Trinity::hash_combine(hashVal, _data[1]);
return hashVal;
}
std::array ObjectGuid::GetRawValue() const
{
std::array raw;
memcpy(raw.data(), _data.data(), BytesSize);
return raw;
}
void ObjectGuid::SetRawValue(std::span rawBytes)
{
ASSERT(rawBytes.size() == BytesSize, SZFMTD " == " SZFMTD, rawBytes.size(), BytesSize);
memcpy(_data.data(), rawBytes.data(), BytesSize);
}
static inline uint32 GetRealmIdForObjectGuid(uint32 realmId)
{
if (realmId)
return realmId;
return sRealmList->GetCurrentRealmId().Realm;
}
constexpr ObjectGuid ObjectGuidFactory::CreateNull()
{
return ObjectGuid();
}
constexpr ObjectGuid ObjectGuidFactory::CreateUniq(ObjectGuid::LowType id)
{
return ObjectGuid(uint64(uint64(HighGuid::Uniq) << 58),
id);
}
ObjectGuid ObjectGuidFactory::CreatePlayer(uint32 realmId, ObjectGuid::LowType dbId)
{
return ObjectGuid(uint64((uint64(HighGuid::Player) << 58)
| (uint64(GetRealmIdForObjectGuid(realmId)) << 42)),
dbId);
}
ObjectGuid ObjectGuidFactory::CreateItem(uint32 realmId, ObjectGuid::LowType dbId)
{
return ObjectGuid(uint64((uint64(HighGuid::Item) << 58)
| (uint64(GetRealmIdForObjectGuid(realmId)) << 42)),
dbId);
}
ObjectGuid ObjectGuidFactory::CreateWorldObject(HighGuid type, uint8 subType, uint32 realmId, uint16 mapId, uint32 serverId, uint32 entry, ObjectGuid::LowType counter)
{
return ObjectGuid(uint64((uint64(type) << 58)
| (uint64(GetRealmIdForObjectGuid(realmId) & 0x1FFF) << 42)
| (uint64(mapId & 0x1FFF) << 29)
| (uint64(entry & 0x7FFFFF) << 6)
| (uint64(subType) & 0x3F)),
uint64((uint64(serverId & 0xFFFFFF) << 40)
| (counter & UI64LIT(0xFFFFFFFFFF))));
}
ObjectGuid ObjectGuidFactory::CreateTransport(HighGuid type, uint32 counter)
{
return ObjectGuid(uint64((uint64(type) << 58)
| (uint64(counter) << 38)),
UI64LIT(0));
}
ObjectGuid ObjectGuidFactory::CreateClientActor(uint16 ownerType, uint16 ownerId, uint32 counter)
{
return ObjectGuid(uint64((uint64(HighGuid::ClientActor) << 58)
| (uint64(ownerType & 0x1FFF) << 42)
| (uint64(ownerId & 0xFFFFFF) << 26)),
uint64(counter));
}
ObjectGuid ObjectGuidFactory::CreateChatChannel(uint32 realmId, bool builtIn, bool trade, uint16 zoneId, uint8 factionGroupMask, ObjectGuid::LowType counter)
{
return ObjectGuid(uint64((uint64(HighGuid::ChatChannel) << 58)
| (uint64(GetRealmIdForObjectGuid(realmId) & 0x1FFF) << 42)
| (uint64(builtIn) << 25)
| (uint64(trade) << 24)
| (uint64(zoneId & 0x3FFF) << 10)
| (uint64(factionGroupMask & 0x3F) << 4)),
counter);
}
ObjectGuid ObjectGuidFactory::CreateGlobal(HighGuid type, ObjectGuid::LowType dbIdHigh, ObjectGuid::LowType dbId)
{
return ObjectGuid(uint64((uint64(type) << 58)
| (uint64(dbIdHigh & UI64LIT(0x3FFFFFFFFFFFFFF)))),
dbId);
}
ObjectGuid ObjectGuidFactory::CreateGuild(HighGuid type, uint32 realmId, ObjectGuid::LowType dbId)
{
return ObjectGuid(uint64((uint64(type) << 58)
| (uint64(GetRealmIdForObjectGuid(realmId)) << 42)),
dbId);
}
ObjectGuid ObjectGuidFactory::CreateMobileSession(uint32 realmId, uint16 arg1, ObjectGuid::LowType counter)
{
return ObjectGuid(uint64((uint64(HighGuid::MobileSession) << 58)
| (uint64(GetRealmIdForObjectGuid(realmId)) << 42)
| (uint64(arg1 & 0x1FF) << 33)),
counter);
}
ObjectGuid ObjectGuidFactory::CreateWebObj(uint32 realmId, uint8 arg1, uint8 arg2, ObjectGuid::LowType counter)
{
return ObjectGuid(uint64((uint64(HighGuid::WebObj) << 58)
| (uint64(GetRealmIdForObjectGuid(realmId) & 0x1FFF) << 42)
| (uint64(arg1 & 0x1F) << 37)
| (uint64(arg2 & 0x3) << 35)),
counter);
}
ObjectGuid ObjectGuidFactory::CreateLFGObject(uint8 arg1, uint8 arg2, uint8 arg3, uint8 arg4, bool arg5, uint8 arg6, ObjectGuid::LowType counter)
{
return ObjectGuid(uint64((uint64(HighGuid::LFGObject) << 58)
| (uint64(arg1 & 0xF) << 54)
| (uint64(arg2 & 0xF) << 50)
| (uint64(arg3 & 0xF) << 46)
| (uint64(arg4 & 0xFF) << 38)
| (uint64(arg5 ? 1 : 0) << 37)
| (uint64(arg6 & 0x3) << 35)),
counter);
}
ObjectGuid ObjectGuidFactory::CreateLFGList(uint8 arg1, ObjectGuid::LowType counter)
{
return ObjectGuid(uint64((uint64(HighGuid::LFGObject) << 58)
| (uint64(arg1 & 0xF) << 54)),
counter);
}
ObjectGuid ObjectGuidFactory::CreateClient(HighGuid type, uint32 realmId, uint32 arg1, ObjectGuid::LowType counter)
{
return ObjectGuid(uint64((uint64(type) << 58)
| (uint64(GetRealmIdForObjectGuid(realmId) & 0x1FFF) << 42)
| (uint64(arg1 & 0xFFFFFFFF) << 10)),
counter);
}
ObjectGuid ObjectGuidFactory::CreateClubFinder(uint32 realmId, uint8 type, uint32 clubFinderId, ObjectGuid::LowType dbId)
{
return ObjectGuid(uint64((uint64(HighGuid::ClubFinder) << 58)
| (type == 1 ? (uint64(GetRealmIdForObjectGuid(realmId) & 0x1FFF) << 42) : UI64LIT(0))
| (uint64(type & 0xFF) << 33)
| (uint64(clubFinderId & 0xFFFFFFFF))),
dbId);
}
ObjectGuid ObjectGuidFactory::CreateToolsClient(uint16 mapId, uint32 serverId, uint64 counter)
{
return ObjectGuid(uint64((uint64(HighGuid::ToolsClient) << 58)
| uint64(mapId)),
uint64((uint64(serverId & 0xFFFFFF) << 40)
| (counter & UI64LIT(0xFFFFFFFFFF))));
}
ObjectGuid ObjectGuidFactory::CreateWorldLayer(uint32 arg1, uint16 arg2, uint8 arg3, uint32 arg4)
{
return ObjectGuid(uint64((uint64(HighGuid::WorldLayer) << 58)
| (uint64(arg1 & 0xFFFFFFFF) << 10)
| (uint64(arg2 & 0x1FF))),
uint64((uint64(arg3 & 0xFF) << 24)
| uint64(arg4 & 0x7FFFFF)));
}
ObjectGuid ObjectGuidFactory::CreateLMMLobby(uint32 realmId, uint32 arg2, uint8 arg3, uint8 arg4, ObjectGuid::LowType counter)
{
return ObjectGuid(uint64((uint64(HighGuid::LMMLobby) << 58)
| (uint64(GetRealmIdForObjectGuid(realmId)) << 42)
| (uint64(arg2 & 0xFFFFFFFF) << 26)
| (uint64(arg3 & 0xFF) << 18)
| (uint64(arg4 & 0xFF) << 10)),
counter);
}
ObjectGuid const ObjectGuid::Empty = ObjectGuid::Create();
ObjectGuid const ObjectGuid::ToStringFailed = ObjectGuid::Create(UI64LIT(3));
ObjectGuid const ObjectGuid::FromStringFailed = ObjectGuid::Create(UI64LIT(4));
ObjectGuid const ObjectGuid::TradeItem = ObjectGuid::Create(UI64LIT(10));
ByteBuffer& operator<<(ByteBuffer& buf, ObjectGuid const& guid)
{
static constexpr std::size_t NumUInt64s = 2;
std::array bytes;
memset(bytes.data(), 0, NumUInt64s);
size_t packedSize = guid._data.size();
for (std::size_t i = 0; i < guid._data.size(); ++i)
{
for (uint32 b = 0; b < 8; ++b)
{
if (uint8 byte = uint8((guid._data[i] >> (b * 8)) & 0xFF))
{
bytes[packedSize++] = byte;
bytes[i] |= uint8(1 << b);
}
}
}
buf.append(bytes.data(), packedSize);
return buf;
}
ByteBuffer& operator>>(ByteBuffer& buf, ObjectGuid& guid)
{
std::array mask;
buf.read(mask);
for (std::size_t i = 0; i < guid._data.size(); ++i)
for (uint32 b = 0; b < 8; ++b)
if (mask[i] & (uint8(1) << b))
guid._data[i] |= uint64(buf.read()) << (b * 8);
return buf;
}