diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Object/Object.h | 13 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Updates/UpdateField.h | 158 |
2 files changed, 171 insertions, 0 deletions
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index d5fb9f3c73f..bede9c2bc6b 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -115,6 +115,12 @@ namespace UF { setter.Clear(); } + + template<typename T> + inline void RemoveOptionalUpdateFieldValue(OptionalUpdateFieldSetter<T>& setter) + { + setter.RemoveValue(); + } } class TC_GAME_API Object @@ -254,6 +260,13 @@ class TC_GAME_API Object UF::ClearDynamicUpdateFieldValues(setter); } + template<typename T> + void RemoveOptionalUpdateFieldValue(UF::OptionalUpdateFieldSetter<T> setter) + { + AddToObjectUpdateIfNeeded(); + UF::RemoveOptionalUpdateFieldValue(setter); + } + // stat system helpers template<typename T> void SetUpdateFieldStatValue(UF::UpdateFieldSetter<T> setter, typename UF::UpdateFieldSetter<T>::ValueType value) diff --git a/src/server/game/Entities/Object/Updates/UpdateField.h b/src/server/game/Entities/Object/Updates/UpdateField.h index 635b98a8e1a..aaed95d4469 100644 --- a/src/server/game/Entities/Object/Updates/UpdateField.h +++ b/src/server/game/Entities/Object/Updates/UpdateField.h @@ -46,6 +46,12 @@ namespace UF template<typename T, uint32 BlockBit, uint32 Bit> class DynamicUpdateField; + template<typename T> + class OptionalUpdateFieldBase; + + template<typename T, uint32 BlockBit, uint32 Bit> + class OptionalUpdateField; + template<typename T, bool PublicSet> struct MutableFieldReference; @@ -199,6 +205,24 @@ namespace UF std::vector<uint32>& _updateMask; }; + template<typename T> + struct OptionalUpdateFieldSetter + { + template<typename F> + friend void RemoveOptionalUpdateFieldValue(OptionalUpdateFieldSetter<F>& setter); + + OptionalUpdateFieldSetter(OptionalUpdateFieldBase<T>& field) : _field(field) { } + + private: + void RemoveValue() + { + if (_field.is_initialized()) + _field.DestroyValue(); + } + + OptionalUpdateFieldBase<T>& _field; + }; + template<typename T, bool PublicSet> struct MutableFieldReference { @@ -259,6 +283,30 @@ namespace UF return { (_value.*field)._values[index] }; } + template<typename V, uint32 BlockBit, uint32 Bit, typename U = T> + std::enable_if_t<std::is_base_of<HasChangesMaskTag, U>::value, OptionalUpdateFieldSetter<V>> + ModifyValue(OptionalUpdateField<V, BlockBit, Bit>(T::* field)) + { + _value._changesMask.Set(BlockBit); + _value._changesMask.Set(Bit); + return { _value.*field }; + } + + template<typename V, uint32 BlockBit, uint32 Bit, typename U = T> + std::enable_if_t<std::is_base_of<HasChangesMaskTag, U>::value, + std::conditional_t<std::is_base_of<IsUpdateFieldStructureTag, V>::value, + MutableFieldReference<V, PublicSet>, + std::conditional_t<PublicSet, UpdateFieldPublicSetter<V>, UpdateFieldSetter<V>>>> + ModifyValue(OptionalUpdateField<V, BlockBit, Bit>(T::* field), uint32) + { + if (!(_value.*field).is_initialized()) + (_value.*field).ConstructValue(); + + _value._changesMask.Set(BlockBit); + _value._changesMask.Set(Bit); + return { *((_value.*field)._value) }; + } + template<typename V, typename U = T> std::enable_if_t<!std::is_base_of<HasChangesMaskTag, U>::value && !std::is_array<V>::value, std::conditional_t<PublicSet, UpdateFieldPublicSetter<V>, UpdateFieldSetter<V>>> @@ -343,6 +391,14 @@ namespace UF } template<typename Derived, typename T, uint32 BlockBit, uint32 Bit> + MutableFieldReference<T, false> ModifyValue(OptionalUpdateField<T, BlockBit, Bit>(Derived::* field)) + { + _changesMask.Set(BlockBit); + _changesMask.Set(Bit); + return { *((static_cast<Derived*>(this)->*field)._value) }; + } + + template<typename Derived, typename T, uint32 BlockBit, uint32 Bit> void ClearChanged(UpdateField<T, BlockBit, Bit>(Derived::*)) { _changesMask.Reset(Bit); @@ -362,6 +418,12 @@ namespace UF (static_cast<Derived*>(this)->*field).ClearChanged(index); } + template<typename Derived, typename T, uint32 BlockBit, uint32 Bit> + void ClearChanged(OptionalUpdateField<T, BlockBit, Bit>(Derived::*)) + { + _changesMask.Reset(Bit); + } + protected: template<typename T, uint32 BlockBit, uint32 Bit> void ClearChangesMask(UpdateField<T, BlockBit, Bit>& field) @@ -411,6 +473,22 @@ namespace UF field._values[i].ClearChangesMask(); } + template<typename T, uint32 BlockBit, uint32 Bit> + void ClearChangesMask(OptionalUpdateField<T, BlockBit, Bit>& field) + { + ClearChangesMask(field, std::is_base_of<HasChangesMaskTag, T>{}); + } + + template<typename T, uint32 BlockBit, uint32 Bit> + void ClearChangesMask(OptionalUpdateField<T, BlockBit, Bit>&, std::false_type) { } + + template<typename T, uint32 BlockBit, uint32 Bit> + void ClearChangesMask(OptionalUpdateField<T, BlockBit, Bit>& field, std::true_type) + { + if (field.is_initialized()) + field._value->ClearChangesMask(); + } + UpdateMask<Bits> _changesMask; }; @@ -604,6 +682,86 @@ namespace UF }; template<typename T> + class OptionalUpdateFieldBase + { + template<typename F, bool PublicSet> + friend struct MutableFieldReference; + + template<std::size_t Bits> + friend class HasChangesMask; + + template<typename F> + friend struct OptionalUpdateFieldSetter; + + public: + using ValueType = T; + using IsLarge = std::integral_constant<bool, sizeof(void*) * 3 < sizeof(T)>; + using StorageType = std::conditional_t<IsLarge::value, std::add_pointer_t<T>, Optional<T>>; + + ~OptionalUpdateFieldBase() + { + DestroyValue(); + } + + bool is_initialized() const + { + return !!_value; + } + + operator T const& () const + { + return *_value; + } + T const* operator->() const + { + return &(*_value); + } + T const& operator*() const + { + return *_value; + } + + private: + void ConstructValue() + { + ConstructValue(IsLarge{}); + } + + void ConstructValue(std::false_type) + { + _value.emplace(); + } + + void ConstructValue(std::true_type) + { + _value = new T(); + } + + void DestroyValue() + { + DestroyValue(IsLarge{}); + } + + void DestroyValue(std::false_type) + { + _value.reset(); + } + + void DestroyValue(std::true_type) + { + delete _value; + _value = nullptr; + } + + StorageType _value = { }; + }; + + template<typename T, uint32 BlockBit, uint32 Bit> + class OptionalUpdateField : public OptionalUpdateFieldBase<T> + { + }; + + template<typename T> struct ViewerDependentValueTag { using ValueType = T; |