|
1 |
| -using System; |
2 |
| -using WowPacketParser.Enums; |
| 1 | +using WowPacketParser.Enums; |
3 | 2 | using WowPacketParser.Misc;
|
4 |
| -using WowPacketParser.Store; |
5 |
| -using WowPacketParser.SQL; |
6 |
| -using System.Linq; |
| 3 | +using System.Collections.Generic; |
| 4 | +using System.Text; |
| 5 | +using WowPacketParser.Parsing.Proto; |
| 6 | +using WowPacketParser.Proto; |
| 7 | +using WowPacketParser.PacketStructures; |
| 8 | +using System.IO; |
| 9 | +using Org.BouncyCastle.Crypto.Digests; |
7 | 10 |
|
8 | 11 | namespace WowPacketParser.SQL.Builders
|
9 | 12 | {
|
10 |
| - [BuilderClass] |
11 |
| - public static class Movement |
| 13 | + [ProtoBuilderClass] |
| 14 | + public class Movement : BaseProtoQueryBuilder |
12 | 15 | {
|
13 |
| - [BuilderMethod] |
14 |
| - public static string MovementData() |
| 16 | + private struct Waypoint |
15 | 17 | {
|
16 |
| - if (!Settings.SQLOutputFlag.HasAnyFlagBit(SQLOutput.creature_movement)) |
17 |
| - return string.Empty; |
| 18 | + public Vec3 Position { get; init; } |
| 19 | + public float Orientation { get; init; } |
| 20 | + public bool Point { get; init; } |
| 21 | + } |
18 | 22 |
|
19 |
| - string output = "SET @MOVID = 0;\n"; |
20 |
| - int pathIdCounter = 0; |
21 |
| - if (Settings.TargetedProject == TargetedProject.Cmangos) |
22 |
| - { |
23 |
| - string nodeSql = "INSERT INTO waypoint_path (PathId, Point, PositionX, PositionY, PositionZ, Orientation, WaitTime, ScriptId, Comment) VALUES\n"; |
24 |
| - foreach (var data in Storage.CreatureMovement.ToList()) |
25 |
| - { |
26 |
| - var creatureMovement = data.Item1; |
27 |
| - if (creatureMovement.Waypoints.Count == 0) |
28 |
| - continue; |
| 23 | + public enum PathType |
| 24 | + { |
| 25 | + None = 0, // pathfinding |
| 26 | + ExactPath = 1, // sent fully |
| 27 | + ExactPathFlying = 2, // sent fully + flying flag |
| 28 | + ExactPathFlyingCyclic = 3, // sent fully + flying flag + cyclic flag |
| 29 | + ExactPathAndJump = 4, // sent fully + parabolic movement at the end |
| 30 | + Invalid = 100, |
| 31 | + } |
29 | 32 |
|
30 |
| - string creatureName = SQLUtil.EscapeString(StoreGetters.GetName(Utilities.ObjectTypeToStore(creatureMovement.GUID.GetObjectType()), (int)creatureMovement.GUID.GetEntry())); |
31 |
| - output += "-- " + $"GUID: {creatureMovement.GUID} PathType: {creatureMovement.Type}" + "\n" + $"INSERT INTO waypoint_path_name(PathId, Name) VALUES(@MOVID + {pathIdCounter},'{creatureName}');\n" + nodeSql; |
| 33 | + private class AggregatedPaths |
| 34 | + { |
| 35 | + public List<Path> Paths { get; set; } = new(); |
| 36 | + public int PointCount { get; set; } = 0; |
| 37 | + } |
32 | 38 |
|
33 |
| - int pointIdCounter = 1; |
34 |
| - int actualPoint = 1; |
35 |
| - foreach (var node in creatureMovement.Waypoints) |
36 |
| - { |
37 |
| - bool finalP = creatureMovement.Destination == null && creatureMovement.Waypoints.Count == actualPoint; |
38 |
| - ++actualPoint; |
39 |
| - float ori = finalP ? (creatureMovement.FinalOrientation != null ? creatureMovement.FinalOrientation.Value : 100f) : 100f; |
40 |
| - if (node.Point == false) |
41 |
| - { |
42 |
| - if (Settings.SkipIntermediatePoints == true) |
43 |
| - continue; |
44 |
| - output += "-- "; |
45 |
| - } |
| 39 | + private class Path |
| 40 | + { |
| 41 | + public List<Waypoint> Waypoints { get; init; } |
| 42 | + public PathType Type { get; init; } |
| 43 | + } |
46 | 44 |
|
47 |
| - output += $"(@MOVID + {pathIdCounter}, '{pointIdCounter}', '{node.Position.X}', '{node.Position.Y}', '{node.Position.Z}', '{ori}', '0', '0', NULL)"; |
48 |
| - |
49 |
| - if (!finalP) |
50 |
| - output += ",\n"; |
51 |
| - else |
52 |
| - output += ";\n\n"; |
53 |
| - |
54 |
| - ++pointIdCounter; |
55 |
| - } |
| 45 | + private Dictionary<UniversalGuid, AggregatedPaths> pathsPerGuid = new(); |
56 | 46 |
|
57 |
| - if (creatureMovement.Destination != null) |
58 |
| - { |
59 |
| - float ori = creatureMovement.FinalOrientation != null ? creatureMovement.FinalOrientation.Value : 100f; |
60 |
| - output += $"(@MOVID + {pathIdCounter}, '{pointIdCounter}', '{creatureMovement.Destination.Position.X}', '{creatureMovement.Destination.Position.Y}', '{creatureMovement.Destination.Position.Z}', '{ori}', '0', '0', NULL);\n"; |
61 |
| - } |
| 47 | + public override bool IsEnabled() => Settings.SQLOutputFlag.HasAnyFlagBit(SQLOutput.creature_movement) && |
| 48 | + Settings.TargetedProject is TargetedProject.Cmangos or TargetedProject.TrinityCore; |
62 | 49 |
|
63 |
| - ++pathIdCounter; |
64 |
| - } |
| 50 | + private PathType GetMovementType(PacketMonsterMove packet) |
| 51 | + { |
| 52 | + PathType flags = PathType.None; |
| 53 | + if (packet.Flags.HasFlag(UniversalSplineFlag.EnterCycle) || packet.Flags.HasFlag(UniversalSplineFlag.Cyclic)) |
| 54 | + flags = PathType.ExactPathFlyingCyclic; |
| 55 | + else if (packet.Flags.HasFlag(UniversalSplineFlag.Flying)) |
| 56 | + flags = PathType.ExactPathFlying; |
| 57 | + else if (packet.Flags.HasFlag(UniversalSplineFlag.UncompressedPath)) |
| 58 | + flags = PathType.ExactPath; |
| 59 | + else if (packet.LookTarget != null) |
| 60 | + flags = PathType.Invalid; |
| 61 | + else if (packet.Jump != null && packet.Jump.StartTime > 0) |
| 62 | + flags = PathType.ExactPathAndJump; |
| 63 | + return flags; |
| 64 | + } |
| 65 | + |
| 66 | + protected override VoidType Process(PacketBase basePacket, PacketMonsterMove packet) |
| 67 | + { |
| 68 | + if (packet.PackedPoints.Count == 0 && packet.Points.Count == 0) |
| 69 | + return default; |
| 70 | + |
| 71 | + var movementType = GetMovementType(packet); |
| 72 | + if (movementType == PathType.Invalid) |
| 73 | + return default; |
| 74 | + |
| 75 | + Path path = new Path() |
| 76 | + { |
| 77 | + Waypoints = new List<Waypoint>(), |
| 78 | + Type = movementType |
| 79 | + }; |
| 80 | + |
| 81 | + for (var index = 0; index < packet.PackedPoints.Count; index++) |
| 82 | + { |
| 83 | + var node = packet.PackedPoints[index]; |
| 84 | + bool finalP = packet.Destination == null && packet.PackedPoints.Count - 1 != index; |
| 85 | + path.Waypoints.Add(new Waypoint() |
| 86 | + { |
| 87 | + Position = node, |
| 88 | + Orientation = 100, |
| 89 | + Point = false |
| 90 | + }); |
| 91 | + } |
| 92 | + |
| 93 | + for (var index = 0; index < packet.Points.Count; index++) |
| 94 | + { |
| 95 | + var node = packet.Points[index]; |
| 96 | + path.Waypoints.Add(new Waypoint() |
| 97 | + { |
| 98 | + Position = node, |
| 99 | + Orientation = 100, |
| 100 | + Point = true |
| 101 | + }); |
65 | 102 | }
|
66 |
| - else if (Settings.TargetedProject == TargetedProject.TrinityCore) |
| 103 | + |
| 104 | + bool dest = false; |
| 105 | + if (packet.Destination != null && !(packet.Destination.X == 0 && packet.Destination.Y == 0 && packet.Destination.Z == 0)) |
67 | 106 | {
|
68 |
| - string nodeSql = "INSERT INTO waypoint_path_node (PathId, NodeId, PositionX, PositionY, PositionZ, Orientation, Delay) VALUES\n"; |
69 |
| - foreach (var data in Storage.CreatureMovement.ToList()) |
| 107 | + float ori = packet.HasLookOrientation ? packet.LookOrientation : 100f; |
| 108 | + path.Waypoints.Add(new Waypoint() |
70 | 109 | {
|
71 |
| - var creatureMovement = data.Item1; |
72 |
| - if (creatureMovement.Waypoints.Count == 0) |
73 |
| - continue; |
| 110 | + Position = packet.Destination, |
| 111 | + Orientation = ori, |
| 112 | + Point = true |
| 113 | + }); |
| 114 | + dest = true; |
| 115 | + } |
74 | 116 |
|
75 |
| - string commentInformation = $"GUID: {creatureMovement.GUID} PathType: {creatureMovement.Type}"; |
76 |
| - output += "-- " + commentInformation + "\n"; |
77 |
| - output += nodeSql; |
| 117 | + if (!pathsPerGuid.TryGetValue(packet.Mover, out var pathList)) |
| 118 | + { |
| 119 | + pathList = new AggregatedPaths(); |
| 120 | + pathsPerGuid.Add(packet.Mover, pathList); |
| 121 | + } |
| 122 | + pathList.Paths.Add(path); |
| 123 | + if (Settings.SkipIntermediatePoints == true) |
| 124 | + pathList.PointCount += packet.Points.Count + (dest ? 1 : 0); |
| 125 | + else |
| 126 | + pathList.PointCount += path.Waypoints.Count; |
78 | 127 |
|
79 |
| - int pointIdCounter = 1; |
80 |
| - int actualPoint = 1; |
81 |
| - foreach (var node in creatureMovement.Waypoints) |
| 128 | + return default; |
| 129 | + } |
| 130 | + |
| 131 | + protected override string GenerateQuery() |
| 132 | + { |
| 133 | + StringBuilder output = new(); |
| 134 | + output.AppendLine("SET @MOVID = 0;"); |
| 135 | + int pathIdCounter = 0; |
| 136 | + foreach (var (mover, paths) in pathsPerGuid) |
| 137 | + { |
| 138 | + string commentInformation = $"GUID: {mover.ToWowParserString()}"; |
| 139 | + output.AppendLine("-- " + commentInformation); |
| 140 | + if (Settings.TargetedProject == TargetedProject.Cmangos) |
| 141 | + { |
| 142 | + output.AppendLine($"INSERT INTO waypoint_path_name(PathId, Name) VALUES(@MOVID + {pathIdCounter},'{SQLUtil.EscapeString(StoreGetters.GetName(Utilities.ObjectTypeToStore(mover.Type.ToObjectType()), (int)mover.Entry))}');"); |
| 143 | + output.AppendLine("INSERT INTO waypoint_path (PathId, Point, PositionX, PositionY, PositionZ, Orientation, WaitTime, ScriptId, Comment) VALUES"); |
| 144 | + } |
| 145 | + else if (Settings.TargetedProject == TargetedProject.TrinityCore) |
| 146 | + { |
| 147 | + output.AppendLine("INSERT INTO waypoint_path_node (PathId, NodeId, PositionX, PositionY, PositionZ, Orientation, Delay) VALUES"); |
| 148 | + } |
| 149 | + int pointIdCounter = 1; |
| 150 | + foreach (var path in paths.Paths) |
| 151 | + { |
| 152 | + foreach (var node in path.Waypoints) |
82 | 153 | {
|
83 |
| - bool finalP = creatureMovement.Destination == null && creatureMovement.Waypoints.Count == actualPoint; |
84 |
| - ++actualPoint; |
85 |
| - float ori = finalP ? (creatureMovement.FinalOrientation != null ? creatureMovement.FinalOrientation.Value : 100f) : 100f; |
86 | 154 | if (node.Point == false)
|
87 | 155 | {
|
88 | 156 | if (Settings.SkipIntermediatePoints == true)
|
89 | 157 | continue;
|
90 |
| - output += "-- "; |
| 158 | + output.Append("-- "); |
91 | 159 | }
|
92 |
| - output += $"(@MOVID + {pathIdCounter}, '{pointIdCounter}', '{node.Position.X}', '{node.Position.Y}', '{node.Position.Z}', '{ori}')"; |
93 | 160 |
|
94 |
| - if (!finalP) |
95 |
| - output += ",\n"; |
| 161 | + var isLast = pointIdCounter == paths.PointCount; |
| 162 | + if (Settings.TargetedProject == TargetedProject.Cmangos) |
| 163 | + output.Append($"(@MOVID + {pathIdCounter}, '{pointIdCounter}', '{node.Position.X}', '{node.Position.Y}', '{node.Position.Z}', '{node.Orientation}', '0', '0', NULL)"); |
| 164 | + else if (Settings.TargetedProject == TargetedProject.TrinityCore) |
| 165 | + output.Append($"(@MOVID + {pathIdCounter}, '{pointIdCounter}', '{node.Position.X}', '{node.Position.Y}', '{node.Position.Z}', '{node.Orientation}')"); |
| 166 | + |
| 167 | + if (!isLast) |
| 168 | + output.Append(","); |
96 | 169 | else
|
97 |
| - output += ";\n\n"; |
| 170 | + output.Append(";"); |
98 | 171 |
|
99 |
| - ++pointIdCounter; |
100 |
| - } |
| 172 | + if (pointIdCounter == 1) |
| 173 | + output.Append($" -- PathType: {path.Type}"); |
101 | 174 |
|
102 |
| - if (creatureMovement.Destination != null) |
103 |
| - { |
104 |
| - float ori = creatureMovement.FinalOrientation != null ? creatureMovement.FinalOrientation.Value : 100f; |
105 |
| - output += $"(@MOVID + {pathIdCounter}, '{pointIdCounter}', '{creatureMovement.Destination.Position.X}', '{creatureMovement.Destination.Position.Y}', '{creatureMovement.Destination.Position.Z}', '{ori}', '0', '0', NULL);\n\n"; |
| 175 | + if (isLast) |
| 176 | + output.AppendLine(); |
| 177 | + |
| 178 | + ++pointIdCounter; |
106 | 179 | }
|
107 | 180 |
|
108 |
| - ++pathIdCounter; |
| 181 | + output.AppendLine(); |
109 | 182 | }
|
110 |
| - } |
111 | 183 |
|
112 |
| - return output; |
| 184 | + ++pathIdCounter; |
| 185 | + } |
| 186 | + return output.ToString(); |
113 | 187 | }
|
114 | 188 | }
|
115 | 189 | }
|
0 commit comments