From 4c11bda5ed95dc7f95f6afabe43651f9400b1b68 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Wed, 23 May 2018 18:24:27 -0400 Subject: [PATCH] Core/WorldObject: Changed the way we store values --- .../Game/Entities/AreaTrigger/AreaTrigger.cs | 4 +- Source/Game/Entities/GameObject/GameObject.cs | 10 +- Source/Game/Entities/Object/WorldObject.cs | 144 +++++++----------- Source/Game/Entities/StatSystem.cs | 2 +- Source/Game/Entities/Unit/Unit.cs | 16 +- 5 files changed, 73 insertions(+), 103 deletions(-) diff --git a/Source/Game/Entities/AreaTrigger/AreaTrigger.cs b/Source/Game/Entities/AreaTrigger/AreaTrigger.cs index cd6842b18..8ed856d63 100644 --- a/Source/Game/Entities/AreaTrigger/AreaTrigger.cs +++ b/Source/Game/Entities/AreaTrigger/AreaTrigger.cs @@ -220,7 +220,7 @@ namespace Game.Entities _duration = newDuration; // should be sent in object create packets only - UpdateData[(int)AreaTriggerFields.Duration] = _duration; + updateValues[(int)AreaTriggerFields.Duration].SignedValue = _duration; } float GetProgress() @@ -597,7 +597,7 @@ namespace Game.Entities _spline.initLengths(); // should be sent in object create packets only - UpdateData[(int)AreaTriggerFields.TimeToTarget] = timeToTarget; + updateValues[(int)AreaTriggerFields.TimeToTarget].UnsignedValue = timeToTarget; if (IsInWorld) { diff --git a/Source/Game/Entities/GameObject/GameObject.cs b/Source/Game/Entities/GameObject/GameObject.cs index a268bf096..0264d1bc1 100644 --- a/Source/Game/Entities/GameObject/GameObject.cs +++ b/Source/Game/Entities/GameObject/GameObject.cs @@ -2129,7 +2129,7 @@ namespace Game.Entities if (m_goValue.Building.Health == 0) newState = GameObjectDestructibleState.Destroyed; - else if (m_goValue.Building.Health < m_goValue.Building.MaxHealth) + else if (m_goValue.Building.Health < m_goValue.Building.MaxHealth / 2) newState = GameObjectDestructibleState.Damaged; else if (m_goValue.Building.Health == m_goValue.Building.MaxHealth) newState = GameObjectDestructibleState.Intact; @@ -2458,7 +2458,7 @@ namespace Game.Entities for (int index = 0; index < valuesCount; ++index) { if (_fieldNotifyFlags.HasAnyFlag(flags[index]) || - ((updateType == UpdateType.Values ? _changesMask.Get(index) : HasUpdateValue(index)) && flags[index].HasAnyFlag(visibleFlag)) || + ((updateType == UpdateType.Values ? _changesMask.Get(index) : updateValues[index].UnsignedValue != 0) && flags[index].HasAnyFlag(visibleFlag)) || (index == (int)GameObjectFields.Flags && forcedFlags)) { updateMask.SetBit(index); @@ -2487,7 +2487,7 @@ namespace Game.Entities uint transportPeriod = GetTransportPeriod(); if (transportPeriod != 0) { - float timer = m_goValue.Transport.PathProgress % transportPeriod; + float timer = (float)m_goValue.Transport.PathProgress % transportPeriod; pathProgress = (short)(timer / transportPeriod * 65535.0f); } break; @@ -2512,7 +2512,7 @@ namespace Game.Entities if (isStoppableTransport) fieldBuffer.WriteUInt32(m_goValue.Transport.PathProgress); else - WriteValue(fieldBuffer, index); + fieldBuffer.WriteUInt32(updateValues[index].UnsignedValue); } else if (index == (int)GameObjectFields.Bytes1) { @@ -2529,7 +2529,7 @@ namespace Game.Entities fieldBuffer.WriteUInt32(bytes1); } else - WriteValue(fieldBuffer, index); // other cases + fieldBuffer.WriteUInt32(updateValues[index].UnsignedValue); } } diff --git a/Source/Game/Entities/Object/WorldObject.cs b/Source/Game/Entities/Object/WorldObject.cs index a8dbe0149..9571ffc76 100644 --- a/Source/Game/Entities/Object/WorldObject.cs +++ b/Source/Game/Entities/Object/WorldObject.cs @@ -87,10 +87,7 @@ namespace Game.Entities void InitValues() { - UpdateData = new Hashtable((int)valuesCount); - for (int i = 0; i < valuesCount; ++i) - UpdateData[i] = 0u; - + updateValues = new UpdateValues[valuesCount]; _changesMask = new BitArray((int)valuesCount); if (_dynamicValuesCount != 0) @@ -111,7 +108,7 @@ namespace Game.Entities public void _Create(ObjectGuid guid) { - if (UpdateData == null) + if (updateValues == null) InitValues(); SetGuidValue(ObjectFields.Guid, guid); @@ -269,39 +266,39 @@ namespace Game.Entities public int GetInt32Value(object index) { Contract.Assert((int)index < valuesCount || PrintIndexError(index, false)); - return Convert.ToInt32(UpdateData[(int)index]); + return updateValues[(int)index].SignedValue; } public uint GetUInt32Value(object index) { - Contract.Assert(Convert.ToInt32(index) < valuesCount || PrintIndexError(index, false)); - return Convert.ToUInt32(UpdateData[Convert.ToInt32(index)]); + Contract.Assert((int)index < valuesCount || PrintIndexError(index, false)); + return updateValues[(int)index].UnsignedValue; } public ulong GetUInt64Value(object index) { Contract.Assert((int)index + 1 < valuesCount || PrintIndexError(index, false)); - return (Convert.ToUInt64(UpdateData[(int)index + 1]) << 32 | (uint)UpdateData[(int)index]); + return ((ulong)updateValues[(int)index + 1].UnsignedValue << 32 | updateValues[(int)index].UnsignedValue); } public float GetFloatValue(object index) { Contract.Assert((int)index < valuesCount || PrintIndexError(index, false)); - return Convert.ToSingle(UpdateData[(int)index]); + return updateValues[(int)index].FloatValue; } public byte GetByteValue(object index, byte offset) { Contract.Assert((int)index < valuesCount || PrintIndexError(index, false)); Contract.Assert(offset < 4); - return Convert.ToByte(((uint)UpdateData[(int)index] >> (offset * 8)) & 0xFF); + return (byte)((updateValues[(int)index].UnsignedValue >> (offset * 8)) & 0xFF); } public ushort GetUInt16Value(object index, byte offset) { Contract.Assert((int)index < valuesCount || PrintIndexError(index, false)); Contract.Assert(offset < 2); - return Convert.ToUInt16(((uint)UpdateData[(int)index] >> (offset * 16)) & 0xFFFF); + return (ushort)((updateValues[(int)index].UnsignedValue >> (offset * 16)) & 0xFFFF); } public ObjectGuid GetGuidValue(object index) @@ -828,10 +825,10 @@ namespace Game.Entities for (int index = 0; index < valuesCount; ++index) { if (Convert.ToBoolean(_fieldNotifyFlags & flags[index]) || - ((updatetype == UpdateType.Values ? _changesMask.Get(index) : HasUpdateValue(index)) && Convert.ToBoolean(flags[index] & visibleFlag))) + ((updatetype == UpdateType.Values ? _changesMask.Get(index) : updateValues[index].UnsignedValue != 0) && Convert.ToBoolean(flags[index] & visibleFlag))) { updateMask.SetBit(index); - WriteValue(fieldBuffer, index); + fieldBuffer.WriteUInt32(updateValues[index].UnsignedValue); } } @@ -882,28 +879,6 @@ namespace Game.Entities data.WriteBytes(fieldBuffer); } - public void WriteValue(ByteBuffer data, int index) - { - switch (UpdateData[index].GetType().Name) - { - default: - case "UInt32": - data.WriteUInt32(UpdateData[index]); - break; - case "Single": - data.WriteFloat((float)UpdateData[index]); - break; - case "Int32": - data.WriteInt32((int)UpdateData[index]); - break; - } - } - - public bool HasUpdateValue(int index) - { - return UpdateData.ContainsKey(index); - } - public void AddToObjectUpdateIfNeeded() { if (IsInWorld && !m_objectUpdated) @@ -1068,7 +1043,7 @@ namespace Game.Entities { if (uint.TryParse(lines[index], out uint value)) { - UpdateData[(int)startOffset + index] = value; + updateValues[(int)startOffset + index].UnsignedValue = value; _changesMask.Set((int)(startOffset + index), true); } } @@ -1078,9 +1053,9 @@ namespace Game.Entities { Contract.Assert((int)index < valuesCount || PrintIndexError(index, true)); - if (Convert.ToInt32(UpdateData[(int)index]) != value) + if (updateValues[(int)index].SignedValue != value) { - UpdateData[(int)index] = value; + updateValues[(int)index].SignedValue = value; _changesMask.Set((int)index, true); AddToObjectUpdateIfNeeded(); @@ -1092,9 +1067,9 @@ namespace Game.Entities int _index = Convert.ToInt32(index); Contract.Assert(_index < valuesCount || PrintIndexError(index, true)); - if (Convert.ToUInt32(UpdateData[_index]) != value) + if (updateValues[_index].UnsignedValue != value) { - UpdateData[_index] = value; + updateValues[_index].UnsignedValue = value; _changesMask.Set(_index, true); AddToObjectUpdateIfNeeded(); @@ -1103,7 +1078,9 @@ namespace Game.Entities public void UpdateUInt32Value(object index, uint value) { - UpdateData[(int)index] = value; + Contract.Assert((int)index < valuesCount || PrintIndexError(index, true)); + + updateValues[(int)index].UnsignedValue = value; _changesMask.Set((int)index, true); } @@ -1112,8 +1089,8 @@ namespace Game.Entities Contract.Assert((int)index + 1 < valuesCount || PrintIndexError(index, true)); if (GetUInt64Value(index) != value) { - UpdateData[(int)index] = MathFunctions.Pair64_LoPart(value); - UpdateData[(int)index + 1] = MathFunctions.Pair64_HiPart(value); + updateValues[(int)index].UnsignedValue = MathFunctions.Pair64_LoPart(value); + updateValues[(int)index + 1].UnsignedValue = MathFunctions.Pair64_HiPart(value); _changesMask.Set((int)index, true); _changesMask.Set((int)index + 1, true); @@ -1121,30 +1098,9 @@ namespace Game.Entities } } - public bool AddUInt64Value(object index, ulong value) - { - if (value != 0 && GetUInt64Value(index) == 0) - { - SetUInt64Value(index, value); - return true; - } - - return false; - } - - public bool RemoveUInt64Value(object index, ulong value) - { - if (value != 0 && GetUInt64Value(index) == value) - { - SetUInt64Value(index, 0); - return true; - } - - return false; - } - public bool AddGuidValue(object index, ObjectGuid value) { + Contract.Assert((int)index + 3 < valuesCount || PrintIndexError(index, true)); if (!value.IsEmpty() && GetGuidValue(index).IsEmpty()) { SetGuidValue(index, value); @@ -1156,6 +1112,7 @@ namespace Game.Entities public bool RemoveGuidValue(object index, ObjectGuid value) { + Contract.Assert((int)index + 3 < valuesCount || PrintIndexError(index, true)); if (!value.IsEmpty() && GetGuidValue(index) == value) { SetGuidValue(index, ObjectGuid.Empty); @@ -1169,9 +1126,9 @@ namespace Game.Entities { Contract.Assert((int)index < valuesCount || PrintIndexError(index, true)); - if (GetFloatValue(index) != value) + if (updateValues[(int)index].FloatValue != value) { - UpdateData[(int)index] = value; + updateValues[(int)index].FloatValue = value; _changesMask.Set((int)index, true); AddToObjectUpdateIfNeeded(); @@ -1188,10 +1145,10 @@ namespace Game.Entities return; } - if ((byte)(GetUInt32Value(index) >> (offset * 8)) != value) + if ((byte)(updateValues[(int)index].UnsignedValue >> (offset * 8)) != value) { - UpdateData[(int)index] = (uint)UpdateData[(int)index] & ~(uint)(0xFF << (offset * 8)); - UpdateData[(int)index] = (uint)UpdateData[(int)index] | (uint)value << (offset * 8); + updateValues[(int)index].UnsignedValue &= ~(uint)(0xFF << (offset * 8)); + updateValues[(int)index].UnsignedValue |= (uint)value << (offset * 8); _changesMask.Set((int)index, true); AddToObjectUpdateIfNeeded(); @@ -1210,8 +1167,8 @@ namespace Game.Entities if ((ushort)(GetUInt32Value(index) >> (offset * 16)) != value) { - UpdateData[(int)index] = (uint)UpdateData[(int)index] & ~((uint)0xFFFF << (offset * 16)); - UpdateData[(int)index] = (uint)UpdateData[(int)index] | (uint)value << (offset * 16); + updateValues[(int)index].UnsignedValue &= ~((uint)0xFFFF << (offset * 16)); + updateValues[(int)index].UnsignedValue |= (uint)value << (offset * 16); _changesMask.Set((int)index, true); AddToObjectUpdateIfNeeded(); @@ -1221,8 +1178,8 @@ namespace Game.Entities public void SetGuidValue(object index, ObjectGuid value) { Contract.Assert((int)index + 3 < valuesCount || PrintIndexError(index, true)); - if (new ObjectGuid(GetUInt64Value((int)index + 2), GetUInt64Value(index)) != value) - { + if (GetGuidValue(index) != value) + { SetUInt64Value(index, value.GetLowValue()); SetUInt64Value((int)index + 2, value.GetHighValue()); @@ -1290,12 +1247,12 @@ namespace Game.Entities public void SetFlag(object index, object newflag) { Contract.Assert((int)index < valuesCount || PrintIndexError(index, true)); - uint oldval = (uint)UpdateData[(int)index]; + uint oldval = updateValues[(int)index].UnsignedValue; uint newval = oldval | Convert.ToUInt32(newflag); if (oldval != newval) { - UpdateData[(int)index] = newval; + updateValues[(int)index].UnsignedValue = newval; _changesMask.Set((int)index, true); AddToObjectUpdateIfNeeded(); @@ -1305,14 +1262,14 @@ namespace Game.Entities public void RemoveFlag(object index, object oldFlag) { Contract.Assert((int)index < valuesCount || PrintIndexError(index, true)); - Contract.Assert(UpdateData != null); + Contract.Assert(updateValues != null); - uint oldval = (uint)UpdateData[(int)index]; + uint oldval = updateValues[(int)index].UnsignedValue; uint newval = (oldval & ~Convert.ToUInt32(oldFlag)); if (oldval != newval) { - UpdateData[(int)index] = newval; + updateValues[(int)index].UnsignedValue = newval; _changesMask.Set((int)index, true); AddToObjectUpdateIfNeeded(); } @@ -1352,9 +1309,9 @@ namespace Game.Entities return; } - if (!Convert.ToBoolean((uint)UpdateData[(int)index] >> (offset * 8) & Convert.ToUInt32(newFlag))) + if (!Convert.ToBoolean(updateValues[(int)index].UnsignedValue >> (offset * 8) & Convert.ToUInt32(newFlag))) { - UpdateData[(int)index] = (uint)UpdateData[(int)index] | Convert.ToUInt32(newFlag) << (offset * 8); + updateValues[(int)index].UnsignedValue |= Convert.ToUInt32(newFlag) << (offset * 8); _changesMask.Set((int)index, true); AddToObjectUpdateIfNeeded(); @@ -1371,9 +1328,9 @@ namespace Game.Entities return; } - if (Convert.ToBoolean((uint)UpdateData[(int)index] >> (offset * 8) & Convert.ToUInt32(oldFlag))) + if (Convert.ToBoolean(updateValues[(int)index].UnsignedValue >> (offset * 8) & Convert.ToUInt32(oldFlag))) { - UpdateData[(int)index] = (uint)UpdateData[(int)index] & ~(Convert.ToUInt32(oldFlag) << (offset * 8)); + updateValues[(int)index].UnsignedValue &= ~(Convert.ToUInt32(oldFlag) << (offset * 8)); _changesMask.Set((int)index, true); AddToObjectUpdateIfNeeded(); @@ -1392,7 +1349,7 @@ namespace Game.Entities { Contract.Assert((int)index < valuesCount || PrintIndexError(index, false)); Contract.Assert(offset < 4); - return Convert.ToBoolean((uint)UpdateData[(int)index] >> (offset * 8) & Convert.ToUInt32(flag)); + return Convert.ToBoolean(updateValues[(int)index].UnsignedValue >> (offset * 8) & Convert.ToUInt32(flag)); } public void SetFlag64(object index, object newFlag) @@ -1512,7 +1469,7 @@ namespace Game.Entities public List GetDynamicStructuredValues(object index) { var values = _dynamicValues[(int)index]; - return new List(values.DeserializeObjects()); + return values.DeserializeObjects(); } public T GetDynamicStructuredValue(object index, ushort offset) @@ -2911,7 +2868,7 @@ namespace Game.Entities protected TypeId objectTypeId { get; set; } protected UpdateFlag m_updateFlag { get; set; } - protected Hashtable UpdateData; + protected UpdateValues[] updateValues; protected uint[][] _dynamicValues; protected BitArray _changesMask { get; set; } protected Dictionary _dynamicChangesMask = new Dictionary(); @@ -2957,6 +2914,19 @@ namespace Game.Entities } } + [StructLayout(LayoutKind.Explicit)] + public struct UpdateValues + { + [FieldOffset(0)] + public uint UnsignedValue; + + [FieldOffset(0)] + public int SignedValue; + + [FieldOffset(0)] + public float FloatValue; + } + public class MovementInfo { public MovementInfo() diff --git a/Source/Game/Entities/StatSystem.cs b/Source/Game/Entities/StatSystem.cs index 1c50ea9e4..a7200fe73 100644 --- a/Source/Game/Entities/StatSystem.cs +++ b/Source/Game/Entities/StatSystem.cs @@ -237,7 +237,7 @@ namespace Game.Entities //Stats public float GetStat(Stats stat) { - return GetFloatValue(UnitFields.Stat + (int)stat); + return GetUInt32Value(UnitFields.Stat + (int)stat); } public void SetCreateStat(Stats stat, float val) { diff --git a/Source/Game/Entities/Unit/Unit.cs b/Source/Game/Entities/Unit/Unit.cs index 18dd47f3a..11f262f57 100644 --- a/Source/Game/Entities/Unit/Unit.cs +++ b/Source/Game/Entities/Unit/Unit.cs @@ -2643,7 +2643,7 @@ namespace Game.Entities { if (Convert.ToBoolean(_fieldNotifyFlags & flags[index]) || Convert.ToBoolean((flags[index] & visibleFlag) & UpdateFieldFlags.SpecialInfo) || - ((updatetype == UpdateType.Values ? _changesMask.Get(index) : HasUpdateValue(index)) && flags[index].HasAnyFlag(visibleFlag)) || + ((updatetype == UpdateType.Values ? _changesMask.Get(index) : updateValues[index].UnsignedValue != 0) && flags[index].HasAnyFlag(visibleFlag)) || (index == (int)UnitFields.AuraState && HasFlag(UnitFields.AuraState, AuraStateType.PerCasterAuraStateMask))) { updateMask.SetBit(index); @@ -2674,7 +2674,7 @@ namespace Game.Entities // Gamemasters should be always able to select units - remove not selectable flag else if (index == (int)UnitFields.Flags) { - UnitFlags appendValue = (UnitFlags)GetUInt32Value(index); + UnitFlags appendValue = (UnitFlags)updateValues[index].UnsignedValue; if (target.IsGameMaster()) appendValue &= ~UnitFlags.NotSelectable; @@ -2683,7 +2683,7 @@ namespace Game.Entities // use modelid_a if not gm, _h if gm for CREATURE_FLAG_EXTRA_TRIGGER creatures else if (index == (int)UnitFields.DisplayId) { - uint displayId = GetUInt32Value(index); + uint displayId = updateValues[index].UnsignedValue; if (creature != null) { CreatureTemplate cinfo = creature.GetCreatureTemplate(); @@ -2716,7 +2716,7 @@ namespace Game.Entities // hide lootable animation for unallowed players else if (index == (int)ObjectFields.DynamicFlags) { - UnitDynFlags dynamicFlags = (UnitDynFlags)GetUInt32Value(index) & ~UnitDynFlags.Tapped; + UnitDynFlags dynamicFlags = (UnitDynFlags)updateValues[index].UnsignedValue & ~UnitDynFlags.Tapped; if (creature != null) { @@ -2745,21 +2745,21 @@ namespace Game.Entities { if (index == (int)UnitFields.Bytes2) // Allow targetting opposite faction in party when enabled in config - fieldBuffer.WriteUInt32(GetUInt32Value(index) & ((int)UnitBytes2Flags.Sanctuary << 8)); // this flag is at public byte offset 1 !! + fieldBuffer.WriteUInt32(updateValues[index].UnsignedValue & ((int)UnitBytes2Flags.Sanctuary << 8)); // this flag is at public byte offset 1 !! else // pretend that all other HOSTILE players have own faction, to allow follow, heal, rezz (trade wont work) fieldBuffer.WriteUInt32(target.getFaction()); } else - fieldBuffer.WriteUInt32(GetUInt32Value(index)); + fieldBuffer.WriteUInt32(updateValues[index].UnsignedValue); } else - fieldBuffer.WriteUInt32(GetUInt32Value(index)); + fieldBuffer.WriteUInt32(updateValues[index].UnsignedValue); } else { // send in current format (float as float, public uint as uint32) - WriteValue(fieldBuffer, index); + fieldBuffer.WriteUInt32(updateValues[index].UnsignedValue); } } }