TrinityCore
Loading...
Searching...
No Matches
WowCSEntityDefinitions.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
19#include "Errors.h"
20#include <algorithm>
21
22namespace WowCS
23{
24void EntityFragmentsHolder::Add(EntityFragment fragment, bool update, void const* data /*= nullptr*/)
25{
26 ASSERT(Count < Ids.size());
27
28 auto insertSorted = []<size_t N>(std::array<EntityFragment, N>& arr, uint8& count, EntityFragment f)
29 {
30 auto end = arr.begin() + count;
31 auto where = std::ranges::lower_bound(arr.begin(), end, f);
32 if (*where == f)
33 return std::pair(where, false);
34
35 std::ranges::move_backward(where, end, end + 1);
36 ++count;
37 *where = f;
38 return std::pair(where, true);
39 };
40
41 if (!insertSorted(Ids, Count, fragment).second)
42 return;
43
44 if (IsUpdateableFragment(fragment))
45 {
47 ASSERT(data);
48
49 auto insertedItr = insertSorted(Updateable.Ids, UpdateableCount, fragment).first;
50 std::ptrdiff_t index = std::ranges::distance(Updateable.Ids.begin(), insertedItr);
51 uint8 maskLowPart = ContentsChangedMask & ((1 << index) - 1);
52 uint8 maskHighPart = (ContentsChangedMask & ~((1 << index) - 1)) << (1 + IsIndirectFragment(fragment));
53 ContentsChangedMask = maskLowPart | maskHighPart;
54 for (uint8 i = 0, maskIndex = 0; i < UpdateableCount; ++i)
55 {
56 Updateable.Masks[i] = 1 << maskIndex++;
58 {
59 ContentsChangedMask |= Updateable.Masks[i]; // set the first bit to true to activate fragment
60 ++maskIndex;
61 Updateable.Masks[i] <<= 1;
62 }
63 }
64
65 auto insertAtIndex = []<typename T, size_t N>(std::array<T, N>& arr, uint8 size, std::ptrdiff_t i, T value)
66 {
67 std::ranges::move_backward(arr.begin() + i, arr.begin() + size - 1, arr.begin() + size);
68 arr[i] = value;
69 };
70
71 insertAtIndex(Updateable.Data, UpdateableCount, index, data);
72 }
73
74 if (update)
75 IdsChanged = true;
76}
77
79{
80 auto removeSorted = []<size_t N>(std::array<EntityFragment, N>& arr, uint8& count, EntityFragment f)
81 {
82 auto end = arr.begin() + count;
83 auto where = std::ranges::find(arr.begin(), end, f);
84 if (where != end)
85 {
86 *std::ranges::move(where + 1, end, where).out = EntityFragment::End;
87 --count;
88 return std::pair(where, true);
89 }
90 return std::pair(where, false);
91 };
92
93 if (!removeSorted(Ids, Count, fragment).second)
94 return;
95
96 if (IsUpdateableFragment(fragment))
97 {
98 auto [removedItr, removed] = removeSorted(Updateable.Ids, UpdateableCount, fragment);
99 if (removed)
100 {
101 std::ptrdiff_t index = std::ranges::distance(Updateable.Ids.begin(), removedItr);
102 uint8 maskLowPart = ContentsChangedMask & ((1 << index) - 1);
103 uint8 maskHighPart = (ContentsChangedMask & ~((1 << index) - 1)) >> (1 + IsIndirectFragment(fragment));
104 ContentsChangedMask = maskLowPart | maskHighPart;
105 for (uint8 i = 0, maskIndex = 0; i < UpdateableCount; ++i)
106 {
107 Updateable.Masks[i] = 1 << maskIndex++;
109 {
110 ++maskIndex;
111 Updateable.Masks[i] <<= 1;
112 }
113 }
114
115 auto removeAtIndex = []<typename T, size_t N>(std::array<T, N>& arr, uint8 oldSize, std::ptrdiff_t i, std::type_identity_t<T> value)
116 {
117 *std::ranges::move(arr.begin() + i + 1, arr.begin() + oldSize, arr.begin() + i).out = value;
118 };
119
120 uint8 oldSize = UpdateableCount + 1;
121 removeAtIndex(Updateable.Data, oldSize, index, nullptr);
122 }
123 }
124
125 IdsChanged = true;
126}
127
129
132{
133 static EntityFragmentInfos entityFragmentInfo;
134
135 std::size_t index = static_cast<std::size_t>(fragment);
136 entityFragmentInfo.SerializeCreate[index] = serializeCreate;
137 entityFragmentInfo.SerializeUpdate[index] = serializeUpdate;
138 entityFragmentInfo.IsChanged[index] = isChanged;
139 entityFragmentInfo.ClearChanged[index] = clearChanged;
140}
141
146}
uint8_t uint8
Definition Define.h:156
#define ASSERT
Definition Errors.h:80
bool(*)(void const *rawFragmentData) EntityFragmentIsChangedFn
EntityFragmentInfos const * EntityFragmentInfo
constexpr bool IsUpdateableFragment(EntityFragment frag)
void(*)(void const *rawFragmentData) EntityFragmentClearChangedFn
void(*)(void const *rawFragmentData, UF::UpdateFieldFlag flags, ByteBuffer &data, Player const *target, BaseEntity const *baseEntity) EntityFragmentSerializeFn
constexpr bool IsIndirectFragment(EntityFragment frag)
std::array< EntityFragmentSerializeFn, N > SerializeUpdate
std::array< EntityFragmentIsChangedFn, N > IsChanged
std::array< EntityFragmentClearChangedFn, N > ClearChanged
std::array< EntityFragmentSerializeFn, N > SerializeCreate
static void Register(EntityFragment fragment, EntityFragmentSerializeFn serializeCreate, EntityFragmentSerializeFn serializeUpdate, EntityFragmentIsChangedFn isChanged, EntityFragmentClearChangedFn clearChanged)
void Remove(EntityFragment fragment)
std::array< EntityFragment, 8 > Ids
void Add(EntityFragment fragment, bool update, void const *data=nullptr)