Fixed crashes and errors when loading into world.
This commit is contained in:
@@ -47,7 +47,7 @@ namespace Game.AI
|
|||||||
SmartEscortState _escortState;
|
SmartEscortState _escortState;
|
||||||
uint _escortNPCFlags;
|
uint _escortNPCFlags;
|
||||||
uint _escortInvokerCheckTimer;
|
uint _escortInvokerCheckTimer;
|
||||||
WaypointPath _path;
|
WaypointPath _path = new();
|
||||||
uint _currentWaypointNode;
|
uint _currentWaypointNode;
|
||||||
bool _waypointReached;
|
bool _waypointReached;
|
||||||
uint _waypointPauseTimer;
|
uint _waypointPauseTimer;
|
||||||
@@ -132,7 +132,6 @@ namespace Game.AI
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_path = new WaypointPath();
|
|
||||||
_path.id = path.id;
|
_path.id = path.id;
|
||||||
_path.nodes.AddRange(path.nodes);
|
_path.nodes.AddRange(path.nodes);
|
||||||
foreach (WaypointNode waypoint in _path.nodes)
|
foreach (WaypointNode waypoint in _path.nodes)
|
||||||
@@ -802,6 +801,7 @@ namespace Game.AI
|
|||||||
{
|
{
|
||||||
me.SetWalk(!run);
|
me.SetWalk(!run);
|
||||||
_run = run;
|
_run = run;
|
||||||
|
|
||||||
foreach (var node in _path.nodes)
|
foreach (var node in _path.nodes)
|
||||||
node.moveType = run ? WaypointMoveType.Run : WaypointMoveType.Walk;
|
node.moveType = run ? WaypointMoveType.Run : WaypointMoveType.Walk;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2435,7 +2435,7 @@ namespace Game.AI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SmartScriptHolder : IComparer<SmartScriptHolder>
|
public class SmartScriptHolder : IComparable<SmartScriptHolder>
|
||||||
{
|
{
|
||||||
public const uint DefaultPriority = uint.MaxValue;
|
public const uint DefaultPriority = uint.MaxValue;
|
||||||
|
|
||||||
@@ -2478,17 +2478,17 @@ namespace Game.AI
|
|||||||
return $"Entry {EntryOrGuid} SourceType {GetScriptType()} Event {EventId} Action {GetActionType()}";
|
return $"Entry {EntryOrGuid} SourceType {GetScriptType()} Event {EventId} Action {GetActionType()}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Compare(SmartScriptHolder left, SmartScriptHolder right)
|
public int CompareTo(SmartScriptHolder other)
|
||||||
{
|
{
|
||||||
int result = left.Priority.CompareTo(right.Priority);
|
int result = Priority.CompareTo(other.Priority);
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
result = left.EntryOrGuid.CompareTo(right.EntryOrGuid);
|
result = EntryOrGuid.CompareTo(other.EntryOrGuid);
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
result = left.SourceType.CompareTo(right.SourceType);
|
result = SourceType.CompareTo(other.SourceType);
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
result = left.EventId.CompareTo(right.EventId);
|
result = EventId.CompareTo(other.EventId);
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
result = left.Link.CompareTo(right.Link);
|
result = Link.CompareTo(other.Link);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -370,7 +370,7 @@ namespace Game.DataStorage
|
|||||||
foreach (var entry in TaxiPathNodeStorage.Values)
|
foreach (var entry in TaxiPathNodeStorage.Values)
|
||||||
TaxiPathNodesByPath[entry.PathID][entry.NodeIndex] = entry;
|
TaxiPathNodesByPath[entry.PathID][entry.NodeIndex] = entry;
|
||||||
|
|
||||||
var taxiMaskSize = TaxiNodesStorage.GetNumRows() + 1;
|
var taxiMaskSize = ((TaxiNodesStorage.GetNumRows() - 1) / 8) + 1;
|
||||||
TaxiNodesMask = new byte[taxiMaskSize];
|
TaxiNodesMask = new byte[taxiMaskSize];
|
||||||
OldContinentsNodesMask = new byte[taxiMaskSize];
|
OldContinentsNodesMask = new byte[taxiMaskSize];
|
||||||
HordeTaxiNodesMask = new byte[taxiMaskSize];
|
HordeTaxiNodesMask = new byte[taxiMaskSize];
|
||||||
|
|||||||
@@ -3559,7 +3559,7 @@ namespace Game.Entities
|
|||||||
uint _stateChangeProgress;
|
uint _stateChangeProgress;
|
||||||
List<uint> _stopFrames = new();
|
List<uint> _stopFrames = new();
|
||||||
bool _autoCycleBetweenStopFrames;
|
bool _autoCycleBetweenStopFrames;
|
||||||
TimeTracker _positionUpdateTimer;
|
TimeTracker _positionUpdateTimer = new();
|
||||||
List<WorldObject> _passengers = new();
|
List<WorldObject> _passengers = new();
|
||||||
|
|
||||||
static TimeSpan PositionUpdateInterval = TimeSpan.FromMilliseconds(50);
|
static TimeSpan PositionUpdateInterval = TimeSpan.FromMilliseconds(50);
|
||||||
|
|||||||
@@ -382,7 +382,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
public void ClearChangesMask<U>(OptionalUpdateField<U> updateField) where U : new()
|
public void ClearChangesMask<U>(OptionalUpdateField<U> updateField) where U : new()
|
||||||
{
|
{
|
||||||
if (typeof(IHasChangesMask).IsAssignableFrom(typeof(U)))
|
if (typeof(IHasChangesMask).IsAssignableFrom(typeof(U)) && updateField.HasValue())
|
||||||
((IHasChangesMask)updateField._value).ClearChangesMask();
|
((IHasChangesMask)updateField._value).ClearChangesMask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2981,9 +2981,9 @@ namespace Game.Entities
|
|||||||
public bool IsPermanentWorldObject() { return m_isWorldObject; }
|
public bool IsPermanentWorldObject() { return m_isWorldObject; }
|
||||||
|
|
||||||
public ITransport GetTransport() { return m_transport; }
|
public ITransport GetTransport() { return m_transport; }
|
||||||
public T GetTransport<T>() where T : ITransport
|
public T GetTransport<T>() where T : class, ITransport
|
||||||
{
|
{
|
||||||
return (T)m_transport;
|
return m_transport as T;
|
||||||
}
|
}
|
||||||
public float GetTransOffsetX() { return m_movementInfo.transport.pos.GetPositionX(); }
|
public float GetTransOffsetX() { return m_movementInfo.transport.pos.GetPositionX(); }
|
||||||
public float GetTransOffsetY() { return m_movementInfo.transport.pos.GetPositionY(); }
|
public float GetTransOffsetY() { return m_movementInfo.transport.pos.GetPositionY(); }
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ namespace Game.Entities
|
|||||||
|
|
||||||
public void InitTaxiNodesForLevel(Race race, Class chrClass, uint level)
|
public void InitTaxiNodesForLevel(Race race, Class chrClass, uint level)
|
||||||
{
|
{
|
||||||
|
m_taximask = new byte[((CliDB.TaxiNodesStorage.GetNumRows() - 1) / 8) + 1];
|
||||||
|
|
||||||
// class specific initial known nodes
|
// class specific initial known nodes
|
||||||
if (chrClass == Class.Deathknight)
|
if (chrClass == Class.Deathknight)
|
||||||
{
|
{
|
||||||
@@ -105,6 +107,8 @@ namespace Game.Entities
|
|||||||
|
|
||||||
public void LoadTaxiMask(string data)
|
public void LoadTaxiMask(string data)
|
||||||
{
|
{
|
||||||
|
m_taximask = new byte[((CliDB.TaxiNodesStorage.GetNumRows() - 1) / 8) + 1];
|
||||||
|
|
||||||
var split = new StringArray(data, ' ');
|
var split = new StringArray(data, ' ');
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|||||||
@@ -127,11 +127,11 @@ namespace Game
|
|||||||
|
|
||||||
public static void ChooseCreatureFlags(CreatureTemplate cInfo, out ulong npcFlag, out uint unitFlags, out uint unitFlags2, out uint unitFlags3, out uint dynamicFlags, CreatureData data = null)
|
public static void ChooseCreatureFlags(CreatureTemplate cInfo, out ulong npcFlag, out uint unitFlags, out uint unitFlags2, out uint unitFlags3, out uint dynamicFlags, CreatureData data = null)
|
||||||
{
|
{
|
||||||
npcFlag = data?.npcflag != 0 ? data.npcflag : cInfo.Npcflag;
|
npcFlag = data != null && data.npcflag != 0 ? data.npcflag : cInfo.Npcflag;
|
||||||
unitFlags = data?.unit_flags != 0 ? data.unit_flags : (uint)cInfo.UnitFlags;
|
unitFlags = data != null && data.unit_flags != 0 ? data.unit_flags : (uint)cInfo.UnitFlags;
|
||||||
unitFlags2 = data?.unit_flags2 != 0 ? data.unit_flags2 : cInfo.UnitFlags2;
|
unitFlags2 = data != null && data.unit_flags2 != 0 ? data.unit_flags2 : cInfo.UnitFlags2;
|
||||||
unitFlags3 = data?.unit_flags3 != 0 ? data.unit_flags3 : cInfo.UnitFlags3;
|
unitFlags3 = data != null && data.unit_flags3 != 0 ? data.unit_flags3 : cInfo.UnitFlags3;
|
||||||
dynamicFlags = data?.dynamicflags != 0 ? data.dynamicflags : cInfo.DynamicFlags;
|
dynamicFlags = data != null && data.dynamicflags != 0 ? data.dynamicflags : cInfo.DynamicFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ResponseCodes CheckPlayerName(string name, Locale locale, bool create = false)
|
public static ResponseCodes CheckPlayerName(string name, Locale locale, bool create = false)
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ namespace Game.Maps
|
|||||||
for (; pauseItr < pauses.Count; ++pauseItr)
|
for (; pauseItr < pauses.Count; ++pauseItr)
|
||||||
{
|
{
|
||||||
var pausePointIndex = pathPoints.IndexOf(pauses[pauseItr]);
|
var pausePointIndex = pathPoints.IndexOf(pauses[pauseItr]);
|
||||||
if (pausePointIndex == -1) // last point is a "fake" spline point, its position can never be reached so transport cannot stop there
|
if (pausePointIndex == pathPoints.Count - 1) // last point is a "fake" spline point, its position can never be reached so transport cannot stop there
|
||||||
break;
|
break;
|
||||||
|
|
||||||
for (; eventItr < events.Count; ++eventItr)
|
for (; eventItr < events.Count; ++eventItr)
|
||||||
@@ -254,10 +254,11 @@ namespace Game.Maps
|
|||||||
movementTime = legTimeAccel(length1);
|
movementTime = legTimeAccel(length1);
|
||||||
|
|
||||||
leg.Duration += movementTime;
|
leg.Duration += movementTime;
|
||||||
var segment = leg.Segments[pauseItr];
|
TransportPathSegment segment = new();
|
||||||
segment.SegmentEndArrivalTimestamp = leg.Duration + delaySum;
|
segment.SegmentEndArrivalTimestamp = leg.Duration + delaySum;
|
||||||
segment.Delay = pathPoints[pausePointIndex].Delay * Time.InMilliseconds;
|
segment.Delay = pathPoints[pausePointIndex].Delay * Time.InMilliseconds;
|
||||||
segment.DistanceFromLegStartAtEnd = splineLengthToCurrentNode;
|
segment.DistanceFromLegStartAtEnd = splineLengthToCurrentNode;
|
||||||
|
leg.Segments.Add(segment);
|
||||||
delaySum += pathPoints[pausePointIndex].Delay * Time.InMilliseconds;
|
delaySum += pathPoints[pausePointIndex].Delay * Time.InMilliseconds;
|
||||||
splineLengthToPreviousNode = splineLengthToCurrentNode;
|
splineLengthToPreviousNode = splineLengthToCurrentNode;
|
||||||
}
|
}
|
||||||
@@ -304,10 +305,11 @@ namespace Game.Maps
|
|||||||
|
|
||||||
leg.StartTimestamp = totalTime;
|
leg.StartTimestamp = totalTime;
|
||||||
leg.Duration += splineTime + delaySum;
|
leg.Duration += splineTime + delaySum;
|
||||||
var pauseSegment = leg.Segments[pauseItr];
|
TransportPathSegment pauseSegment = new();
|
||||||
pauseSegment.SegmentEndArrivalTimestamp = leg.Duration;
|
pauseSegment.SegmentEndArrivalTimestamp = leg.Duration;
|
||||||
pauseSegment.Delay = 0;
|
pauseSegment.Delay = 0;
|
||||||
pauseSegment.DistanceFromLegStartAtEnd = leg.Spline.Length();
|
pauseSegment.DistanceFromLegStartAtEnd = leg.Spline.Length();
|
||||||
|
leg.Segments.Add(pauseSegment);
|
||||||
totalTime += leg.Segments[pauseItr].SegmentEndArrivalTimestamp + leg.Segments[pauseItr].Delay;
|
totalTime += leg.Segments[pauseItr].SegmentEndArrivalTimestamp + leg.Segments[pauseItr].Delay;
|
||||||
|
|
||||||
for (var i = 0; i < leg.Segments.Count; ++i)
|
for (var i = 0; i < leg.Segments.Count; ++i)
|
||||||
@@ -378,13 +380,14 @@ namespace Game.Maps
|
|||||||
|
|
||||||
public void AddPathNodeToTransport(uint transportEntry, uint timeSeg, TransportAnimationRecord node)
|
public void AddPathNodeToTransport(uint transportEntry, uint timeSeg, TransportAnimationRecord node)
|
||||||
{
|
{
|
||||||
TransportAnimation animNode = new();
|
if (!_transportAnimations.ContainsKey(transportEntry))
|
||||||
|
_transportAnimations[transportEntry] = new();
|
||||||
|
|
||||||
|
TransportAnimation animNode = _transportAnimations[transportEntry];
|
||||||
if (animNode.TotalTime < timeSeg)
|
if (animNode.TotalTime < timeSeg)
|
||||||
animNode.TotalTime = timeSeg;
|
animNode.TotalTime = timeSeg;
|
||||||
|
|
||||||
animNode.Path[timeSeg] = node;
|
animNode.Path[timeSeg] = node;
|
||||||
|
|
||||||
_transportAnimations[transportEntry] = animNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddPathRotationToTransport(uint transportEntry, uint timeSeg, TransportRotationRecord node)
|
public void AddPathRotationToTransport(uint transportEntry, uint timeSeg, TransportRotationRecord node)
|
||||||
@@ -531,7 +534,7 @@ namespace Game.Maps
|
|||||||
public List<TransportPathLeg> PathLegs = new();
|
public List<TransportPathLeg> PathLegs = new();
|
||||||
public List<TransportPathEvent> Events = new();
|
public List<TransportPathEvent> Events = new();
|
||||||
|
|
||||||
public List<uint> MapIds = new();
|
public HashSet<uint> MapIds = new();
|
||||||
public bool InInstance;
|
public bool InInstance;
|
||||||
|
|
||||||
public Position ComputePosition(uint time, out TransportMovementState moveState, out int legIndex)
|
public Position ComputePosition(uint time, out TransportMovementState moveState, out int legIndex)
|
||||||
@@ -708,10 +711,10 @@ namespace Game.Maps
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
List<uint> lKeys = Path.Keys.ToList();
|
List<uint> lKeys = Path.Keys.ToList();
|
||||||
int reqIndex = lKeys.IndexOf(time) - 1;
|
int reqIndex = lKeys.IndexOf(time);
|
||||||
|
|
||||||
if (reqIndex != -1)
|
if (reqIndex != -1)
|
||||||
return Path[lKeys[reqIndex]];
|
return Path[lKeys[reqIndex - 1]];
|
||||||
|
|
||||||
return Path.LastOrDefault().Value;
|
return Path.LastOrDefault().Value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1244,7 +1244,7 @@ namespace Game.Networking.Packets
|
|||||||
|
|
||||||
public override void Read()
|
public override void Read()
|
||||||
{
|
{
|
||||||
_worldPacket.WriteUInt32(Ticks);
|
Ticks = _worldPacket.ReadUInt32();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -268,6 +268,47 @@ namespace Game
|
|||||||
}
|
}
|
||||||
while (result.NextRow());
|
while (result.NextRow());
|
||||||
|
|
||||||
|
// Now check for circular reference
|
||||||
|
// All pool_ids are in pool_template
|
||||||
|
foreach (var (id, poolData) in mPoolTemplate)
|
||||||
|
{
|
||||||
|
List<uint> checkedPools = new();
|
||||||
|
var poolItr = mPoolSearchMap.LookupByKey(id);
|
||||||
|
while (poolItr != 0)
|
||||||
|
{
|
||||||
|
if (poolData.MapId != -1)
|
||||||
|
{
|
||||||
|
if (mPoolTemplate[poolItr].MapId == -1)
|
||||||
|
mPoolTemplate[poolItr].MapId = poolData.MapId;
|
||||||
|
|
||||||
|
if (mPoolTemplate[poolItr].MapId != poolData.MapId)
|
||||||
|
{
|
||||||
|
Log.outError(LogFilter.Sql, $"`pool_pool` has child pools on multiple maps in pool id ({poolItr}), skipped.");
|
||||||
|
mPoolPoolGroups[poolItr].RemoveOneRelation(id);
|
||||||
|
mPoolSearchMap.Remove(poolItr);
|
||||||
|
--count;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkedPools.Add(id);
|
||||||
|
if (checkedPools.Contains(poolItr))
|
||||||
|
{
|
||||||
|
string ss = "The pool(s) ";
|
||||||
|
foreach (var itr in checkedPools)
|
||||||
|
ss += $"{itr} ";
|
||||||
|
ss += $"create(s) a circular reference, which can cause the server to freeze.\nRemoving the last link between mother pool {id} and child pool {poolItr}";
|
||||||
|
Log.outError(LogFilter.Sql, ss);
|
||||||
|
mPoolPoolGroups[poolItr].RemoveOneRelation(id);
|
||||||
|
mPoolSearchMap.Remove(poolItr);
|
||||||
|
--count;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
poolItr = mPoolSearchMap.LookupByKey(poolItr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} pools in mother pools in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
|
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} pools in mother pools in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ namespace Game.Spells
|
|||||||
case AuraType.Transform:
|
case AuraType.Transform:
|
||||||
case AuraType.ModRoot2:
|
case AuraType.ModRoot2:
|
||||||
m_canBeRecalculated = false;
|
m_canBeRecalculated = false;
|
||||||
if (!m_spellInfo.ProcFlags)
|
if (m_spellInfo.ProcFlags == null)
|
||||||
break;
|
break;
|
||||||
amount = (int)(GetBase().GetUnitOwner().CountPctFromMaxHealth(10));
|
amount = (int)(GetBase().GetUnitOwner().CountPctFromMaxHealth(10));
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user