Skip to content

Commit

Permalink
Refactor output of movement into protobuf based
Browse files Browse the repository at this point in the history
  • Loading branch information
killerwife committed Jan 27, 2025
1 parent 8b8cd1f commit 6891387
Show file tree
Hide file tree
Showing 7 changed files with 259 additions and 151 deletions.
12 changes: 1 addition & 11 deletions WowPacketParser.Proto/PacketStructures/structures.proto
Original file line number Diff line number Diff line change
Expand Up @@ -344,15 +344,6 @@ enum UniversalSplineFlag {
Steering = 0x40000000;
}

enum CreatureMovementFlags {
NormalPathfinding = 0; // pathfinding
ExactPath = 1; // sent fully
ExactPathFlying = 2; // sent fully + flying flag
ExactPathFlyingCyclic = 3; // sent fully + flying flag + cyclic flag
ExactPathAndJump = 4; // sent fully + parabolic movement at the end
CombatMovement = 100;
}

message PacketMonsterMove {
UniversalGuid mover = 1;
Vec3 position = 2;
Expand All @@ -371,8 +362,7 @@ message PacketMonsterMove {
repeated Vec3 points = 13;
repeated Vec3 packedPoints = 14;
optional SplineJump jump = 15;
optional CreatureMovementFlags creatureMovementFlags = 16;
bool creationSpline = 17;
bool creationSpline = 16;
}

message SplineJump {
Expand Down
96 changes: 96 additions & 0 deletions WowPacketParser/PacketStructures/ProtoExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -256,5 +256,101 @@ public static CreateObjectType ToCreateObjectType(this UpdateTypeCataclysm updat
return CreateObjectType.Spawn;
throw new ArgumentOutOfRangeException();
}

public static ObjectType ToObjectType(this UniversalHighGuid highGuid)
{
switch (highGuid)
{
case UniversalHighGuid.Player:
return ObjectType.Player;
case UniversalHighGuid.DynamicObject:
return ObjectType.DynamicObject;
case UniversalHighGuid.Item:
return ObjectType.Item;
case UniversalHighGuid.GameObject:
case UniversalHighGuid.Transport:
return ObjectType.GameObject;
case UniversalHighGuid.Vehicle:
case UniversalHighGuid.Creature:
case UniversalHighGuid.Pet:
return ObjectType.Unit;
case UniversalHighGuid.AreaTrigger:
return ObjectType.AreaTrigger;
default:
return ObjectType.Object;
}
}

public static string ToWowParserString(this UniversalGuid guid)
{
if (guid.KindCase == UniversalGuid.KindOneofCase.Guid128 && (guid.Guid128.High != 0 || guid.Guid128.Low != 0))
{
var guid128 = new WowGuid128(guid.Guid128.Low, guid.Guid128.High);
return guid128.ToString();
}
else if (guid.KindCase == UniversalGuid.KindOneofCase.Guid64 && (guid.Guid64.High != 0 || guid.Guid64.Low != 0))
{
var guid64 = new WowGuid64(guid.Guid64.Low);
return guid64.ToString();
}

return "Full: 0x0";
}

public static uint GetLow(this UniversalGuid guid)
{
if (guid.KindCase == UniversalGuid.KindOneofCase.Guid128)
return (uint)(guid.Guid128.Low & 0xFFFFFFFFFF);
else if (guid.KindCase == UniversalGuid.KindOneofCase.Guid64)
{
switch (guid.Type)
{
case UniversalHighGuid.Player:
case UniversalHighGuid.DynamicObject:
case UniversalHighGuid.RaidGroup:
case UniversalHighGuid.Item:
return (uint)(guid.Guid64.Low & 0x000FFFFFFFFFFFFF);
case UniversalHighGuid.GameObject:
case UniversalHighGuid.Transport:
//case HighGuidType.MOTransport: ??
case UniversalHighGuid.Vehicle:
case UniversalHighGuid.Creature:
case UniversalHighGuid.Pet:
return (uint)(guid.Guid64.Low & 0x00000000FFFFFFFFul);
}

return (uint)(guid.Guid64.Low & 0x00000000FFFFFFFFul);
}

return 0;
}

public static uint GetEntry(this UniversalGuid128 guid)
{
return (uint)((guid.High >> 6) & 0x7FFFFF);
}

public static byte GetSubType(this UniversalGuid128 guid) => (byte)(guid.High & 0x3F);

public static ushort GetRealmId(this UniversalGuid128 guid) => (ushort)((guid.High >> 42) & 0x1FFF);

public static uint GetServerId(this UniversalGuid128 guid) => (uint)((guid.Low >> 40) & 0xFFFFFF);

public static ushort GetMapId(this UniversalGuid128 guid) => (ushort)((guid.High >> 29) & 0x1FFF);

public static bool HasEntry(this UniversalGuid guid)
{
switch (guid.Type)
{
case UniversalHighGuid.Creature:
case UniversalHighGuid.GameObject:
case UniversalHighGuid.Pet:
case UniversalHighGuid.Vehicle:
case UniversalHighGuid.AreaTrigger:
return true;
default:
return false;
}
}
}
}
236 changes: 155 additions & 81 deletions WowPacketParser/SQL/Builders/Movement.cs
Original file line number Diff line number Diff line change
@@ -1,115 +1,189 @@
using System;
using WowPacketParser.Enums;
using WowPacketParser.Enums;
using WowPacketParser.Misc;
using WowPacketParser.Store;
using WowPacketParser.SQL;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using WowPacketParser.Parsing.Proto;
using WowPacketParser.Proto;
using WowPacketParser.PacketStructures;
using System.IO;
using Org.BouncyCastle.Crypto.Digests;

