From 28eda522b1bef6d354d5a6b54fc0864ea503121a Mon Sep 17 00:00:00 2001 From: Shauren Date: Fri, 25 Oct 2019 19:29:52 +0200 Subject: Core/Entities: Add support for future optional updatefields --- src/server/game/Entities/Object/Object.h | 13 ++ .../game/Entities/Object/Updates/UpdateField.h | 158 +++++++++++++++++++++ 2 files changed, 171 insertions(+) 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 + inline void RemoveOptionalUpdateFieldValue(OptionalUpdateFieldSetter& setter) + { + setter.RemoveValue(); + } } class TC_GAME_API Object @@ -254,6 +260,13 @@ class TC_GAME_API Object UF::ClearDynamicUpdateFieldValues(setter); } + template + void RemoveOptionalUpdateFieldValue(UF::OptionalUpdateFieldSetter setter) + { + AddToObjectUpdateIfNeeded(); + UF::RemoveOptionalUpdateFieldValue(setter); + } + // stat system helpers template void SetUpdateFieldStatValue(UF::UpdateFieldSetter setter, typename UF::UpdateFieldSetter::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 class DynamicUpdateField; + template + class OptionalUpdateFieldBase; + + template + class OptionalUpdateField; + template struct MutableFieldReference; @@ -199,6 +205,24 @@ namespace UF std::vector& _updateMask; }; + template + struct OptionalUpdateFieldSetter + { + template + friend void RemoveOptionalUpdateFieldValue(OptionalUpdateFieldSetter& setter); + + OptionalUpdateFieldSetter(OptionalUpdateFieldBase& field) : _field(field) { } + + private: + void RemoveValue() + { + if (_field.is_initialized()) + _field.DestroyValue(); + } + + OptionalUpdateFieldBase& _field; + }; + template struct MutableFieldReference { @@ -259,6 +283,30 @@ namespace UF return { (_value.*field)._values[index] }; } + template + std::enable_if_t::value, OptionalUpdateFieldSetter> + ModifyValue(OptionalUpdateField(T::* field)) + { + _value._changesMask.Set(BlockBit); + _value._changesMask.Set(Bit); + return { _value.*field }; + } + + template + std::enable_if_t::value, + std::conditional_t::value, + MutableFieldReference, + std::conditional_t, UpdateFieldSetter>>> + ModifyValue(OptionalUpdateField(T::* field), uint32) + { + if (!(_value.*field).is_initialized()) + (_value.*field).ConstructValue(); + + _value._changesMask.Set(BlockBit); + _value._changesMask.Set(Bit); + return { *((_value.*field)._value) }; + } + template std::enable_if_t::value && !std::is_array::value, std::conditional_t, UpdateFieldSetter>> @@ -342,6 +390,14 @@ namespace UF return { uf._values[index] }; } + template + MutableFieldReference ModifyValue(OptionalUpdateField(Derived::* field)) + { + _changesMask.Set(BlockBit); + _changesMask.Set(Bit); + return { *((static_cast(this)->*field)._value) }; + } + template void ClearChanged(UpdateField(Derived::*)) { @@ -362,6 +418,12 @@ namespace UF (static_cast(this)->*field).ClearChanged(index); } + template + void ClearChanged(OptionalUpdateField(Derived::*)) + { + _changesMask.Reset(Bit); + } + protected: template void ClearChangesMask(UpdateField& field) @@ -411,6 +473,22 @@ namespace UF field._values[i].ClearChangesMask(); } + template + void ClearChangesMask(OptionalUpdateField& field) + { + ClearChangesMask(field, std::is_base_of{}); + } + + template + void ClearChangesMask(OptionalUpdateField&, std::false_type) { } + + template + void ClearChangesMask(OptionalUpdateField& field, std::true_type) + { + if (field.is_initialized()) + field._value->ClearChangesMask(); + } + UpdateMask _changesMask; }; @@ -603,6 +681,86 @@ namespace UF std::vector _updateMask; }; + template + class OptionalUpdateFieldBase + { + template + friend struct MutableFieldReference; + + template + friend class HasChangesMask; + + template + friend struct OptionalUpdateFieldSetter; + + public: + using ValueType = T; + using IsLarge = std::integral_constant; + using StorageType = std::conditional_t, Optional>; + + ~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 + class OptionalUpdateField : public OptionalUpdateFieldBase + { + }; + template struct ViewerDependentValueTag { -- cgit v1.2.3