mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-13 03:32:28 -04:00
Core/Objects: Implement SetUpdateField
This commit is contained in:
@@ -127,15 +127,27 @@ namespace UF
|
||||
}
|
||||
|
||||
template<typename K, typename V>
|
||||
inline void RemoveMapUpdateFieldValue(MapUpdateFieldSetter<K, V>& setter, std::type_identity_t<K> const& key)
|
||||
inline bool RemoveMapUpdateFieldValue(MapUpdateFieldSetter<K, V>& setter, std::type_identity_t<K> const& key)
|
||||
{
|
||||
setter.RemoveKey(key);
|
||||
return setter.RemoveKey(key);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void RemoveOptionalUpdateFieldValue(OptionalUpdateFieldSetter<T>& setter)
|
||||
inline bool InsertSetUpdateFieldValue(SetUpdateFieldSetter<T>& setter, std::type_identity_t<T> const& key)
|
||||
{
|
||||
setter.RemoveValue();
|
||||
return setter.Insert(key);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool RemoveSetUpdateFieldValue(SetUpdateFieldSetter<T>& setter, std::type_identity_t<T> const& key)
|
||||
{
|
||||
return setter.Remove(key);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool RemoveOptionalUpdateFieldValue(OptionalUpdateFieldSetter<T>& setter)
|
||||
{
|
||||
return setter.RemoveValue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,13 +262,6 @@ class TC_GAME_API BaseEntity
|
||||
UF::RemoveDynamicUpdateFieldValue(setter, index);
|
||||
}
|
||||
|
||||
template<typename K, typename V>
|
||||
void RemoveMapUpdateFieldValue(UF::MapUpdateFieldSetter<K, V> setter, std::type_identity_t<K> const& key)
|
||||
{
|
||||
AddToObjectUpdateIfNeeded();
|
||||
UF::RemoveMapUpdateFieldValue(setter, key);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ClearDynamicUpdateFieldValues(UF::DynamicUpdateFieldSetter<T> setter)
|
||||
{
|
||||
@@ -264,11 +269,32 @@ class TC_GAME_API BaseEntity
|
||||
UF::ClearDynamicUpdateFieldValues(setter);
|
||||
}
|
||||
|
||||
template<typename K, typename V>
|
||||
void RemoveMapUpdateFieldValue(UF::MapUpdateFieldSetter<K, V> setter, std::type_identity_t<K> const& key)
|
||||
{
|
||||
if (UF::RemoveMapUpdateFieldValue(setter, key))
|
||||
AddToObjectUpdateIfNeeded();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void InsertSetUpdateFieldValue(UF::SetUpdateFieldSetter<T> setter, std::type_identity_t<T> const& key)
|
||||
{
|
||||
if (UF::InsertSetUpdateFieldValue(setter, key))
|
||||
AddToObjectUpdateIfNeeded();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void RemoveSetUpdateFieldValue(UF::SetUpdateFieldSetter<T> setter, std::type_identity_t<T> const& key)
|
||||
{
|
||||
if (UF::RemoveSetUpdateFieldValue(setter, key))
|
||||
AddToObjectUpdateIfNeeded();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void RemoveOptionalUpdateFieldValue(UF::OptionalUpdateFieldSetter<T> setter)
|
||||
{
|
||||
AddToObjectUpdateIfNeeded();
|
||||
UF::RemoveOptionalUpdateFieldValue(setter);
|
||||
if (UF::RemoveOptionalUpdateFieldValue(setter))
|
||||
AddToObjectUpdateIfNeeded();
|
||||
}
|
||||
|
||||
// stat system helpers
|
||||
|
||||
@@ -71,6 +71,12 @@ namespace UF
|
||||
template<typename K, typename V, int32 BlockBit, uint32 Bit>
|
||||
class MapUpdateField;
|
||||
|
||||
template<typename T>
|
||||
class SetUpdateFieldBase;
|
||||
|
||||
template<typename T, int32 BlockBit, uint32 Bit>
|
||||
class SetUpdateField;
|
||||
|
||||
template<typename T>
|
||||
class OptionalUpdateFieldBase;
|
||||
|
||||
@@ -260,34 +266,70 @@ namespace UF
|
||||
struct MapUpdateFieldSetter
|
||||
{
|
||||
template<typename F, typename G>
|
||||
friend void RemoveMapUpdateFieldValue(MapUpdateFieldSetter<F, G>& setter, std::type_identity_t<F> const& key);
|
||||
friend bool RemoveMapUpdateFieldValue(MapUpdateFieldSetter<F, G>& setter, std::type_identity_t<F> const& key);
|
||||
|
||||
MapUpdateFieldSetter(std::unordered_map<K, V>& values) : _values(values) { }
|
||||
|
||||
private:
|
||||
void RemoveKey(K const& key)
|
||||
bool RemoveKey(K const& key)
|
||||
{
|
||||
auto itr = _values.find(key);
|
||||
if (itr != _values.end())
|
||||
{
|
||||
itr->second.state = MapUpdateFieldState::Deleted;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unordered_map<K, V>& _values;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct SetUpdateFieldSetter
|
||||
{
|
||||
template<typename F>
|
||||
friend bool RemoveSetUpdateFieldValue(SetUpdateFieldSetter<F>& setter, std::type_identity_t<F> const& key);
|
||||
|
||||
SetUpdateFieldSetter(std::unordered_map<T, MapUpdateFieldState>& values) : _values(values) { }
|
||||
|
||||
private:
|
||||
bool Insert(T const& key)
|
||||
{
|
||||
return _values.emplace(key, MapUpdateFieldState::Changed).second;
|
||||
}
|
||||
|
||||
bool Remove(T const& key)
|
||||
{
|
||||
auto itr = _values.find(key);
|
||||
if (itr != _values.end())
|
||||
{
|
||||
itr->second = MapUpdateFieldState::Deleted;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unordered_map<T, MapUpdateFieldState>& _values;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct OptionalUpdateFieldSetter
|
||||
{
|
||||
template<typename F>
|
||||
friend void RemoveOptionalUpdateFieldValue(OptionalUpdateFieldSetter<F>& setter);
|
||||
friend bool RemoveOptionalUpdateFieldValue(OptionalUpdateFieldSetter<F>& setter);
|
||||
|
||||
OptionalUpdateFieldSetter(OptionalUpdateFieldBase<T>& field) : _field(field) { }
|
||||
|
||||
private:
|
||||
void RemoveValue()
|
||||
bool RemoveValue()
|
||||
{
|
||||
if (_field.has_value())
|
||||
{
|
||||
_field.DestroyValue();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
OptionalUpdateFieldBase<T>& _field;
|
||||
@@ -397,6 +439,16 @@ namespace UF
|
||||
return { itr->second.value };
|
||||
}
|
||||
|
||||
template<typename V, int32 BlockBit, uint32 Bit>
|
||||
SetUpdateFieldSetter<V> ModifyValue(SetUpdateField<V, BlockBit, Bit>(T::* field))
|
||||
{
|
||||
if constexpr (BlockBit >= 0)
|
||||
_value._changesMask.Set(BlockBit);
|
||||
|
||||
_value._changesMask.Set(Bit);
|
||||
return { (_value.*field)._values };
|
||||
}
|
||||
|
||||
template<typename V, int32 BlockBit, uint32 Bit>
|
||||
OptionalUpdateFieldSetter<V> ModifyValue(OptionalUpdateField<V, BlockBit, Bit>(T::* field))
|
||||
{
|
||||
@@ -639,6 +691,21 @@ namespace UF
|
||||
itr->second.state = MapUpdateFieldState::Changed;
|
||||
}
|
||||
|
||||
template<typename Derived, typename T, int32 BlockBit, uint32 Bit>
|
||||
void MarkChanged(SetUpdateField<T, BlockBit, Bit>(Derived::* field), std::type_identity_t<T> const& key)
|
||||
{
|
||||
static_assert(std::is_base_of_v<Base, Derived>, "Given field argument must belong to the same structure as this HasChangesMask");
|
||||
|
||||
if constexpr (BlockBit >= 0)
|
||||
_changesMask.Set(BlockBit);
|
||||
|
||||
_changesMask.Set(Bit);
|
||||
SetUpdateField<T, BlockBit, Bit>& uf = (static_cast<Derived*>(this)->*field);
|
||||
auto itr = uf._values.find(key);
|
||||
if (itr != uf._values.end() && itr->second == MapUpdateFieldState::Unchanged)
|
||||
itr->second = MapUpdateFieldState::Changed;
|
||||
}
|
||||
|
||||
template<typename Derived, typename T, int32 BlockBit, uint32 Bit>
|
||||
void MarkChanged(OptionalUpdateField<T, BlockBit, Bit>(Derived::*))
|
||||
{
|
||||
@@ -704,6 +771,17 @@ namespace UF
|
||||
itr->second.state = MapUpdateFieldState::Unchanged;
|
||||
}
|
||||
|
||||
template<typename Derived, typename T, int32 BlockBit, uint32 Bit>
|
||||
void ClearChanged(SetUpdateField<T, BlockBit, Bit>(Derived::* field), std::type_identity_t<T> const& key)
|
||||
{
|
||||
static_assert(std::is_base_of_v<Base, Derived>, "Given field argument must belong to the same structure as this HasChangesMask");
|
||||
|
||||
SetUpdateField<T, BlockBit, Bit>& uf = (static_cast<Derived*>(this)->*field);
|
||||
auto itr = uf._values.find(key);
|
||||
if (itr != uf._values.end() && itr->second == MapUpdateFieldState::Changed)
|
||||
itr->second = MapUpdateFieldState::Unchanged;
|
||||
}
|
||||
|
||||
template<typename Derived, typename T, int32 BlockBit, uint32 Bit>
|
||||
void ClearChanged(OptionalUpdateField<T, BlockBit, Bit>(Derived::*))
|
||||
{
|
||||
@@ -759,7 +837,7 @@ namespace UF
|
||||
break;
|
||||
case MapUpdateFieldState::Changed:
|
||||
if constexpr (std::is_base_of_v<HasChangesMaskTag, K>)
|
||||
itr->first.ClearChangesMask();
|
||||
const_cast<K&>(itr->first).ClearChangesMask();
|
||||
|
||||
if constexpr (std::is_base_of_v<HasChangesMaskTag, V>)
|
||||
itr->second.value.ClearChangesMask();
|
||||
@@ -777,6 +855,32 @@ namespace UF
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline void ClearChangesMask(SetUpdateFieldBase<T>& field)
|
||||
{
|
||||
for (auto itr = field._values.begin(); itr != field._values.end(); )
|
||||
{
|
||||
switch (itr->second)
|
||||
{
|
||||
case MapUpdateFieldState::Unchanged:
|
||||
break;
|
||||
case MapUpdateFieldState::Changed:
|
||||
if constexpr (std::is_base_of_v<HasChangesMaskTag, T>)
|
||||
const_cast<T&>(itr->first).ClearChangesMask();
|
||||
|
||||
itr->second = MapUpdateFieldState::Unchanged;
|
||||
break;
|
||||
case MapUpdateFieldState::Deleted:
|
||||
itr = field._values.erase(itr++);
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline void ClearChangesMask(OptionalUpdateFieldBase<T>& field)
|
||||
{
|
||||
@@ -1085,6 +1189,55 @@ namespace UF
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class SetUpdateFieldBase : public IsUpdateFieldHolderTag
|
||||
{
|
||||
template<typename F, bool PublicSet>
|
||||
friend struct MutableFieldReferenceWithChangesMask;
|
||||
|
||||
template<typename F, bool PublicSet>
|
||||
friend struct MutableFieldReferenceNoChangesMask;
|
||||
|
||||
template<typename F, bool PublicSet>
|
||||
friend struct MutableNestedFieldReference;
|
||||
|
||||
template<std::size_t Bits>
|
||||
friend class HasChangesMask;
|
||||
|
||||
public:
|
||||
using key_type = T;
|
||||
using mapped_type = MapUpdateFieldState;
|
||||
using value_type = std::pair<key_type const, mapped_type>;
|
||||
|
||||
typename std::unordered_map<T, MapUpdateFieldState>::const_iterator begin() const
|
||||
{
|
||||
return _values.begin();
|
||||
}
|
||||
|
||||
typename std::unordered_map<T, MapUpdateFieldState>::const_iterator end() const
|
||||
{
|
||||
return _values.end();
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return _values.empty();
|
||||
}
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
return _values.size();
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<T, MapUpdateFieldState> _values;
|
||||
};
|
||||
|
||||
template<typename T, int32 BlockBit, uint32 Bit>
|
||||
class SetUpdateField : public SetUpdateFieldBase<T>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class OptionalUpdateFieldBase : public IsUpdateFieldHolderTag
|
||||
{
|
||||
|
||||
@@ -107,7 +107,7 @@ inline void WriteMapFieldUpdate(MapUpdateFieldBase<K, V> const& map, ByteBuffer&
|
||||
++changesCount;
|
||||
|
||||
if constexpr (std::is_base_of_v<IsUpdateFieldStructureTag, K>)
|
||||
k.WriteUpdate(data, true /*ignoreChangesMask*/, owner, receiver);
|
||||
k.WriteUpdate(data, false, owner, receiver);
|
||||
else
|
||||
data << k;
|
||||
|
||||
@@ -116,7 +116,7 @@ inline void WriteMapFieldUpdate(MapUpdateFieldBase<K, V> const& map, ByteBuffer&
|
||||
continue;
|
||||
|
||||
if constexpr (std::is_base_of_v<IsUpdateFieldStructureTag, V>)
|
||||
v.value.WriteUpdate(data, true /*ignoreChangesMask*/, owner, receiver); // client bug replaces unchanged values with 0/default so send everything as if it changed
|
||||
v.value.WriteUpdate(data, false, owner, receiver);
|
||||
else
|
||||
data << v.value;
|
||||
}
|
||||
@@ -124,6 +124,50 @@ inline void WriteMapFieldUpdate(MapUpdateFieldBase<K, V> const& map, ByteBuffer&
|
||||
data.put<uint16>(changesCountPos, changesCount);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename O>
|
||||
inline void WriteSetFieldCreate(SetUpdateFieldBase<T> const& set, ByteBuffer& data, O const* owner, Player const* receiver)
|
||||
{
|
||||
data << uint32(set.size());
|
||||
for (auto const& [k, _] : set)
|
||||
{
|
||||
if constexpr (std::is_base_of_v<IsUpdateFieldStructureTag, T>)
|
||||
k.WriteCreate(data, owner, receiver);
|
||||
else
|
||||
data << k;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename O>
|
||||
inline void WriteSetFieldUpdate(SetUpdateFieldBase<T> const& set, ByteBuffer& data, bool ignoreChangesMask, O const* owner, Player const* receiver)
|
||||
{
|
||||
data << uint8(ignoreChangesMask ? 1 : 0);
|
||||
if (ignoreChangesMask)
|
||||
UF::WriteSetFieldCreate(set, data, owner, receiver);
|
||||
else
|
||||
{
|
||||
uint16 changesCount = 0;
|
||||
size_t changesCountPos = data.wpos();
|
||||
data << uint16(changesCount);
|
||||
|
||||
for (auto const& [k, state] : set)
|
||||
{
|
||||
if (state == MapUpdateFieldState::Unchanged)
|
||||
continue;
|
||||
|
||||
++changesCount;
|
||||
|
||||
if constexpr (std::is_base_of_v<IsUpdateFieldStructureTag, T>)
|
||||
k.WriteUpdate(data, false, owner, receiver);
|
||||
else
|
||||
data << k;
|
||||
|
||||
data << uint8(state);
|
||||
}
|
||||
|
||||
data.put<uint16>(changesCountPos, changesCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TRINITYCORE_UPDATE_FIELD_IMPL_H
|
||||
|
||||
Reference in New Issue
Block a user