Core/Entities: Add support for future optional updatefields

This commit is contained in:
Shauren
2019-10-25 19:29:52 +02:00
parent d3bf53772b
commit 28eda522b1
2 changed files with 171 additions and 0 deletions

View File

@@ -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)

View File

@@ -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>>>
@@ -342,6 +390,14 @@ namespace UF
return { uf._values[index] };
}
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::*))
{
@@ -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;
};
@@ -603,6 +681,86 @@ namespace UF
std::vector<uint32> _updateMask;
};
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
{