diff options
-rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Object.h | 55 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Updates/UpdateField.h | 42 |
3 files changed, 59 insertions, 40 deletions
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 86e742426e0..66a9124befd 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -70,7 +70,7 @@ constexpr float VisibilityDistances[AsUnderlyingType(VisibilityDistanceType::Max MAX_VISIBILITY_DISTANCE }; -Object::Object() : m_values(this), m_scriptRef(this, NoopObjectDeleter()) +Object::Object() : m_scriptRef(this, NoopObjectDeleter()) { m_objectTypeId = TYPEID_OBJECT; m_objectType = TYPEMASK_OBJECT; diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 55d6e2e1d18..0fdeed66e7d 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -107,6 +107,30 @@ struct CreateObjectBits namespace UF { + class UpdateFieldHolder + { + public: + template<typename Derived, typename T, int32 BlockBit, uint32 Bit> + inline MutableFieldReference<T, false> ModifyValue(UpdateField<T, BlockBit, Bit>(Derived::* field)); + + template<typename Derived, typename T, int32 BlockBit, uint32 Bit> + inline void ClearChangesMask(UpdateField<T, BlockBit, Bit>(Derived::* field)); + + uint32 GetChangedObjectTypeMask() const { return _changesMask; } + + bool HasChanged(uint32 index) const { return (_changesMask & UpdateMaskHelpers::GetBlockFlag(index)) != 0; } + + inline Object* GetOwner(); + + private: + friend Object; + + // This class is tightly tied to Object::m_values member, do not construct elsewhere + UpdateFieldHolder() : _changesMask(0) { } + + uint32 _changesMask; + }; + template<typename T> inline bool SetUpdateFieldValue(UpdateFieldSetter<T>& setter, typename UpdateFieldSetter<T>::value_type&& value) { @@ -264,6 +288,7 @@ class TC_GAME_API Object Conversation* ToConversation() { if (IsConversation()) return reinterpret_cast<Conversation*>(this); else return nullptr; } Conversation const* ToConversation() const { if (IsConversation()) return reinterpret_cast<Conversation const*>(this); else return nullptr; } + friend UF::UpdateFieldHolder; UF::UpdateFieldHolder m_values; UF::UpdateField<UF::ObjectData, 0, TYPEID_OBJECT> m_objectData; @@ -425,6 +450,36 @@ class TC_GAME_API Object Object& operator=(Object&& right) = delete; }; +inline Object* UF::UpdateFieldHolder::GetOwner() +{ +#if TRINITY_COMPILER == TRINITY_COMPILER_GNU +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winvalid-offsetof" +#endif + + return reinterpret_cast<Object*>(reinterpret_cast<std::byte*>(this) - offsetof(Object, m_values)); + +#if TRINITY_COMPILER == TRINITY_COMPILER_GNU +#pragma GCC diagnostic pop +#endif +} + +template <typename Derived, typename T, int32 BlockBit, uint32 Bit> +inline UF::MutableFieldReference<T, false> UF::UpdateFieldHolder::ModifyValue(UpdateField<T, BlockBit, Bit> Derived::* field) +{ + Object* owner = GetOwner(); + _changesMask |= UpdateMaskHelpers::GetBlockFlag(Bit); + return { (static_cast<Derived*>(owner)->*field)._value }; +} + +template <typename Derived, typename T, int32 BlockBit, uint32 Bit> +inline void UF::UpdateFieldHolder::ClearChangesMask(UpdateField<T, BlockBit, Bit> Derived::* field) +{ + Object* owner = GetOwner(); + _changesMask &= ~UpdateMaskHelpers::GetBlockFlag(Bit); + (static_cast<Derived*>(owner)->*field)._value.ClearChangesMask(); +} + template <class T_VALUES, class T_FLAGS, class FLAG_TYPE, size_t ARRAY_SIZE> class FlaggedValuesArray32 { diff --git a/src/server/game/Entities/Object/Updates/UpdateField.h b/src/server/game/Entities/Object/Updates/UpdateField.h index fdad7e0d18e..ebf07df9c28 100644 --- a/src/server/game/Entities/Object/Updates/UpdateField.h +++ b/src/server/game/Entities/Object/Updates/UpdateField.h @@ -672,42 +672,6 @@ namespace UF Mask _changesMask; }; - class UpdateFieldHolder - { - public: - explicit UpdateFieldHolder(Object* owner) : _owner(owner) - { - } - - template<typename Derived, typename T, int32 BlockBit, uint32 Bit> - MutableFieldReference<T, false> ModifyValue(UpdateField<T, BlockBit, Bit>(Derived::* field)) - { - _changesMask.Set(Bit); - return { (static_cast<Derived*>(_owner)->*field)._value }; - } - - template<typename Derived, typename T, int32 BlockBit, uint32 Bit> - void ClearChangesMask(UpdateField<T, BlockBit, Bit>(Derived::* field)) - { - _changesMask.Reset(Bit); - (static_cast<Derived*>(_owner)->*field)._value.ClearChangesMask(); - } - - uint32 GetChangedObjectTypeMask() const - { - return _changesMask.GetBlock(0); - } - - bool HasChanged(uint32 index) const - { - return _changesMask[index]; - } - - private: - UpdateMask<NUM_CLIENT_OBJECT_TYPES> _changesMask; - Object* _owner; - }; - template<typename T> class UpdateFieldBase : public IsUpdateFieldHolderTag { @@ -878,7 +842,7 @@ namespace UF bool HasChanged(uint32 index) const { - return (_updateMask[index / 32] & (1 << (index % 32))) != 0; + return (_updateMask[UpdateMaskHelpers::GetBlockIndex(index)] & UpdateMaskHelpers::GetBlockFlag(index)) != 0; } void WriteUpdateMask(ByteBuffer& data, int32 bitsForSize = 32) const @@ -949,9 +913,9 @@ namespace UF return !!_value; } - operator T const& () const + operator bool const() const { - return *_value; + return has_value(); } T const* operator->() const { |