Core: Updated to 11.2.5.63704
Port From (https://github.com/TrinityCore/TrinityCore/commit/53068a94e88991ae7196fb247df4b7ca2e47e554)
This commit is contained in:
@@ -15,6 +15,11 @@ namespace Game.Entities
|
||||
T GetValue();
|
||||
}
|
||||
|
||||
public interface IsUpdateFieldStructureTag<T>
|
||||
{
|
||||
void WriteCreate(WorldPacket data, T owner, Player receiver);
|
||||
void WriteUpdate(WorldPacket data, bool ignoreChangesMask, T owner, Player receiver);
|
||||
}
|
||||
public interface IHasChangesMask
|
||||
{
|
||||
void ClearChangesMask();
|
||||
@@ -184,25 +189,18 @@ namespace Game.Entities
|
||||
|
||||
public class DynamicUpdateField<T> where T : new()
|
||||
{
|
||||
public List<T> _values;
|
||||
public List<uint> _updateMask;
|
||||
public List<T> _values = new();
|
||||
public List<uint> _updateMask = new();
|
||||
public int BlockBit;
|
||||
public int Bit;
|
||||
|
||||
public DynamicUpdateField()
|
||||
{
|
||||
_values = new List<T>();
|
||||
_updateMask = new List<uint>();
|
||||
|
||||
BlockBit = -1;
|
||||
Bit = -1;
|
||||
}
|
||||
|
||||
public DynamicUpdateField(int blockBit, int bit)
|
||||
{
|
||||
_values = new List<T>();
|
||||
_updateMask = new List<uint>();
|
||||
|
||||
BlockBit = blockBit;
|
||||
Bit = bit;
|
||||
}
|
||||
@@ -353,6 +351,81 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public enum MapUpdateFieldState
|
||||
{
|
||||
Unchanged = 0,
|
||||
Changed = 1,
|
||||
Deleted = 2
|
||||
}
|
||||
|
||||
public class MapUpdateField<K, V> where V : new()
|
||||
{
|
||||
Dictionary<K, (V, MapUpdateFieldState)> _values = new();
|
||||
public int BlockBit;
|
||||
public int Bit;
|
||||
|
||||
public MapUpdateField(int blockBit, int bit)
|
||||
{
|
||||
BlockBit = blockBit;
|
||||
Bit = bit;
|
||||
}
|
||||
|
||||
public bool Empty()
|
||||
{
|
||||
return _values.Empty();
|
||||
}
|
||||
|
||||
public int Size()
|
||||
{
|
||||
return _values.Count;
|
||||
}
|
||||
|
||||
public void TryAdd(K key)
|
||||
{
|
||||
if (!_values.ContainsKey(key))
|
||||
_values[key] = (new V(), MapUpdateFieldState.Changed);
|
||||
}
|
||||
|
||||
public void Remove(K key)
|
||||
{
|
||||
_values.Remove(key);
|
||||
}
|
||||
|
||||
public void MarkKeyForRemoval(K key)
|
||||
{
|
||||
var itr = _values.LookupByKey(key);
|
||||
if (itr.Item1 != null)
|
||||
itr.Item2 = MapUpdateFieldState.Deleted;
|
||||
}
|
||||
|
||||
public (V, MapUpdateFieldState) Get(K key)
|
||||
{
|
||||
if (_values.TryGetValue(key, out var value))
|
||||
return value;
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public (K, V) FindIf(Predicate<V> predicate)
|
||||
{
|
||||
var itr = _values.First(pair => { return predicate(pair.Value.Item1); });
|
||||
if (itr.Key != null)
|
||||
return (itr.Key, itr.Value.Item1);
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<K, (V, MapUpdateFieldState)>> GetEnumerator()
|
||||
{
|
||||
foreach (var obj in _values)
|
||||
yield return obj;
|
||||
}
|
||||
|
||||
public List<K> GetKeys() { return _values.Keys.ToList(); }
|
||||
|
||||
public List<(V, MapUpdateFieldState)> GetValues() { return _values.Values.ToList(); }
|
||||
}
|
||||
|
||||
public class VariantUpdateField(int blockBit, int bit)
|
||||
{
|
||||
public object _value;
|
||||
@@ -435,6 +508,33 @@ namespace Game.Entities
|
||||
|
||||
public void ClearChangesMask(UpdateFieldString updateField) { }
|
||||
|
||||
public void ClearChangesMask<K, V>(MapUpdateField<K, V> field) where V : new()
|
||||
{
|
||||
foreach (var key in field.GetKeys())
|
||||
{
|
||||
var value = field.Get(key);
|
||||
switch (value.Item2)
|
||||
{
|
||||
case MapUpdateFieldState.Unchanged:
|
||||
break;
|
||||
case MapUpdateFieldState.Changed:
|
||||
if (typeof(HasChangesMask).IsAssignableFrom(typeof(K)))
|
||||
((IHasChangesMask)key).ClearChangesMask();
|
||||
|
||||
if (typeof(HasChangesMask).IsAssignableFrom(typeof(V)))
|
||||
((IHasChangesMask)value.Item1).ClearChangesMask();
|
||||
|
||||
value.Item2 = MapUpdateFieldState.Unchanged;
|
||||
break;
|
||||
case MapUpdateFieldState.Deleted:
|
||||
field.Remove(key);
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearChangesMask<U>(OptionalUpdateField<U> updateField) where U : new()
|
||||
{
|
||||
if (typeof(IHasChangesMask).IsAssignableFrom(typeof(U)) && updateField.HasValue())
|
||||
@@ -488,6 +588,19 @@ namespace Game.Entities
|
||||
return updateField;
|
||||
}
|
||||
|
||||
public MapUpdateField<K, V> ModifyValue<K, V>(MapUpdateField<K, V> updateField) where V : new()
|
||||
{
|
||||
MarkChanged(updateField);
|
||||
return updateField;
|
||||
}
|
||||
|
||||
public V ModifyValue<K, V>(MapUpdateField<K, V> updateField, K key) where V : new()
|
||||
{
|
||||
MarkChanged(updateField);
|
||||
updateField.TryAdd(key);
|
||||
return updateField.Get(key).Item1;
|
||||
}
|
||||
|
||||
public OptionalUpdateField<U> ModifyValue<U>(OptionalUpdateField<U> updateField) where U : new()
|
||||
{
|
||||
MarkChanged(updateField);
|
||||
@@ -565,6 +678,14 @@ namespace Game.Entities
|
||||
_changesMask.Set(updateField.Bit);
|
||||
}
|
||||
|
||||
public void MarkChanged<K, V>(MapUpdateField<K, V> updateField) where V : new()
|
||||
{
|
||||
if (updateField.BlockBit >= 0)
|
||||
_changesMask.Set(updateField.BlockBit);
|
||||
|
||||
_changesMask.Set(updateField.Bit);
|
||||
}
|
||||
|
||||
public void MarkChanged<U>(OptionalUpdateField<U> updateField) where U : new()
|
||||
{
|
||||
_changesMask.Set(updateField.BlockBit);
|
||||
@@ -613,6 +734,60 @@ namespace Game.Entities
|
||||
data.WriteBits(0xFFFFFFFFu, size % 32);
|
||||
}
|
||||
|
||||
public void WriteMapFieldCreate<K, V, T>(MapUpdateField<K, V> map, WorldPacket data, T owner, Player receiver) where V : new()
|
||||
{
|
||||
data.WriteInt32(map.Size());
|
||||
foreach (var (k, (v, _)) in map)
|
||||
{
|
||||
if (typeof(IsUpdateFieldStructureTag<T>).IsAssignableFrom(typeof(K)))
|
||||
((IsUpdateFieldStructureTag<T>)k).WriteCreate(data, owner, receiver);
|
||||
else
|
||||
data.Write(k);
|
||||
|
||||
if (typeof(IsUpdateFieldStructureTag<T>).IsAssignableFrom(typeof(V)))
|
||||
((IsUpdateFieldStructureTag<T>)v).WriteCreate(data, owner, receiver);
|
||||
else
|
||||
data.Write(v);
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteMapFieldUpdate<K, V, T>(MapUpdateField<K, V> map, WorldPacket data, bool ignoreChangesMask, T owner, Player receiver) where V : new()
|
||||
{
|
||||
data.WriteUInt8((byte)(ignoreChangesMask ? 1 : 0));
|
||||
if (ignoreChangesMask)
|
||||
WriteMapFieldCreate(map, data, owner, receiver);
|
||||
else
|
||||
{
|
||||
ushort changesCount = 0;
|
||||
WorldPacket tempBuffer = new();
|
||||
|
||||
foreach (var (k, (v, state)) in map)
|
||||
{
|
||||
if (state == MapUpdateFieldState.Unchanged)
|
||||
continue;
|
||||
|
||||
++changesCount;
|
||||
|
||||
if (typeof(IsUpdateFieldStructureTag<T>).IsAssignableFrom(typeof(K)))
|
||||
((IsUpdateFieldStructureTag<T>)k).WriteUpdate(tempBuffer, true /*ignoreChangesMask*/, owner, receiver);
|
||||
else
|
||||
tempBuffer.Write(k);
|
||||
|
||||
tempBuffer.WriteUInt8((byte)state);
|
||||
if (state == MapUpdateFieldState.Deleted)
|
||||
continue;
|
||||
|
||||
if (typeof(IsUpdateFieldStructureTag<T>).IsAssignableFrom(typeof(V)))
|
||||
((IsUpdateFieldStructureTag<T>)v).WriteUpdate(tempBuffer, true /*ignoreChangesMask*/, owner, receiver); // client bug replaces unchanged values with 0/default so send everything as if it changed
|
||||
else
|
||||
tempBuffer.Write(v);
|
||||
}
|
||||
|
||||
data.WriteUInt16(changesCount);
|
||||
data.WriteBytes(tempBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
public UpdateMask GetStaticUpdateMask()
|
||||
{
|
||||
return new UpdateMask(ChangeMaskLength);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -844,6 +844,12 @@ namespace Game.Entities
|
||||
updateField.RemoveValue(index);
|
||||
}
|
||||
|
||||
public void RemoveMapUpdateFieldValue<K, V>(MapUpdateField<K, V> setter, K key) where V : new()
|
||||
{
|
||||
AddToObjectUpdateIfNeeded();
|
||||
setter.MarkKeyForRemoval(key);
|
||||
}
|
||||
|
||||
public void ClearDynamicUpdateFieldValues<T>(DynamicUpdateField<T> updateField) where T : new()
|
||||
{
|
||||
AddToObjectUpdateIfNeeded();
|
||||
|
||||
Reference in New Issue
Block a user