using System; using System.Globalization; using System.Text.RegularExpressions; using System.Threading; public struct Point : IEquatable { public int X { get; } public int Y { get; } public Point(int x, int y) { X = x; Y = y; } public bool Equals(Point other) => X == other.X && Y == other.Y; public override bool Equals(object obj) => obj is Point other && Equals(other); public override int GetHashCode() => HashCode.Combine(X, Y); public override string ToString() => $"({X},{Y})"; } public class Tile { public int X { get; set; } public int Y { get; set; } public double Z { get; set; } public Point XY => new Point(X, Y); public Tile(int x, int y, double z = 0.0) { X = x; Y = y; Z = z; } } Tile _myAvatarActualTargetTile = null; Regex mvRegex = new Regex(@"/mv (\d+),(\d+),([\d\.]+)/"); void InterceptUserUpdate(dynamic e) { if(Self == null || Self.Location == null) return; var packet = e.Packet; int numUpdates = packet.ReadInt(); for(int i = 0; i < numUpdates; i++) { int entityIndex = packet.ReadInt(); packet.ReadInt(); packet.ReadInt(); packet.ReadString(); packet.ReadInt(); packet.ReadInt(); string action = packet.ReadString(); if (entityIndex == Self.Index) { Match match = mvRegex.Match(action); if (match.Success) { var newTargetTile = new Tile( int.Parse(match.Groups[1].Value), int.Parse(match.Groups[2].Value), double.Parse(match.Groups[3].Value, CultureInfo.InvariantCulture) ); if (_myAvatarActualTargetTile == null || !(_myAvatarActualTargetTile.XY.Equals(newTargetTile.XY))) { Point fromPoint = new Point(Self.Location.X, Self.Location.Y); Point toPoint = newTargetTile.XY; Log($"Movement initiated: From {fromPoint} to {toPoint}"); _myAvatarActualTargetTile = newTargetTile; } } else if (action.EndsWith("//") && !action.Contains("/mv")) { _myAvatarActualTargetTile = null; } } } } OnIntercept(In["UserUpdate"], e => InterceptUserUpdate(e)); while(Run) { Delay(100); }