namespace WowPacketParser.SQL.Builders
{
[BuilderClass]
public static class Movement
[ProtoBuilderClass]
public class Movement : BaseProtoQueryBuilder
{
[BuilderMethod]
public static string MovementData()
private struct Waypoint
{
if (!Settings.SQLOutputFlag.HasAnyFlagBit(SQLOutput.creature_movement))
return string.Empty;
public Vec3 Position { get; init; }
public float Orientation { get; init; }
public bool Point { get; init; }
}

string output = "SET @MOVID = 0;\n";
int pathIdCounter = 0;
if (Settings.TargetedProject == TargetedProject.Cmangos)
{
string nodeSql = "INSERT INTO waypoint_path (PathId, Point, PositionX, PositionY, PositionZ, Orientation, WaitTime, ScriptId, Comment) VALUES\n";
foreach (var data in Storage.CreatureMovement.ToList())
{
var creatureMovement = data.Item1;
if (creatureMovement.Waypoints.Count == 0)
continue;
public enum PathType
{
None = 0, // pathfinding
ExactPath = 1, // sent fully
ExactPathFlying = 2, // sent fully + flying flag
ExactPathFlyingCyclic = 3, // sent fully + flying flag + cyclic flag
ExactPathAndJump = 4, // sent fully + parabolic movement at the end
Invalid = 100,
}

string creatureName = SQLUtil.EscapeString(StoreGetters.GetName(Utilities.ObjectTypeToStore(creatureMovement.GUID.GetObjectType()), (int)creatureMovement.GUID.GetEntry()));
output += "-- " + $"GUID: {creatureMovement.GUID} PathType: {creatureMovement.Type}" + "\n" + $"INSERT INTO waypoint_path_name(PathId, Name) VALUES(@MOVID + {pathIdCounter},'{creatureName}');\n" + nodeSql;
private class AggregatedPaths
{
public List<Path> Paths { get; set; } = new();
public int PointCount { get; set; } = 0;
}

int pointIdCounter = 1;
int actualPoint = 1;
foreach (var node in creatureMovement.Waypoints)
{
bool finalP = creatureMovement.Destination == null && creatureMovement.Waypoints.Count == actualPoint;
++actualPoint;
float ori = finalP ? (creatureMovement.FinalOrientation != null ? creatureMovement.FinalOrientation.Value : 100f) : 100f;
if (node.Point == false)
{
if (Settings.SkipIntermediatePoints == true)
continue;
output += "-- ";
}
private class Path
{
public List<Waypoint> Waypoints { get; init; }
public PathType Type { get; init; }
}

output += $"(@MOVID + {pathIdCounter}, '{pointIdCounter}', '{node.Position.X}', '{node.Position.Y}', '{node.Position.Z}', '{ori}', '0', '0', NULL)";

if (!finalP)
output += ",\n";
else
output += ";\n\n";

++pointIdCounter;
}
private Dictionary<UniversalGuid, AggregatedPaths> pathsPerGuid = new();

if (creatureMovement.Destination != null)
{
float ori = creatureMovement.FinalOrientation != null ? creatureMovement.FinalOrientation.Value : 100f;
output += $"(@MOVID + {pathIdCounter}, '{pointIdCounter}', '{creatureMovement.Destination.Position.X}', '{creatureMovement.Destination.Position.Y}', '{creatureMovement.Destination.Position.Z}', '{ori}', '0', '0', NULL);\n";
}
public override bool IsEnabled() => Settings.SQLOutputFlag.HasAnyFlagBit(SQLOutput.creature_movement) &&
Settings.TargetedProject is TargetedProject.Cmangos or TargetedProject.TrinityCore;

++pathIdCounter;
}
private PathType GetMovementType(PacketMonsterMove packet)
{
PathType flags = PathType.None;
if (packet.Flags.HasFlag(UniversalSplineFlag.EnterCycle) || packet.Flags.HasFlag(UniversalSplineFlag.Cyclic))
flags = PathType.ExactPathFlyingCyclic;
else if (packet.Flags.HasFlag(UniversalSplineFlag.Flying))
flags = PathType.ExactPathFlying;
else if (packet.Flags.HasFlag(UniversalSplineFlag.UncompressedPath))
flags = PathType.ExactPath;
else if (packet.LookTarget != null)
flags = PathType.Invalid;
else if (packet.Jump != null && packet.Jump.StartTime > 0)
flags = PathType.ExactPathAndJump;
return flags;
}

protected override VoidType Process(PacketBase basePacket, PacketMonsterMove packet)
{
if (packet.PackedPoints.Count == 0 && packet.Points.Count == 0)
return default;

var movementType = GetMovementType(packet);
if (movementType == PathType.Invalid)
return default;

Path path = new Path()
{
Waypoints = new List<Waypoint>(),
Type = movementType
};

for (var index = 0; index < packet.PackedPoints.Count; index++)
{
var node = packet.PackedPoints[index];
bool finalP = packet.Destination == null && packet.PackedPoints.Count - 1 != index;
path.Waypoints.Add(new Waypoint()
{
Position = node,
Orientation = 100,
Point = false
});
}

for (var index = 0; index < packet.Points.Count; index++)
{
var node = packet.Points[index];
path.Waypoints.Add(new Waypoint()
{
Position = node,
Orientation = 100,
Point = true
});
}
else if (Settings.TargetedProject == TargetedProject.TrinityCore)

bool dest = false;
if (packet.Destination != null && !(packet.Destination.X == 0 && packet.Destination.Y == 0 && packet.Destination.Z == 0))
{
string nodeSql = "INSERT INTO waypoint_path_node (PathId, NodeId, PositionX, PositionY, PositionZ, Orientation, Delay) VALUES\n";
foreach (var data in Storage.CreatureMovement.ToList())
float ori = packet.HasLookOrientation ? packet.LookOrientation : 100f;
path.Waypoints.Add(new Waypoint()
{
var creatureMovement = data.Item1;
if (creatureMovement.Waypoints.Count == 0)
continue;
Position = packet.Destination,
Orientation = ori,
Point = true
});
dest = true;
}

string commentInformation = $"GUID: {creatureMovement.GUID} PathType: {creatureMovement.Type}";
output += "-- " + commentInformation + "\n";
output += nodeSql;
if (!pathsPerGuid.TryGetValue(packet.Mover, out var pathList))
{
pathList = new AggregatedPaths();
pathsPerGuid.Add(packet.Mover, pathList);
}
pathList.Paths.Add(path);
if (Settings.SkipIntermediatePoints == true)
pathList.PointCount += packet.Points.Count + (dest ? 1 : 0);
else
pathList.PointCount += path.Waypoints.Count;

int pointIdCounter = 1;
int actualPoint = 1;
foreach (var node in creatureMovement.Waypoints)
return default;
}

protected override string GenerateQuery()
{
StringBuilder output = new();
output.AppendLine("SET @MOVID = 0;");
int pathIdCounter = 0;
foreach (var (mover, paths) in pathsPerGuid)
{
string commentInformation = $"GUID: {mover.ToWowParserString()}";
output.AppendLine("-- " + commentInformation);
if (Settings.TargetedProject == TargetedProject.Cmangos)
{
output.AppendLine($"INSERT INTO waypoint_path_name(PathId, Name) VALUES(@MOVID + {pathIdCounter},'{SQLUtil.EscapeString(StoreGetters.GetName(Utilities.ObjectTypeToStore(mover.Type.ToObjectType()), (int)mover.Entry))}');");
output.AppendLine("INSERT INTO waypoint_path (PathId, Point, PositionX, PositionY, PositionZ, Orientation, WaitTime, ScriptId, Comment) VALUES");
}
else if (Settings.TargetedProject == TargetedProject.TrinityCore)
{
output.AppendLine("INSERT INTO waypoint_path_node (PathId, NodeId, PositionX, PositionY, PositionZ, Orientation, Delay) VALUES");
}
int pointIdCounter = 1;
foreach (var path in paths.Paths)
{
foreach (var node in path.Waypoints)
{
bool finalP = creatureMovement.Destination == null && creatureMovement.Waypoints.Count == actualPoint;
++actualPoint;
float ori = finalP ? (creatureMovement.FinalOrientation != null ? creatureMovement.FinalOrientation.Value : 100f) : 100f;
if (node.Point == false)
{
if (Settings.SkipIntermediatePoints == true)
continue;
output += "-- ";
output.Append("-- ");
}
output += $"(@MOVID + {pathIdCounter}, '{pointIdCounter}', '{node.Position.X}', '{node.Position.Y}', '{node.Position.Z}', '{ori}')";

if (!finalP)
output += ",\n";
var isLast = pointIdCounter == paths.PointCount;
if (Settings.TargetedProject == TargetedProject.Cmangos)
output.Append($"(@MOVID + {pathIdCounter}, '{pointIdCounter}', '{node.Position.X}', '{node.Position.Y}', '{node.Position.Z}', '{node.Orientation}', '0', '0', NULL)");
else if (Settings.TargetedProject == TargetedProject.TrinityCore)
output.Append($"(@MOVID + {pathIdCounter}, '{pointIdCounter}', '{node.Position.X}', '{node.Position.Y}', '{node.Position.Z}', '{node.Orientation}')");

if (!isLast)
output.Append(",");
else
output += ";\n\n";
output.Append(";");

++pointIdCounter;
}
if (pointIdCounter == 1)
output.Append($" -- PathType: {path.Type}");

if (creatureMovement.Destination != null)
{
float ori = creatureMovement.FinalOrientation != null ? creatureMovement.FinalOrientation.Value : 100f;
output += $"(@MOVID + {pathIdCounter}, '{pointIdCounter}', '{creatureMovement.Destination.Position.X}', '{creatureMovement.Destination.Position.Y}', '{creatureMovement.Destination.Position.Z}', '{ori}', '0', '0', NULL);\n\n";
if (isLast)
output.AppendLine();

++pointIdCounter;
}

++pathIdCounter;
output.AppendLine();
}
}

return output;
++pathIdCounter;
}
return output.ToString();
}
}
}
Loading

0 comments on commit 6891387

Please sign in to comment.