From 1027c42352ee49606d72109bd890b4d8f7f7a88c Mon Sep 17 00:00:00 2001 From: Shauren Date: Fri, 23 May 2025 15:20:57 +0200 Subject: Core/PacketIO: Replace static_asserts with concepts and add them to PacketUtilities as well --- src/server/game/Entities/Unit/Unit.cpp | 4 +- .../game/Server/Packets/AuthenticationPackets.cpp | 177 +++++++++++---------- .../game/Server/Packets/AuthenticationPackets.h | 94 +++++------ .../game/Server/Packets/CombatLogPackets.cpp | 66 ++++---- src/server/game/Server/Packets/CombatLogPackets.h | 44 ++--- .../game/Server/Packets/CombatLogPacketsCommon.h | 9 +- src/server/game/Server/Packets/InspectPackets.h | 7 +- src/server/game/Server/Packets/MiscPackets.cpp | 2 +- src/server/game/Server/Packets/MovementPackets.cpp | 45 ++++-- src/server/game/Server/Packets/MovementPackets.h | 72 ++++----- src/server/game/Server/Packets/PacketUtilities.h | 126 ++++++++++----- src/server/game/Server/Packets/SystemPackets.cpp | 85 ++++++---- src/server/game/Server/Packets/SystemPackets.h | 82 +++++----- src/server/shared/Packets/ByteBuffer.cpp | 1 + src/server/shared/Packets/ByteBuffer.h | 70 ++++---- 15 files changed, 482 insertions(+), 402 deletions(-) (limited to 'src/server') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 80ea5a2d1fe..2d640a0fd24 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -5542,7 +5542,7 @@ void Unit::SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* info) data.SpellID = aura->GetId(); data.LogData.Initialize(this); - WorldPackets::CombatLog::SpellPeriodicAuraLog::SpellLogEffect spellLogEffect; + WorldPackets::CombatLog::PeriodicAuraLogEffect& spellLogEffect = data.Effects.emplace_back(); spellLogEffect.Effect = aura->GetAuraType(); spellLogEffect.Amount = info->damage; spellLogEffect.OriginalDamage = info->originalDamage; @@ -5558,8 +5558,6 @@ void Unit::SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* info) if (contentTuningParams.GenerateDataForUnits(caster, this)) spellLogEffect.ContentTuning = contentTuningParams; - data.Effects.push_back(spellLogEffect); - SendCombatLogMessage(&data); } diff --git a/src/server/game/Server/Packets/AuthenticationPackets.cpp b/src/server/game/Server/Packets/AuthenticationPackets.cpp index 0dda7373312..1fee24274a1 100644 --- a/src/server/game/Server/Packets/AuthenticationPackets.cpp +++ b/src/server/game/Server/Packets/AuthenticationPackets.cpp @@ -86,110 +86,125 @@ void AuthSession::Read() } } -ByteBuffer& operator<<(ByteBuffer& data, AuthWaitInfo const& waitInfo) +ByteBuffer& operator<<(ByteBuffer& data, GameTime const& gameTime) { - data << uint32(waitInfo.WaitCount); - data << uint32(waitInfo.WaitTime); - data << uint8(waitInfo.AllowedFactionGroupForCharacterCreate); - data << WorldPackets::Bits<1>(waitInfo.HasFCM); - data << WorldPackets::Bits<1>(waitInfo.CanCreateOnlyIfExisting); + data << uint32(gameTime.BillingType); + data << uint32(gameTime.MinutesRemaining); + data << uint32(gameTime.RealBillingType); + data << Bits<1>(gameTime.IsInIGR); + data << Bits<1>(gameTime.IsPaidForByIGR); + data << Bits<1>(gameTime.IsCAISEnabled); data.FlushBits(); return data; } -WorldPacket const* AuthResponse::Write() +ByteBuffer& operator<<(ByteBuffer& data, BaseBuildKey const& buildKey) { - _worldPacket << uint32(Result); - _worldPacket << OptionalInit(SuccessInfo); - _worldPacket << OptionalInit(WaitInfo); - _worldPacket.FlushBits(); + for (std::size_t i = 0; i < 16; ++i) + { + data << buildKey.BuildKey[i]; + data << buildKey.ConfigKey[i]; + } - if (SuccessInfo) + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, AuthSuccessInfo const& successInfo) +{ + data << uint32(successInfo.VirtualRealmAddress); + data << Size(successInfo.VirtualRealms); + data << uint32(successInfo.TimeRested); + data << uint8(successInfo.ActiveExpansionLevel); + data << uint8(successInfo.AccountExpansionLevel); + data << uint32(successInfo.TimeSecondsUntilPCKick); + data << Size(*successInfo.AvailableClasses); + data << Size(successInfo.Templates); + data << uint32(successInfo.CurrencyID); + data << successInfo.Time; + + for (RaceClassAvailability const& raceClassAvailability : *successInfo.AvailableClasses) { - _worldPacket << uint32(SuccessInfo->VirtualRealmAddress); - _worldPacket << Size(SuccessInfo->VirtualRealms); - _worldPacket << uint32(SuccessInfo->TimeRested); - _worldPacket << uint8(SuccessInfo->ActiveExpansionLevel); - _worldPacket << uint8(SuccessInfo->AccountExpansionLevel); - _worldPacket << uint32(SuccessInfo->TimeSecondsUntilPCKick); - _worldPacket << Size(*SuccessInfo->AvailableClasses); - _worldPacket << Size(SuccessInfo->Templates); - _worldPacket << uint32(SuccessInfo->CurrencyID); - _worldPacket << SuccessInfo->Time; - - for (RaceClassAvailability const& raceClassAvailability : *SuccessInfo->AvailableClasses) + data << uint8(raceClassAvailability.RaceID); + data << Size(raceClassAvailability.Classes); + + for (ClassAvailability const& classAvailability : raceClassAvailability.Classes) { - _worldPacket << uint8(raceClassAvailability.RaceID); - _worldPacket << Size(raceClassAvailability.Classes); - - for (ClassAvailability const& classAvailability : raceClassAvailability.Classes) - { - _worldPacket << uint8(classAvailability.ClassID); - _worldPacket << uint8(classAvailability.ActiveExpansionLevel); - _worldPacket << uint8(classAvailability.AccountExpansionLevel); - _worldPacket << uint8(classAvailability.MinActiveExpansionLevel); - } + data << uint8(classAvailability.ClassID); + data << uint8(classAvailability.ActiveExpansionLevel); + data << uint8(classAvailability.AccountExpansionLevel); + data << uint8(classAvailability.MinActiveExpansionLevel); } + } - _worldPacket << Bits<1>(SuccessInfo->IsExpansionTrial); - _worldPacket << Bits<1>(SuccessInfo->ForceCharacterTemplate); - _worldPacket << OptionalInit(SuccessInfo->NumPlayersHorde); - _worldPacket << OptionalInit(SuccessInfo->NumPlayersAlliance); - _worldPacket << OptionalInit(SuccessInfo->ExpansionTrialExpiration); - _worldPacket << OptionalInit(SuccessInfo->NewBuildKeys); - _worldPacket.FlushBits(); + data << Bits<1>(successInfo.IsExpansionTrial); + data << Bits<1>(successInfo.ForceCharacterTemplate); + data << OptionalInit(successInfo.NumPlayersHorde); + data << OptionalInit(successInfo.NumPlayersAlliance); + data << OptionalInit(successInfo.ExpansionTrialExpiration); + data << OptionalInit(successInfo.CurrentBuild); + data.FlushBits(); - { - _worldPacket << uint32(SuccessInfo->GameTimeInfo.BillingType); - _worldPacket << uint32(SuccessInfo->GameTimeInfo.MinutesRemaining); - _worldPacket << uint32(SuccessInfo->GameTimeInfo.RealBillingType); - _worldPacket << Bits<1>(SuccessInfo->GameTimeInfo.IsInIGR); // inGameRoom check in function checking which lua event to fire when remaining time is near end - BILLING_NAG_DIALOG vs IGR_BILLING_NAG_DIALOG - _worldPacket << Bits<1>(SuccessInfo->GameTimeInfo.IsPaidForByIGR); // inGameRoom lua return from Script_GetBillingPlan - _worldPacket << Bits<1>(SuccessInfo->GameTimeInfo.IsCAISEnabled); // not used anywhere in the client - _worldPacket.FlushBits(); - } + data << successInfo.GameTimeInfo; - if (SuccessInfo->NumPlayersHorde) - _worldPacket << uint16(*SuccessInfo->NumPlayersHorde); + if (successInfo.NumPlayersHorde) + data << uint16(*successInfo.NumPlayersHorde); - if (SuccessInfo->NumPlayersAlliance) - _worldPacket << uint16(*SuccessInfo->NumPlayersAlliance); + if (successInfo.NumPlayersAlliance) + data << uint16(*successInfo.NumPlayersAlliance); - if (SuccessInfo->ExpansionTrialExpiration) - _worldPacket << *SuccessInfo->ExpansionTrialExpiration; + if (successInfo.ExpansionTrialExpiration) + data << *successInfo.ExpansionTrialExpiration; - if (SuccessInfo->NewBuildKeys) - { - for (std::size_t i = 0; i < 16; ++i) - { - _worldPacket << SuccessInfo->NewBuildKeys->NewBuildKey[i]; - _worldPacket << SuccessInfo->NewBuildKeys->SomeKey[i]; - } - } + if (successInfo.CurrentBuild) + data << *successInfo.CurrentBuild; - for (VirtualRealmInfo const& virtualRealm : SuccessInfo->VirtualRealms) - _worldPacket << virtualRealm; + for (VirtualRealmInfo const& virtualRealm : successInfo.VirtualRealms) + data << virtualRealm; - for (CharacterTemplate const* characterTemplate : SuccessInfo->Templates) + for (CharacterTemplate const* characterTemplate : successInfo.Templates) + { + data << uint32(characterTemplate->TemplateSetId); + data << Size(characterTemplate->Classes); + for (CharacterTemplateClass const& templateClass : characterTemplate->Classes) { - _worldPacket << uint32(characterTemplate->TemplateSetId); - _worldPacket << Size(characterTemplate->Classes); - for (CharacterTemplateClass const& templateClass : characterTemplate->Classes) - { - _worldPacket << uint8(templateClass.ClassID); - _worldPacket << uint8(templateClass.FactionGroup); - } - - _worldPacket << SizedString::BitsSize<7>(characterTemplate->Name); - _worldPacket << SizedString::BitsSize<10>(characterTemplate->Description); - _worldPacket.FlushBits(); - - _worldPacket << SizedString::Data(characterTemplate->Name); - _worldPacket << SizedString::Data(characterTemplate->Description); + data << uint8(templateClass.ClassID); + data << uint8(templateClass.FactionGroup); } + + data << SizedString::BitsSize<7>(characterTemplate->Name); + data << SizedString::BitsSize<10>(characterTemplate->Description); + data.FlushBits(); + + data << SizedString::Data(characterTemplate->Name); + data << SizedString::Data(characterTemplate->Description); } + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, AuthWaitInfo const& waitInfo) +{ + data << uint32(waitInfo.WaitCount); + data << uint32(waitInfo.WaitTime); + data << uint8(waitInfo.AllowedFactionGroupForCharacterCreate); + data << WorldPackets::Bits<1>(waitInfo.HasFCM); + data << WorldPackets::Bits<1>(waitInfo.CanCreateOnlyIfExisting); + data.FlushBits(); + + return data; +} + +WorldPacket const* AuthResponse::Write() +{ + _worldPacket << uint32(Result); + _worldPacket << OptionalInit(SuccessInfo); + _worldPacket << OptionalInit(WaitInfo); + _worldPacket.FlushBits(); + + if (SuccessInfo) + _worldPacket << *SuccessInfo; + if (WaitInfo) _worldPacket << *WaitInfo; diff --git a/src/server/game/Server/Packets/AuthenticationPackets.h b/src/server/game/Server/Packets/AuthenticationPackets.h index 1f2f76091c3..e6a7a96f8ae 100644 --- a/src/server/game/Server/Packets/AuthenticationPackets.h +++ b/src/server/game/Server/Packets/AuthenticationPackets.h @@ -91,17 +91,13 @@ namespace WorldPackets public: static constexpr uint32 DigestLength = 24; - explicit AuthSession(WorldPacket&& packet) : EarlyProcessClientPacket(CMSG_AUTH_SESSION, std::move(packet)) - { - LocalChallenge.fill(0); - Digest.fill(0); - } + explicit AuthSession(WorldPacket&& packet) : EarlyProcessClientPacket(CMSG_AUTH_SESSION, std::move(packet)) { } uint32 RegionID = 0; uint32 BattlegroupID = 0; uint32 RealmID = 0; - std::array LocalChallenge; - std::array Digest; + std::array LocalChallenge = { }; + std::array Digest = { }; uint64 DosResponse = 0; std::string RealmJoinTicket; bool UseIPv6 = false; @@ -142,53 +138,51 @@ namespace WorldPackets VirtualRealmNameInfo RealmNameInfo; }; - class AuthResponse final : public ServerPacket + struct GameTime { - public: - struct AuthSuccessInfo - { - struct GameTime - { - uint32 BillingType = 0; - uint32 MinutesRemaining = 0; - uint32 RealBillingType = 0; - bool IsInIGR = false; - bool IsPaidForByIGR = false; - bool IsCAISEnabled = false; - }; - - struct NewBuild - { - std::array NewBuildKey = { }; - std::array SomeKey = { }; - }; + uint32 BillingType = 0; + uint32 MinutesRemaining = 0; + uint32 RealBillingType = 0; + bool IsInIGR = false; + bool IsPaidForByIGR = false; + bool IsCAISEnabled = false; + }; - AuthSuccessInfo() { } // work around clang bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101227 + struct BaseBuildKey + { + std::array BuildKey = { }; + std::array ConfigKey = { }; + }; - uint8 ActiveExpansionLevel = 0; ///< the current server expansion, the possible values are in @ref Expansions - uint8 AccountExpansionLevel = 0; ///< the current expansion of this account, the possible values are in @ref Expansions - uint32 TimeRested = 0; ///< affects the return value of the GetBillingTimeRested() client API call, it is the number of seconds you have left until the experience points and loot you receive from creatures and quests is reduced. It is only used in the Asia region in retail, it's not implemented in TC and will probably never be. + struct AuthSuccessInfo + { + uint8 ActiveExpansionLevel = 0; ///< the current server expansion, the possible values are in @ref Expansions + uint8 AccountExpansionLevel = 0; ///< the current expansion of this account, the possible values are in @ref Expansions + uint32 TimeRested = 0; ///< affects the return value of the GetBillingTimeRested() client API call, it is the number of seconds you have left until the experience points and loot you receive from creatures and quests is reduced. It is only used in the Asia region in retail, it's not implemented in TC and will probably never be. - uint32 VirtualRealmAddress = 0; ///< a special identifier made from the Index, BattleGroup and Region. - uint32 TimeSecondsUntilPCKick = 0; ///< @todo research - uint32 CurrencyID = 0; ///< this is probably used for the ingame shop. @todo implement - Timestamp<> Time; + uint32 VirtualRealmAddress = 0; ///< a special identifier made from the Index, BattleGroup and Region. + uint32 TimeSecondsUntilPCKick = 0; ///< @todo research + uint32 CurrencyID = 0; ///< this is probably used for the ingame shop. @todo implement + Timestamp<> Time; - GameTime GameTimeInfo; + GameTime GameTimeInfo; - std::vector VirtualRealms; ///< list of realms connected to this one (inclusive) @todo implement - std::vector Templates; ///< list of pre-made character templates. + std::vector VirtualRealms; ///< list of realms connected to this one (inclusive) @todo implement + std::vector Templates; ///< list of pre-made character templates. - std::vector const* AvailableClasses = nullptr; ///< the minimum AccountExpansion required to select race/class combinations + std::vector const* AvailableClasses = nullptr; ///< the minimum AccountExpansion required to select race/class combinations - bool IsExpansionTrial = false; - bool ForceCharacterTemplate = false; ///< forces the client to always use a character template when creating a new character. @see Templates. @todo implement - Optional NumPlayersHorde; ///< number of horde players in this realm. @todo implement - Optional NumPlayersAlliance; ///< number of alliance players in this realm. @todo implement - Optional> ExpansionTrialExpiration; ///< expansion trial expiration unix timestamp - Optional NewBuildKeys; - }; + bool IsExpansionTrial = false; + bool ForceCharacterTemplate = false; ///< forces the client to always use a character template when creating a new character. @see Templates. @todo implement + Optional NumPlayersHorde; ///< number of horde players in this realm. @todo implement + Optional NumPlayersAlliance; ///< number of alliance players in this realm. @todo implement + Optional> ExpansionTrialExpiration; ///< expansion trial expiration unix timestamp + Optional CurrentBuild; + }; + class AuthResponse final : public ServerPacket + { + public: explicit AuthResponse() : ServerPacket(SMSG_AUTH_RESPONSE, 132) { } WorldPacket const* Write() override; @@ -274,16 +268,12 @@ namespace WorldPackets public: static constexpr uint32 DigestLength = 24; - explicit AuthContinuedSession(WorldPacket&& packet) : EarlyProcessClientPacket(CMSG_AUTH_CONTINUED_SESSION, std::move(packet)) - { - LocalChallenge.fill(0); - Digest.fill(0); - } + explicit AuthContinuedSession(WorldPacket&& packet) : EarlyProcessClientPacket(CMSG_AUTH_CONTINUED_SESSION, std::move(packet)) { } uint64 DosResponse = 0; uint64 Key = 0; - std::array LocalChallenge; - std::array Digest; + std::array LocalChallenge = { }; + std::array Digest = { }; private: friend EarlyProcessClientPacket; diff --git a/src/server/game/Server/Packets/CombatLogPackets.cpp b/src/server/game/Server/Packets/CombatLogPackets.cpp index 408d8029311..4baec163035 100644 --- a/src/server/game/Server/Packets/CombatLogPackets.cpp +++ b/src/server/game/Server/Packets/CombatLogPackets.cpp @@ -191,6 +191,42 @@ WorldPacket const* SpellHealLog::Write() return &_worldPacket; } +ByteBuffer& operator<<(ByteBuffer& data, PeriodicalAuraLogEffectDebugInfo const& debugInfo) +{ + data << float(debugInfo.CritRollMade); + data << float(debugInfo.CritRollNeeded); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, PeriodicAuraLogEffect const& effect) +{ + data << int32(effect.Effect); + data << int32(effect.Amount); + data << int32(effect.OriginalDamage); + data << int32(effect.OverHealOrKill); + data << int32(effect.SchoolMaskOrPower); + data << int32(effect.AbsorbedOrAmplitude); + data << int32(effect.Resisted); + data << Size(effect.Supporters); + + for (Spells::SpellSupportInfo const& supportInfo : effect.Supporters) + data << supportInfo; + + data << Bits<1>(effect.Crit); + data << OptionalInit(effect.DebugInfo); + data << OptionalInit(effect.ContentTuning); + data.FlushBits(); + + if (effect.ContentTuning) + data << *effect.ContentTuning; + + if (effect.DebugInfo) + data << *effect.DebugInfo; + + return data; +} + WorldPacket const* SpellPeriodicAuraLog::Write() { *this << TargetGUID; @@ -200,34 +236,8 @@ WorldPacket const* SpellPeriodicAuraLog::Write() WriteLogDataBit(); FlushBits(); - for (SpellLogEffect const& effect : Effects) - { - *this << int32(effect.Effect); - *this << int32(effect.Amount); - *this << int32(effect.OriginalDamage); - *this << int32(effect.OverHealOrKill); - *this << int32(effect.SchoolMaskOrPower); - *this << int32(effect.AbsorbedOrAmplitude); - *this << int32(effect.Resisted); - *this << Size(effect.Supporters); - - for (Spells::SpellSupportInfo const& supportInfo : effect.Supporters) - *this << supportInfo; - - *this << Bits<1>(effect.Crit); - *this << OptionalInit(effect.DebugInfo); - *this << OptionalInit(effect.ContentTuning); - FlushBits(); - - if (effect.ContentTuning) - *this << *effect.ContentTuning; - - if (effect.DebugInfo) - { - *this << float(effect.DebugInfo->CritRollMade); - *this << float(effect.DebugInfo->CritRollNeeded); - } - } + for (PeriodicAuraLogEffect const& effect : Effects) + *this << effect; WriteLogData(); diff --git a/src/server/game/Server/Packets/CombatLogPackets.h b/src/server/game/Server/Packets/CombatLogPackets.h index 303cd14ae00..7b94d4a9223 100644 --- a/src/server/game/Server/Packets/CombatLogPackets.h +++ b/src/server/game/Server/Packets/CombatLogPackets.h @@ -108,30 +108,30 @@ namespace WorldPackets std::vector Supporters; }; + struct PeriodicalAuraLogEffectDebugInfo + { + float CritRollMade = 0.0f; + float CritRollNeeded = 0.0f; + }; + + struct PeriodicAuraLogEffect + { + int32 Effect = 0; + int32 Amount = 0; + int32 OriginalDamage = 0; + int32 OverHealOrKill = 0; + int32 SchoolMaskOrPower = 0; + int32 AbsorbedOrAmplitude = 0; + int32 Resisted = 0; + bool Crit = false; + Optional DebugInfo; + Optional ContentTuning; + std::vector Supporters; + }; + class SpellPeriodicAuraLog final : public CombatLogServerPacket { public: - struct PeriodicalAuraLogEffectDebugInfo - { - float CritRollMade = 0.0f; - float CritRollNeeded = 0.0f; - }; - - struct SpellLogEffect - { - int32 Effect = 0; - int32 Amount = 0; - int32 OriginalDamage = 0; - int32 OverHealOrKill = 0; - int32 SchoolMaskOrPower = 0; - int32 AbsorbedOrAmplitude = 0; - int32 Resisted = 0; - bool Crit = false; - Optional DebugInfo; - Optional ContentTuning; - std::vector Supporters; - }; - explicit SpellPeriodicAuraLog() : CombatLogServerPacket(SMSG_SPELL_PERIODIC_AURA_LOG, 16 + 16 + 4 + 4 + 1) { } WorldPacket const* Write() override; @@ -139,7 +139,7 @@ namespace WorldPackets ObjectGuid TargetGUID; ObjectGuid CasterGUID; int32 SpellID = 0; - std::vector Effects; + std::vector Effects; }; class SpellInterruptLog final : public ServerPacket diff --git a/src/server/game/Server/Packets/CombatLogPacketsCommon.h b/src/server/game/Server/Packets/CombatLogPacketsCommon.h index 69b0c031470..cc9294dfe4f 100644 --- a/src/server/game/Server/Packets/CombatLogPacketsCommon.h +++ b/src/server/game/Server/Packets/CombatLogPacketsCommon.h @@ -120,7 +120,14 @@ namespace WorldPackets Spells::SpellCastLogData LogData; protected: - template + template + void operator<<(T val) + { + _worldPacket << val; + _fullLogPacket << val; + } + + template requires (!ByteBufferNumeric) void operator<<(T const& val) { _worldPacket << val; diff --git a/src/server/game/Server/Packets/InspectPackets.h b/src/server/game/Server/Packets/InspectPackets.h index a57d0c5c612..bd8c0703129 100644 --- a/src/server/game/Server/Packets/InspectPackets.h +++ b/src/server/game/Server/Packets/InspectPackets.h @@ -128,17 +128,14 @@ namespace WorldPackets class InspectResult final : public ServerPacket { public: - explicit InspectResult() : ServerPacket(SMSG_INSPECT_RESULT, 4096) - { - PvpTalents.fill(0); - } + explicit InspectResult() : ServerPacket(SMSG_INSPECT_RESULT, 4096) { } WorldPacket const* Write() override; PlayerModelDisplayInfo DisplayInfo; std::vector Glyphs; std::vector Talents; - std::array PvpTalents; + std::array PvpTalents = { }; Optional GuildData; std::array Bracket; Optional AzeriteLevel; diff --git a/src/server/game/Server/Packets/MiscPackets.cpp b/src/server/game/Server/Packets/MiscPackets.cpp index 29a1a7ed5ae..c641abdb94f 100644 --- a/src/server/game/Server/Packets/MiscPackets.cpp +++ b/src/server/game/Server/Packets/MiscPackets.cpp @@ -575,7 +575,7 @@ WorldPacket const* LoadCUFProfiles::Write() // Bool Options for (uint8 option = 0; option < CUF_BOOL_OPTIONS_COUNT; option++) - _worldPacket << Bits<1>(cufProfile->BoolOptions[option]); + _worldPacket.WriteBit(cufProfile->BoolOptions[option]); // Other Options _worldPacket << uint16(cufProfile->FrameHeight); diff --git a/src/server/game/Server/Packets/MovementPackets.cpp b/src/server/game/Server/Packets/MovementPackets.cpp index 443c458339e..d706d273667 100644 --- a/src/server/game/Server/Packets/MovementPackets.cpp +++ b/src/server/game/Server/Packets/MovementPackets.cpp @@ -1095,7 +1095,33 @@ WorldPacket const* ResumeToken::Write() return &_worldPacket; } -ByteBuffer& operator<<(ByteBuffer& data, MoveSetCompoundState::MoveStateChange const& stateChange) +ByteBuffer& operator<<(ByteBuffer& data, CollisionHeightInfo const& collisionHeightInfo) +{ + data << float(collisionHeightInfo.Height); + data << float(collisionHeightInfo.Scale); + data << uint8(collisionHeightInfo.Reason); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, StateChangeRangeInfo const& stateChangeRangeInfo) +{ + data << float(stateChangeRangeInfo.Min); + data << float(stateChangeRangeInfo.Max); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, KnockBackInfo const& knockBackInfo) +{ + data << float(knockBackInfo.HorzSpeed); + data << knockBackInfo.Direction; + data << float(knockBackInfo.InitVertSpeed); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, MoveStateChange const& stateChange) { data << uint32(stateChange.MessageID); data << uint32(stateChange.SequenceIndex); @@ -1118,27 +1144,16 @@ ByteBuffer& operator<<(ByteBuffer& data, MoveSetCompoundState::MoveStateChange c data << float(*stateChange.Speed); if (stateChange.Range) - { - data << float(stateChange.Range->Min); - data << float(stateChange.Range->Max); - } + data << *stateChange.Range; if (stateChange.KnockBack) - { - data << float(stateChange.KnockBack->HorzSpeed); - data << stateChange.KnockBack->Direction; - data << float(stateChange.KnockBack->InitVertSpeed); - } + data << *stateChange.KnockBack; if (stateChange.VehicleRecID) data << int32(*stateChange.VehicleRecID); if (stateChange.CollisionHeight) - { - data << float(stateChange.CollisionHeight->Height); - data << float(stateChange.CollisionHeight->Scale); - data << uint8(stateChange.CollisionHeight->Reason); - } + data << *stateChange.CollisionHeight; if (stateChange.MovementForceGUID) data << *stateChange.MovementForceGUID; diff --git a/src/server/game/Server/Packets/MovementPackets.h b/src/server/game/Server/Packets/MovementPackets.h index cbfba392381..71a51a5b9b4 100644 --- a/src/server/game/Server/Packets/MovementPackets.h +++ b/src/server/game/Server/Packets/MovementPackets.h @@ -691,47 +691,47 @@ namespace WorldPackets uint32 Reason = 1; }; - class MoveSetCompoundState final : public ServerPacket + struct CollisionHeightInfo { - public: - struct CollisionHeightInfo - { - float Height = 0.0f; - float Scale = 0.0f; - UpdateCollisionHeightReason Reason = UpdateCollisionHeightReason::Scale; - }; + float Height = 0.0f; + float Scale = 0.0f; + UpdateCollisionHeightReason Reason = UpdateCollisionHeightReason::Scale; + }; - struct KnockBackInfo - { - float HorzSpeed = 0.0f; - TaggedPosition Direction; - float InitVertSpeed = 0.0f; - }; + struct StateChangeRangeInfo + { + float Min = 0.0f; + float Max = 0.0f; + }; - struct StateChangeRangeInfo - { - float Min = 0.0f; - float Max = 0.0f; - }; + struct KnockBackInfo + { + float HorzSpeed = 0.0f; + TaggedPosition Direction; + float InitVertSpeed = 0.0f; + }; - struct MoveStateChange - { - MoveStateChange(OpcodeServer messageId, uint32 sequenceIndex) : MessageID(messageId), SequenceIndex(sequenceIndex) { } - - uint32 MessageID = 0; - uint32 SequenceIndex = 0; - Optional Speed; - Optional Range; - Optional KnockBack; - Optional VehicleRecID; - Optional CollisionHeight; - Optional MovementForce_; - Optional MovementForceGUID; - Optional MovementInertiaID; - Optional MovementInertiaLifetimeMs; - Optional DriveCapabilityRecID; - }; + struct MoveStateChange + { + MoveStateChange(OpcodeServer messageId, uint32 sequenceIndex) : MessageID(messageId), SequenceIndex(sequenceIndex) { } + uint32 MessageID = 0; + uint32 SequenceIndex = 0; + Optional Speed; + Optional Range; + Optional KnockBack; + Optional VehicleRecID; + Optional CollisionHeight; + Optional MovementForce_; + Optional MovementForceGUID; + Optional MovementInertiaID; + Optional MovementInertiaLifetimeMs; + Optional DriveCapabilityRecID; + }; + + class MoveSetCompoundState final : public ServerPacket + { + public: explicit MoveSetCompoundState() : ServerPacket(SMSG_MOVE_SET_COMPOUND_STATE, 4 + 1) { } WorldPacket const* Write() override; diff --git a/src/server/game/Server/Packets/PacketUtilities.h b/src/server/game/Server/Packets/PacketUtilities.h index 2917d2d8d25..c7b859ecd65 100644 --- a/src/server/game/Server/Packets/PacketUtilities.h +++ b/src/server/game/Server/Packets/PacketUtilities.h @@ -345,19 +345,26 @@ namespace WorldPackets ChronoDuration _value = ChronoDuration::zero(); }; - template + template + concept AsWritable = std::is_default_constructible_v && HasByteBufferShiftOperators; + + template + concept AsWritableFor = requires { static_cast(std::declval()); } + && requires { static_cast(Underlying()); }; + + template T> struct AsWriter { T const& Value; friend inline ByteBuffer& operator<<(ByteBuffer& data, AsWriter const& opt) { - data << Underlying(opt.Value); + data << static_cast(opt.Value); return data; } }; - template + template T> struct AsReaderWriter : AsWriter { friend inline ByteBuffer& operator>>(ByteBuffer& data, AsReaderWriter const& opt) @@ -369,13 +376,16 @@ namespace WorldPackets } }; - template + template T> inline AsWriter As(T const& value) { return { value }; } - template + template T> inline AsReaderWriter As(T& value) { return { value }; } template + concept OptionalWritable = std::is_default_constructible_v; + + template struct OptionalInitWriter { Optional const& Opt; @@ -387,7 +397,7 @@ namespace WorldPackets } }; - template + template struct OptionalInitReaderWriter : OptionalInitWriter { friend inline ByteBuffer& operator>>(ByteBuffer& data, OptionalInitReaderWriter const& opt) @@ -398,13 +408,13 @@ namespace WorldPackets } }; - template + template inline OptionalInitWriter OptionalInit(Optional const& value) { return { value }; } - template + template inline OptionalInitReaderWriter OptionalInit(Optional& value) { return { value }; } - template + template struct PtrInitWriter { std::unique_ptr const& Ptr; @@ -416,7 +426,7 @@ namespace WorldPackets } }; - template + template struct PtrInitReaderWriter : PtrInitWriter { friend inline ByteBuffer& operator>>(ByteBuffer& data, PtrInitReaderWriter const& opt) @@ -427,41 +437,62 @@ namespace WorldPackets } }; - template + template inline PtrInitWriter OptionalInit(std::unique_ptr const& value) { return { value }; } - template + template inline PtrInitReaderWriter OptionalInit(std::unique_ptr& value) { return { value }; } - template + template + concept BitsWritable = AsWritableFor; + + template struct BitsWriter { T const& Value; friend inline ByteBuffer& operator<<(ByteBuffer& data, BitsWriter const& bits) { - data.WriteBits(static_cast(bits.Value), BitCount); + if constexpr (BitCount != 1) + data.WriteBits(static_cast(bits.Value), BitCount); + else + data.WriteBit(static_cast(bits.Value) != 0); + return data; } }; - template + template struct BitsReaderWriter : BitsWriter { friend inline ByteBuffer& operator>>(ByteBuffer& data, BitsReaderWriter const& bits) { - const_cast(bits.Value) = static_cast(data.ReadBits(BitCount)); + if constexpr (BitCount != 1) + const_cast(bits.Value) = static_cast(data.ReadBits(BitCount)); + else + const_cast(bits.Value) = static_cast(data.ReadBit() ? 1 : 0); + return data; } }; - template + template inline BitsWriter Bits(T const& value) { return { value }; } - template + template inline BitsReaderWriter Bits(T& value) { return { value }; } - template + template + concept ContainerWritable = requires(T const& container) { { container.size() } -> AsWritableFor; } + && !std::same_as + && !std::same_as; + + template + concept ContainerReadable = ContainerWritable + && !std::is_const_v + && requires(T & container) { container.resize(SizeType{}); }; + + template Container> struct SizeWriter { Container const& Value; @@ -473,7 +504,7 @@ namespace WorldPackets } }; - template + template Container> struct SizeReaderWriter : SizeWriter { friend inline ByteBuffer& operator>>(ByteBuffer& data, SizeReaderWriter const& size) @@ -485,13 +516,13 @@ namespace WorldPackets } }; - template + template Container> inline SizeWriter Size(Container const& value) { return { value }; } - template + template Container> inline SizeReaderWriter Size(Container& value) { return { value }; } - template + template Container> struct BitsSizeWriter { Container const& Value; @@ -503,7 +534,7 @@ namespace WorldPackets } }; - template + template Container> struct BitsSizeReaderWriter : BitsSizeWriter { friend inline ByteBuffer& operator>>(ByteBuffer& data, BitsSizeReaderWriter const& bits) @@ -513,15 +544,26 @@ namespace WorldPackets } }; - template + template Container> inline BitsSizeWriter BitsSize(Container const& value) { return { value }; } - template + template Container> inline BitsSizeReaderWriter BitsSize(Container& value) { return { value }; } + template + concept StringWritable = requires(T const& container) { { container.length() } -> AsWritableFor; } + && requires(ByteBuffer& data, T const& string) { data.WriteString(static_cast(string)); /*TODO: Kill String class and remove the cast*/ }; + + template + concept StringReadable = StringWritable + && !std::is_const_v + && !std::same_as + && requires(T& container) { container.resize(uint32()); } + && requires(ByteBuffer& data, T& string) { string = data.ReadString(uint32(), bool()); }; + namespace SizedString { - template + template struct SizeWriter { Container const& Value; @@ -533,7 +575,7 @@ namespace WorldPackets } }; - template + template struct SizeReaderWriter : SizeWriter { friend inline ByteBuffer& operator>>(ByteBuffer& data, SizeReaderWriter const& bits) @@ -543,13 +585,13 @@ namespace WorldPackets } }; - template + template inline SizeWriter BitsSize(Container const& value) { return { value }; } - template + template inline SizeReaderWriter BitsSize(Container& value) { return { value }; } - template + template struct DataWriter { Container const& Value; @@ -561,7 +603,7 @@ namespace WorldPackets } }; - template + template struct DataReaderWriter : DataWriter { static constexpr bool IsUtf8() { return Mode == Strings::ValidUtf8; } @@ -573,17 +615,17 @@ namespace WorldPackets } }; - template + template inline DataWriter Data(Container const& value) { return { value }; } - template + template inline DataReaderWriter Data(Container& value) { return { value }; } } // SizedCString (sends size + string + null terminator but only if not empty) namespace SizedCString { - template + template struct SizeWriter { Container const& Value; @@ -595,7 +637,7 @@ namespace WorldPackets } }; - template + template struct SizeReaderWriter : SizeWriter { friend inline ByteBuffer& operator>>(ByteBuffer& data, SizeReaderWriter const& bits) @@ -606,13 +648,13 @@ namespace WorldPackets } }; - template + template inline SizeWriter BitsSize(Container const& value) { return { value }; } - template + template inline SizeReaderWriter BitsSize(Container& value) { return { value }; } - template + template struct DataWriter { Container const& Value; @@ -628,7 +670,7 @@ namespace WorldPackets } }; - template + template struct DataReaderWriter : DataWriter { static constexpr bool IsUtf8() { return Mode == Strings::ValidUtf8; } @@ -644,10 +686,10 @@ namespace WorldPackets } }; - template + template inline DataWriter Data(Container const& value) { return { value }; } - template + template inline DataReaderWriter Data(Container& value) { return { value }; } } } diff --git a/src/server/game/Server/Packets/SystemPackets.cpp b/src/server/game/Server/Packets/SystemPackets.cpp index 0afe471b740..651ce1ae4cd 100644 --- a/src/server/game/Server/Packets/SystemPackets.cpp +++ b/src/server/game/Server/Packets/SystemPackets.cpp @@ -19,6 +19,44 @@ namespace WorldPackets::System { +ByteBuffer& operator<<(ByteBuffer& data, SocialQueueConfig const& socialQueueConfig) +{ + data << Bits<1>(socialQueueConfig.ToastsDisabled); + data << float(socialQueueConfig.ToastDuration); + data << float(socialQueueConfig.DelayDuration); + data << float(socialQueueConfig.QueueMultiplier); + data << float(socialQueueConfig.PlayerMultiplier); + data << float(socialQueueConfig.PlayerFriendValue); + data << float(socialQueueConfig.PlayerGuildValue); + data << float(socialQueueConfig.ThrottleInitialThreshold); + data << float(socialQueueConfig.ThrottleDecayTime); + data << float(socialQueueConfig.ThrottlePrioritySpike); + data << float(socialQueueConfig.ThrottleMinThreshold); + data << float(socialQueueConfig.ThrottlePvPPriorityNormal); + data << float(socialQueueConfig.ThrottlePvPPriorityLow); + data << float(socialQueueConfig.ThrottlePvPHonorThreshold); + data << float(socialQueueConfig.ThrottleLfgListPriorityDefault); + data << float(socialQueueConfig.ThrottleLfgListPriorityAbove); + data << float(socialQueueConfig.ThrottleLfgListPriorityBelow); + data << float(socialQueueConfig.ThrottleLfgListIlvlScalingAbove); + data << float(socialQueueConfig.ThrottleLfgListIlvlScalingBelow); + data << float(socialQueueConfig.ThrottleRfPriorityAbove); + data << float(socialQueueConfig.ThrottleRfIlvlScalingAbove); + data << float(socialQueueConfig.ThrottleDfMaxItemLevel); + data << float(socialQueueConfig.ThrottleDfBestPriority); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, SessionAlertConfig const& sessionAlert) +{ + data << int32(sessionAlert.Delay); + data << int32(sessionAlert.Period); + data << int32(sessionAlert.DisplayTime); + + return data; +} + ByteBuffer& operator<<(ByteBuffer& data, SavedThrottleObjectState const& throttleState) { data << uint32(throttleState.MaxTries); @@ -41,6 +79,15 @@ ByteBuffer& operator<<(ByteBuffer& data, EuropaTicketConfig const& europaTicketS return data; } +ByteBuffer& operator<<(ByteBuffer& data, SquelchInfo const& squelch) +{ + data << Bits<1>(squelch.IsSquelched); + data << squelch.BnetAccountGuid; + data << squelch.GuildGuid; + + return data; +} + ByteBuffer& operator<<(ByteBuffer& data, GameRuleValuePair const& gameRuleValue) { data << int32(gameRuleValue.Rule); @@ -167,46 +214,14 @@ WorldPacket const* FeatureSystemStatus::Write() _worldPacket.FlushBits(); - { - _worldPacket << Bits<1>(QuickJoinConfig.ToastsDisabled); - _worldPacket << float(QuickJoinConfig.ToastDuration); - _worldPacket << float(QuickJoinConfig.DelayDuration); - _worldPacket << float(QuickJoinConfig.QueueMultiplier); - _worldPacket << float(QuickJoinConfig.PlayerMultiplier); - _worldPacket << float(QuickJoinConfig.PlayerFriendValue); - _worldPacket << float(QuickJoinConfig.PlayerGuildValue); - _worldPacket << float(QuickJoinConfig.ThrottleInitialThreshold); - _worldPacket << float(QuickJoinConfig.ThrottleDecayTime); - _worldPacket << float(QuickJoinConfig.ThrottlePrioritySpike); - _worldPacket << float(QuickJoinConfig.ThrottleMinThreshold); - _worldPacket << float(QuickJoinConfig.ThrottlePvPPriorityNormal); - _worldPacket << float(QuickJoinConfig.ThrottlePvPPriorityLow); - _worldPacket << float(QuickJoinConfig.ThrottlePvPHonorThreshold); - _worldPacket << float(QuickJoinConfig.ThrottleLfgListPriorityDefault); - _worldPacket << float(QuickJoinConfig.ThrottleLfgListPriorityAbove); - _worldPacket << float(QuickJoinConfig.ThrottleLfgListPriorityBelow); - _worldPacket << float(QuickJoinConfig.ThrottleLfgListIlvlScalingAbove); - _worldPacket << float(QuickJoinConfig.ThrottleLfgListIlvlScalingBelow); - _worldPacket << float(QuickJoinConfig.ThrottleRfPriorityAbove); - _worldPacket << float(QuickJoinConfig.ThrottleRfIlvlScalingAbove); - _worldPacket << float(QuickJoinConfig.ThrottleDfMaxItemLevel); - _worldPacket << float(QuickJoinConfig.ThrottleDfBestPriority); - } + _worldPacket << QuickJoinConfig; if (SessionAlert) - { - _worldPacket << int32(SessionAlert->Delay); - _worldPacket << int32(SessionAlert->Period); - _worldPacket << int32(SessionAlert->DisplayTime); - } + _worldPacket << *SessionAlert; _worldPacket << SizedString::Data(Unknown1027); - { - _worldPacket << Bits<1>(Squelch.IsSquelched); - _worldPacket << Squelch.BnetAccountGuid; - _worldPacket << Squelch.GuildGuid; - } + _worldPacket << Squelch; if (EuropaTicketSystemStatus) _worldPacket << *EuropaTicketSystemStatus; diff --git a/src/server/game/Server/Packets/SystemPackets.h b/src/server/game/Server/Packets/SystemPackets.h index 1d17c83ab6d..42d40c4cf60 100644 --- a/src/server/game/Server/Packets/SystemPackets.h +++ b/src/server/game/Server/Packets/SystemPackets.h @@ -27,6 +27,40 @@ namespace WorldPackets { namespace System { + struct SocialQueueConfig + { + bool ToastsDisabled = false; + float ToastDuration = 0.0f; + float DelayDuration = 0.0f; + float QueueMultiplier = 0.0f; + float PlayerMultiplier = 0.0f; + float PlayerFriendValue = 0.0f; + float PlayerGuildValue = 0.0f; + float ThrottleInitialThreshold = 0.0f; + float ThrottleDecayTime = 0.0f; + float ThrottlePrioritySpike = 0.0f; + float ThrottleMinThreshold = 0.0f; + float ThrottlePvPPriorityNormal = 0.0f; + float ThrottlePvPPriorityLow = 0.0f; + float ThrottlePvPHonorThreshold = 0.0f; + float ThrottleLfgListPriorityDefault = 0.0f; + float ThrottleLfgListPriorityAbove = 0.0f; + float ThrottleLfgListPriorityBelow = 0.0f; + float ThrottleLfgListIlvlScalingAbove = 0.0f; + float ThrottleLfgListIlvlScalingBelow = 0.0f; + float ThrottleRfPriorityAbove = 0.0f; + float ThrottleRfIlvlScalingAbove = 0.0f; + float ThrottleDfMaxItemLevel = 0.0f; + float ThrottleDfBestPriority = 0.0f; + }; + + struct SessionAlertConfig + { + int32 Delay = 0; + int32 Period = 0; + int32 DisplayTime = 0; + }; + struct SavedThrottleObjectState { uint32 MaxTries = 0; @@ -45,6 +79,13 @@ namespace WorldPackets SavedThrottleObjectState ThrottleState; }; + struct SquelchInfo + { + bool IsSquelched = false; + ObjectGuid BnetAccountGuid; + ObjectGuid GuildGuid; + }; + struct GameRuleValuePair { int32 Rule = 0; @@ -55,47 +96,6 @@ namespace WorldPackets class FeatureSystemStatus final : public ServerPacket { public: - struct SessionAlertConfig - { - int32 Delay = 0; - int32 Period = 0; - int32 DisplayTime = 0; - }; - - struct SocialQueueConfig - { - bool ToastsDisabled = false; - float ToastDuration = 0.0f; - float DelayDuration = 0.0f; - float QueueMultiplier = 0.0f; - float PlayerMultiplier = 0.0f; - float PlayerFriendValue = 0.0f; - float PlayerGuildValue = 0.0f; - float ThrottleInitialThreshold = 0.0f; - float ThrottleDecayTime = 0.0f; - float ThrottlePrioritySpike = 0.0f; - float ThrottleMinThreshold = 0.0f; - float ThrottlePvPPriorityNormal = 0.0f; - float ThrottlePvPPriorityLow = 0.0f; - float ThrottlePvPHonorThreshold = 0.0f; - float ThrottleLfgListPriorityDefault = 0.0f; - float ThrottleLfgListPriorityAbove = 0.0f; - float ThrottleLfgListPriorityBelow = 0.0f; - float ThrottleLfgListIlvlScalingAbove = 0.0f; - float ThrottleLfgListIlvlScalingBelow = 0.0f; - float ThrottleRfPriorityAbove = 0.0f; - float ThrottleRfIlvlScalingAbove = 0.0f; - float ThrottleDfMaxItemLevel = 0.0f; - float ThrottleDfBestPriority = 0.0f; - }; - - struct SquelchInfo - { - bool IsSquelched = false; - ObjectGuid BnetAccountGuid; - ObjectGuid GuildGuid; - }; - struct RafSystemFeatureInfo { bool Enabled = false; diff --git a/src/server/shared/Packets/ByteBuffer.cpp b/src/server/shared/Packets/ByteBuffer.cpp index c8980a93fe4..f5d6a5ab4b5 100644 --- a/src/server/shared/Packets/ByteBuffer.cpp +++ b/src/server/shared/Packets/ByteBuffer.cpp @@ -198,6 +198,7 @@ void ByteBuffer::OnInvalidPosition(size_t pos, size_t valueSize) const throw ByteBufferPositionException(pos, _storage.size(), valueSize); } +template TC_SHARED_API char ByteBuffer::read(); template TC_SHARED_API uint8 ByteBuffer::read(); template TC_SHARED_API uint16 ByteBuffer::read(); template TC_SHARED_API uint32 ByteBuffer::read(); diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h index 94c22206aa0..df6fc935a58 100644 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -18,8 +18,9 @@ #ifndef TRINITYCORE_BYTE_BUFFER_H #define TRINITYCORE_BYTE_BUFFER_H -#include "Define.h" #include "ByteConverter.h" +#include "Concepts.h" +#include "Define.h" #include #include #include @@ -50,6 +51,14 @@ public: ByteBufferInvalidValueException(char const* type, std::string_view value); }; +template +concept ByteBufferNumeric = std::same_as || std::same_as + || std::same_as || std::same_as + || std::same_as || std::same_as + || std::same_as || std::same_as + || std::same_as || std::same_as + || std::same_as || std::is_enum_v; + class TC_SHARED_API ByteBuffer { public: @@ -117,10 +126,9 @@ class TC_SHARED_API ByteBuffer _storage.clear(); } - template + template void append(T value) { - static_assert(std::is_trivially_copyable_v, "append(T) must be used with trivially copyable types"); EndianConvert(value); append(reinterpret_cast(&value), sizeof(value)); } @@ -248,10 +256,9 @@ class TC_SHARED_API ByteBuffer return value; } - template + template void put(std::size_t pos, T value) { - static_assert(std::is_trivially_copyable_v, "put(size_t, T) must be used with trivially copyable types"); EndianConvert(value); put(pos, reinterpret_cast(&value), sizeof(value)); } @@ -469,7 +476,7 @@ class TC_SHARED_API ByteBuffer return _wpos * 8 + 8 - _bitpos; } - template + template void read_skip() { read_skip(sizeof(T)); } void read_skip(size_t skip) @@ -481,7 +488,7 @@ class TC_SHARED_API ByteBuffer _rpos += skip; } - template + template T read() { ResetBitPos(); @@ -490,7 +497,7 @@ class TC_SHARED_API ByteBuffer return r; } - template + template T read(size_t pos) const { if (pos + sizeof(T) > _storage.size()) @@ -502,7 +509,7 @@ class TC_SHARED_API ByteBuffer return val; } - template + template void read(T* dest, size_t count) { static_assert(std::is_trivially_copyable_v, "read(T*, size_t) must be used with trivially copyable types"); @@ -523,8 +530,8 @@ class TC_SHARED_API ByteBuffer _rpos += len; } - template - void read(std::array& arr) + template + void read(std::array& arr) { read(arr.data(), Size); } @@ -549,6 +556,8 @@ class TC_SHARED_API ByteBuffer append(str, len); } + void ReadSkipCString(bool requireValidUtf8 = true) { (void)ReadCString(requireValidUtf8); } + std::string_view ReadCString(bool requireValidUtf8 = true); std::string_view ReadString(uint32 length, bool requireValidUtf8 = true); @@ -563,12 +572,12 @@ class TC_SHARED_API ByteBuffer { _storage.resize(newsize, 0); _rpos = 0; - _wpos = size(); + _wpos = _storage.size(); } void reserve(size_t ressize) { - if (ressize > size()) + if (ressize > _storage.size()) _storage.reserve(ressize); } @@ -577,7 +586,7 @@ class TC_SHARED_API ByteBuffer _storage.shrink_to_fit(); } - template + template void append(T const* src, size_t cnt) { #if TRINITY_ENDIAN == TRINITY_LITTLEENDIAN @@ -596,8 +605,8 @@ class TC_SHARED_API ByteBuffer append(buffer.data(), buffer.size()); } - template - void append(std::array const& arr) + template + void append(std::array const& arr) { append(arr.data(), Size); } @@ -619,30 +628,7 @@ class TC_SHARED_API ByteBuffer std::vector _storage; }; -template <> -inline std::string ByteBuffer::read() -{ - return std::string(ReadCString()); -} - -template <> -inline void ByteBuffer::read_skip() -{ - (void)ReadCString(); -} - -template <> -inline void ByteBuffer::read_skip() -{ - read_skip(); -} - -template <> -inline void ByteBuffer::read_skip() -{ - read_skip(); -} - +extern template char ByteBuffer::read(); extern template uint8 ByteBuffer::read(); extern template uint16 ByteBuffer::read(); extern template uint32 ByteBuffer::read(); @@ -654,4 +640,8 @@ extern template int64 ByteBuffer::read(); extern template float ByteBuffer::read(); extern template double ByteBuffer::read(); +template +concept HasByteBufferShiftOperators = requires(ByteBuffer& data, T const& value) { { data << value } -> std::convertible_to; } + && requires(ByteBuffer& data, T& value) { { data >> value } -> std::convertible_to; }; + #endif -- cgit v1.2.3