Files
CypherCore/Source/Game/Network/Packets/MovementPackets.cs
T

1257 lines
42 KiB
C#

/*
* Copyright (C) 2012-2018 CypherCore <http://github.com/CypherCore>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using Framework.Constants;
using Framework.Dynamic;
using Framework.GameMath;
using Game.Entities;
using Game.Movement;
using System.Collections.Generic;
using System.Linq;
namespace Game.Network.Packets
{
public static class MovementExtensions
{
public static void ReadTransportInfo(WorldPacket data, ref MovementInfo.TransportInfo transportInfo)
{
transportInfo.guid = data.ReadPackedGuid(); // Transport Guid
transportInfo.pos.posX = data.ReadFloat();
transportInfo.pos.posY = data.ReadFloat();
transportInfo.pos.posZ = data.ReadFloat();
transportInfo.pos.Orientation = data.ReadFloat();
transportInfo.seat = data.ReadInt8(); // VehicleSeatIndex
transportInfo.time = data.ReadUInt32(); // MoveTime
bool hasPrevTime = data.HasBit();
bool hasVehicleId = data.HasBit();
if (hasPrevTime)
transportInfo.prevTime = data.ReadUInt32(); // PrevMoveTime
if (hasVehicleId)
transportInfo.vehicleId = data.ReadUInt32(); // VehicleRecID
}
public static void WriteTransportInfo(WorldPacket data, MovementInfo.TransportInfo transportInfo)
{
bool hasPrevTime = transportInfo.prevTime != 0;
bool hasVehicleId = transportInfo.vehicleId != 0;
data.WritePackedGuid(transportInfo.guid); // Transport Guid
data.WriteFloat(transportInfo.pos.GetPositionX());
data.WriteFloat(transportInfo.pos.GetPositionY());
data.WriteFloat(transportInfo.pos.GetPositionZ());
data.WriteFloat(transportInfo.pos.GetOrientation());
data.WriteInt8(transportInfo.seat); // VehicleSeatIndex
data.WriteUInt32(transportInfo.time); // MoveTime
data.WriteBit(hasPrevTime);
data.WriteBit(hasVehicleId);
data.FlushBits();
if (hasPrevTime)
data.WriteUInt32(transportInfo.prevTime); // PrevMoveTime
if (hasVehicleId)
data.WriteUInt32(transportInfo.vehicleId); // VehicleRecID
}
public static MovementInfo ReadMovementInfo(WorldPacket data)
{
var movementInfo = new MovementInfo();
movementInfo.Guid = data.ReadPackedGuid();
movementInfo.Time = data.ReadUInt32();
movementInfo.Pos.posX = data.ReadFloat();
movementInfo.Pos.posY = data.ReadFloat();
movementInfo.Pos.posZ = data.ReadFloat();
movementInfo.Pos.Orientation = data.ReadFloat();
movementInfo.Pitch = data.ReadFloat();
movementInfo.SplineElevation = data.ReadFloat();
uint removeMovementForcesCount = data.ReadUInt32();
uint moveIndex = data.ReadUInt32();
for (uint i = 0; i < removeMovementForcesCount; ++i)
{
ObjectGuid guid = data.ReadPackedGuid();
}
// ResetBitReader
movementInfo.SetMovementFlags((MovementFlag)data.ReadBits<uint>(30));
movementInfo.SetMovementFlags2((MovementFlag2)data.ReadBits<uint>(18));
bool hasTransport = data.HasBit();
bool hasFall = data.HasBit();
bool hasSpline = data.HasBit(); // todo 6.x read this infos
data.ReadBit(); // HeightChangeFailed
data.ReadBit(); // RemoteTimeValid
if (hasTransport)
ReadTransportInfo(data, ref movementInfo.transport);
if (hasFall)
{
movementInfo.jump.fallTime = data.ReadUInt32();
movementInfo.jump.zspeed = data.ReadFloat();
// ResetBitReader
bool hasFallDirection = data.HasBit();
if (hasFallDirection)
{
movementInfo.jump.sinAngle = data.ReadFloat();
movementInfo.jump.cosAngle = data.ReadFloat();
movementInfo.jump.xyspeed = data.ReadFloat();
}
}
return movementInfo;
}
public static void WriteMovementInfo(WorldPacket data, MovementInfo movementInfo)
{
bool hasTransportData = !movementInfo.transport.guid.IsEmpty();
bool hasFallDirection = movementInfo.HasMovementFlag(MovementFlag.Falling | MovementFlag.FallingFar);
bool hasFallData = hasFallDirection || movementInfo.jump.fallTime != 0;
bool hasSpline = false; // todo 6.x send this infos
data.WritePackedGuid(movementInfo.Guid);
data.WriteUInt32(movementInfo.Time);
data.WriteFloat(movementInfo.Pos.GetPositionX());
data.WriteFloat(movementInfo.Pos.GetPositionY());
data.WriteFloat(movementInfo.Pos.GetPositionZ());
data.WriteFloat(movementInfo.Pos.GetOrientation());
data.WriteFloat(movementInfo.Pitch);
data.WriteFloat(movementInfo.SplineElevation);
uint removeMovementForcesCount = 0;
data.WriteUInt32(removeMovementForcesCount);
uint int168 = 0;
data.WriteUInt32(int168);
/*for (public uint i = 0; i < removeMovementForcesCount; ++i)
{
_worldPacket << ObjectGuid;
}*/
data.WriteBits((uint)movementInfo.GetMovementFlags(), 30);
data.WriteBits((uint)movementInfo.GetMovementFlags2(), 18);
data.WriteBit(hasTransportData);
data.WriteBit(hasFallData);
data.WriteBit(hasSpline);
data.WriteBit(0); // HeightChangeFailed
data.WriteBit(0); // RemoteTimeValid
data.FlushBits();
if (hasTransportData)
WriteTransportInfo(data, movementInfo.transport);
if (hasFallData)
{
data.WriteUInt32(movementInfo.jump.fallTime);
data.WriteFloat(movementInfo.jump.zspeed);
data.WriteBit(hasFallDirection);
data.FlushBits();
if (hasFallDirection)
{
data.WriteFloat(movementInfo.jump.cosAngle);
data.WriteFloat(movementInfo.jump.sinAngle);
data.WriteFloat(movementInfo.jump.xyspeed);
}
}
}
public static void WriteCreateObjectSplineDataBlock(MoveSpline moveSpline, WorldPacket data)
{
data.WriteUInt32(moveSpline.GetId()); // ID
if (!moveSpline.isCyclic()) // Destination
data.WriteVector3(moveSpline.FinalDestination());
else
data.WriteVector3(Vector3.Zero);
bool hasSplineMove = data.WriteBit(!moveSpline.Finalized() && !moveSpline.splineIsFacingOnly);
data.FlushBits();
if (hasSplineMove)
{
data.WriteUInt32((uint)moveSpline.splineflags.Flags); // SplineFlags
data.WriteInt32(moveSpline.timePassed()); // Elapsed
data.WriteUInt32(moveSpline.Duration()); // Duration
data.WriteFloat(1.0f); // DurationModifier
data.WriteFloat(1.0f); // NextDurationModifier
data.WriteBits((byte)moveSpline.facing.type, 2); // Face
bool HasJumpGravity = data.WriteBit(moveSpline.splineflags.hasFlag(SplineFlag.Parabolic | SplineFlag.Animation)); // HasJumpGravity
bool HasSpecialTime = data.WriteBit(moveSpline.splineflags.hasFlag(SplineFlag.Parabolic) && moveSpline.effect_start_time < moveSpline.Duration()); // HasSpecialTime
data.WriteBits(moveSpline.getPath().Length, 16);
data.WriteBits((byte)moveSpline.spline.m_mode, 2); // Mode
data.WriteBit(0); // HasSplineFilter
data.WriteBit(moveSpline.spell_effect_extra.HasValue); // HasSpellEffectExtraData
//if (HasSplineFilterKey)
//{
// data << uint32(FilterKeysCount);
// for (var i = 0; i < FilterKeysCount; ++i)
// {
// data << float(In);
// data << float(Out);
// }
// data.WriteBits(FilterFlags, 2);
// data.FlushBits();
//}
switch (moveSpline.facing.type)
{
case MonsterMoveType.FacingSpot:
data.WriteVector3(moveSpline.facing.f); // FaceSpot
break;
case MonsterMoveType.FacingTarget:
data.WritePackedGuid(moveSpline.facing.target); // FaceGUID
break;
case MonsterMoveType.FacingAngle:
data.WriteFloat(moveSpline.facing.angle); // FaceDirection
break;
}
if (HasJumpGravity)
data.WriteFloat(moveSpline.vertical_acceleration); // JumpGravity
if (HasSpecialTime)
data.WriteUInt32(moveSpline.effect_start_time); // SpecialTime
foreach (var vec in moveSpline.getPath())
data.WriteVector3(vec);
if (moveSpline.spell_effect_extra.HasValue)
{
data.WritePackedGuid(moveSpline.spell_effect_extra.Value.Target);
data.WriteUInt32(moveSpline.spell_effect_extra.Value.SpellVisualId);
data.WriteUInt32(moveSpline.spell_effect_extra.Value.ProgressCurveId);
data.WriteUInt32(moveSpline.spell_effect_extra.Value.ParabolicCurveId);
}
}
}
public static void WriteCreateObjectAreaTriggerSpline(Spline spline, WorldPacket data)
{
data.WriteBits(spline.getPoints().Length, 16);
foreach (var point in spline.getPoints())
data.WriteVector3(point);
}
}
public class ClientPlayerMovement : ClientPacket
{
public ClientPlayerMovement(WorldPacket packet) : base(packet) { }
public override void Read()
{
Status = MovementExtensions.ReadMovementInfo(_worldPacket);
}
public MovementInfo Status;
}
public class MoveUpdate : ServerPacket
{
public MoveUpdate() : base(ServerOpcodes.MoveUpdate, ConnectionType.Instance) { }
public override void Write()
{
MovementExtensions.WriteMovementInfo(_worldPacket, Status);
}
public MovementInfo Status;
}
public class MonsterMove : ServerPacket
{
public MonsterMove() : base(ServerOpcodes.OnMonsterMove, ConnectionType.Instance)
{
SplineData = new MovementMonsterSpline();
}
public void InitializeSplineData(MoveSpline moveSpline)
{
SplineData.ID = moveSpline.GetId();
MovementSpline movementSpline = SplineData.Move;
MoveSplineFlag splineFlags = moveSpline.splineflags;
splineFlags.SetUnsetFlag(SplineFlag.Cyclic, moveSpline.isCyclic());
movementSpline.Flags = (uint)(splineFlags.Flags & ~SplineFlag.MaskNoMonsterMove);
movementSpline.Face = moveSpline.facing.type;
movementSpline.FaceDirection = moveSpline.facing.angle;
movementSpline.FaceGUID = moveSpline.facing.target;
movementSpline.FaceSpot = moveSpline.facing.f;
if (splineFlags.hasFlag(SplineFlag.Animation))
{
movementSpline.AnimTier = splineFlags.getAnimationId();
movementSpline.TierTransStartTime = (uint)moveSpline.effect_start_time;
}
movementSpline.MoveTime = (uint)moveSpline.Duration();
if (splineFlags.hasFlag(SplineFlag.Parabolic))
{
movementSpline.JumpGravity = moveSpline.vertical_acceleration;
movementSpline.SpecialTime = (uint)moveSpline.effect_start_time;
}
if (splineFlags.hasFlag(SplineFlag.FadeObject))
movementSpline.SpecialTime = (uint)moveSpline.effect_start_time;
if (moveSpline.spell_effect_extra.HasValue)
{
movementSpline.SpellEffectExtraData.HasValue = true;
movementSpline.SpellEffectExtraData.Value.TargetGuid = moveSpline.spell_effect_extra.Value.Target;
movementSpline.SpellEffectExtraData.Value.SpellVisualID = moveSpline.spell_effect_extra.Value.SpellVisualId;
movementSpline.SpellEffectExtraData.Value.ProgressCurveID = moveSpline.spell_effect_extra.Value.ProgressCurveId;
movementSpline.SpellEffectExtraData.Value.ParabolicCurveID = moveSpline.spell_effect_extra.Value.ParabolicCurveId;
}
Spline spline = moveSpline.spline;
Vector3[] array = spline.getPoints();
if (splineFlags.hasFlag(SplineFlag.UncompressedPath))
{
if (!splineFlags.hasFlag(SplineFlag.Cyclic))
{
int count = spline.getPointCount() - 3;
for (uint i = 0; i < count; ++i)
movementSpline.Points.Add(array[i + 2]);
}
else
{
int count = spline.getPointCount() - 3;
movementSpline.Points.Add(array[1]);
for (uint i = 0; i < count; ++i)
movementSpline.Points.Add(array[i + 1]);
}
}
else
{
int lastIdx = spline.getPointCount() - 3;
Vector3[] realPath = spline.getPoints().Skip(1).ToArray();
movementSpline.Points.Add(realPath[lastIdx]);
if (lastIdx > 1)
{
Vector3 middle = (realPath[0] + realPath[lastIdx]) / 2.0f;
// first and last points already appended
for (uint i = 1; i < lastIdx; ++i)
movementSpline.PackedDeltas.Add(middle - realPath[i]);
}
}
}
public override void Write()
{
_worldPacket.WritePackedGuid(MoverGUID);
_worldPacket.WriteVector3(Pos);
SplineData.Write(_worldPacket);
}
public MovementMonsterSpline SplineData;
public ObjectGuid MoverGUID;
public Vector3 Pos;
}
public class MoveSplineSetSpeed : ServerPacket
{
public MoveSplineSetSpeed(ServerOpcodes opcode) : base(opcode, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(MoverGUID);
_worldPacket.WriteFloat(Speed);
}
public ObjectGuid MoverGUID;
public float Speed = 1.0f;
}
public class MoveSetSpeed : ServerPacket
{
public MoveSetSpeed(ServerOpcodes opcode) : base(opcode, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(MoverGUID);
_worldPacket.WriteUInt32(SequenceIndex);
_worldPacket.WriteFloat(Speed);
}
public ObjectGuid MoverGUID;
public uint SequenceIndex = 0; // Unit movement packet index, incremented each time
public float Speed = 1.0f;
}
public class MoveUpdateSpeed : ServerPacket
{
public MoveUpdateSpeed(ServerOpcodes opcode) : base(opcode, ConnectionType.Instance) { }
public override void Write()
{
MovementExtensions.WriteMovementInfo(_worldPacket, Status);
_worldPacket.WriteFloat(Speed);
}
public MovementInfo Status;
public float Speed = 1.0f;
}
public class MoveSplineSetFlag : ServerPacket
{
public MoveSplineSetFlag(ServerOpcodes opcode) : base(opcode, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(MoverGUID);
}
public ObjectGuid MoverGUID;
}
public class MoveSetFlag : ServerPacket
{
public MoveSetFlag(ServerOpcodes opcode) : base(opcode, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(MoverGUID);
_worldPacket.WriteUInt32(SequenceIndex);
}
public ObjectGuid MoverGUID;
public uint SequenceIndex = 0; // Unit movement packet index, incremented each time
}
public class TransferPending : ServerPacket
{
public TransferPending() : base(ServerOpcodes.TransferPending)
{
Ship = new Optional<ShipTransferPending>();
TransferSpellID = new Optional<int>();
}
public override void Write()
{
_worldPacket.WriteInt32(MapID);
_worldPacket.WriteXYZ(OldMapPosition);
_worldPacket.WriteBit(Ship.HasValue);
_worldPacket.WriteBit(TransferSpellID.HasValue);
if (Ship.HasValue)
{
_worldPacket.WriteUInt32(Ship.Value.ID);
_worldPacket.WriteInt32(Ship.Value.OriginMapID);
}
if (TransferSpellID.HasValue)
_worldPacket.WriteInt32(TransferSpellID.Value);
_worldPacket.FlushBits();
}
public int MapID = -1;
public Position OldMapPosition;
public Optional<ShipTransferPending> Ship;
public Optional<int> TransferSpellID;
public struct ShipTransferPending
{
public uint ID; // gameobject_template.entry of the transport the player is teleporting on
public int OriginMapID; // Map id the player is currently on (before teleport)
}
}
public class TransferAborted : ServerPacket
{
public TransferAborted() : base(ServerOpcodes.TransferAborted) { }
public override void Write()
{
_worldPacket.WriteUInt32(MapID);
_worldPacket.WriteUInt8(Arg);
_worldPacket.WriteInt32(MapDifficultyXConditionID);
_worldPacket.WriteBits(TransfertAbort, 5);
_worldPacket.FlushBits();
}
public uint MapID;
public byte Arg;
public int MapDifficultyXConditionID;
public TransferAbortReason TransfertAbort;
}
public class NewWorld : ServerPacket
{
public NewWorld() : base(ServerOpcodes.NewWorld) { }
public override void Write()
{
_worldPacket.WriteUInt32(MapID);
_worldPacket.WriteXYZO(Pos);
_worldPacket.WriteUInt32(Reason);
_worldPacket.WriteXYZ(MovementOffset);
}
public uint MapID;
public uint Reason;
public Position Pos;
public Position MovementOffset; // Adjusts all pending movement events by this offset
}
public class WorldPortResponse : ClientPacket
{
public WorldPortResponse(WorldPacket packet) : base(packet) { }
public override void Read() { }
}
public class MoveTeleport : ServerPacket
{
public MoveTeleport() : base(ServerOpcodes.MoveTeleport, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(MoverGUID);
_worldPacket.WriteUInt32(SequenceIndex);
_worldPacket.WriteXYZ(Pos);
_worldPacket.WriteFloat(Facing);
_worldPacket.WriteUInt8(PreloadWorld);
_worldPacket.WriteBit(Vehicle.HasValue);
_worldPacket.WriteBit(TransportGUID.HasValue);
_worldPacket.FlushBits();
if (Vehicle.HasValue)
{
_worldPacket.WriteUInt8(Vehicle.Value.VehicleSeatIndex);
_worldPacket.WriteBit(Vehicle.Value.VehicleExitVoluntary);
_worldPacket.WriteBit(Vehicle.Value.VehicleExitTeleport);
_worldPacket.FlushBits();
}
if (TransportGUID.HasValue)
_worldPacket.WritePackedGuid(TransportGUID.Value);
}
public Position Pos;
public Optional<VehicleTeleport> Vehicle;
public uint SequenceIndex;
public ObjectGuid MoverGUID;
public Optional<ObjectGuid> TransportGUID;
public float Facing;
public byte PreloadWorld;
}
public class MoveUpdateTeleport : ServerPacket
{
public MoveUpdateTeleport() : base(ServerOpcodes.MoveUpdateTeleport) { }
public override void Write()
{
MovementExtensions.WriteMovementInfo(_worldPacket, Status);
_worldPacket.WriteInt32(MovementForces.Count);
_worldPacket.WriteBit(WalkSpeed.HasValue);
_worldPacket.WriteBit(RunSpeed.HasValue);
_worldPacket.WriteBit(RunBackSpeed.HasValue);
_worldPacket.WriteBit(SwimSpeed.HasValue);
_worldPacket.WriteBit(SwimBackSpeed.HasValue);
_worldPacket.WriteBit(FlightSpeed.HasValue);
_worldPacket.WriteBit(FlightBackSpeed.HasValue);
_worldPacket.WriteBit(TurnRate.HasValue);
_worldPacket.WriteBit(PitchRate.HasValue);
_worldPacket.FlushBits();
foreach (MovementForce force in MovementForces)
force.Write(_worldPacket);
if (WalkSpeed.HasValue)
_worldPacket.WriteFloat(WalkSpeed.Value);
if (RunSpeed.HasValue)
_worldPacket.WriteFloat(RunSpeed.Value);
if (RunBackSpeed.HasValue)
_worldPacket.WriteFloat(RunBackSpeed.Value);
if (SwimSpeed.HasValue)
_worldPacket.WriteFloat(SwimSpeed.Value);
if (SwimBackSpeed.HasValue)
_worldPacket.WriteFloat(SwimBackSpeed.Value);
if (FlightSpeed.HasValue)
_worldPacket.WriteFloat(FlightSpeed.Value);
if (FlightBackSpeed.HasValue)
_worldPacket.WriteFloat(FlightBackSpeed.Value);
if (TurnRate.HasValue)
_worldPacket.WriteFloat(TurnRate.Value);
if (PitchRate.HasValue)
_worldPacket.WriteFloat(PitchRate.Value);
}
public MovementInfo Status;
public List<MovementForce> MovementForces = new List<MovementForce>();
public Optional<float> SwimBackSpeed;
public Optional<float> FlightSpeed;
public Optional<float> SwimSpeed;
public Optional<float> WalkSpeed;
public Optional<float> TurnRate;
public Optional<float> RunSpeed;
public Optional<float> FlightBackSpeed;
public Optional<float> RunBackSpeed;
public Optional<float> PitchRate;
}
class MoveUpdateApplyMovementForce : ServerPacket
{
public MoveUpdateApplyMovementForce() : base(ServerOpcodes.MoveUpdateApplyMovementForce) { }
public override void Write()
{
MovementExtensions.WriteMovementInfo(_worldPacket, movementInfo);
Force.Write(_worldPacket);
}
MovementInfo movementInfo = new MovementInfo();
MovementForce Force = new MovementForce();
}
class MoveUpdateRemoveMovementForce : ServerPacket
{
public MoveUpdateRemoveMovementForce() : base(ServerOpcodes.MoveUpdateRemoveMovementForce) { }
public override void Write()
{
MovementExtensions.WriteMovementInfo(_worldPacket, movementInfo);
_worldPacket.WritePackedGuid(TriggerGUID);
}
MovementInfo movementInfo = new MovementInfo();
ObjectGuid TriggerGUID;
}
class MoveTeleportAck : ClientPacket
{
public MoveTeleportAck(WorldPacket packet) : base(packet) { }
public override void Read()
{
MoverGUID = _worldPacket.ReadPackedGuid();
AckIndex = _worldPacket.ReadInt32();
MoveTime = _worldPacket.ReadInt32();
}
public ObjectGuid MoverGUID;
int AckIndex = 0;
int MoveTime = 0;
}
public class MovementAckMessage : ClientPacket
{
public MovementAckMessage(WorldPacket packet) : base(packet) { }
public override void Read()
{
Ack.Read(_worldPacket);
}
public MovementAck Ack;
}
public class MovementSpeedAck : ClientPacket
{
public MovementSpeedAck(WorldPacket packet) : base(packet) { }
public override void Read()
{
Ack.Read(_worldPacket);
Speed = _worldPacket.ReadFloat();
}
public MovementAck Ack;
public float Speed;
}
public class SetActiveMover : ClientPacket
{
public ObjectGuid ActiveMover;
public SetActiveMover(WorldPacket packet) : base(packet) { }
public override void Read()
{
ActiveMover = _worldPacket.ReadPackedGuid();
}
}
public class MoveSetActiveMover : ServerPacket
{
public ObjectGuid MoverGUID;
public MoveSetActiveMover() : base(ServerOpcodes.MoveSetActiveMover) { }
public override void Write()
{
_worldPacket.WritePackedGuid(MoverGUID);
}
}
class MoveKnockBack : ServerPacket
{
public MoveKnockBack() : base(ServerOpcodes.MoveKnockBack, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(MoverGUID);
_worldPacket.WriteUInt32(SequenceIndex);
_worldPacket.WriteVector2(Direction);
Speeds.Write(_worldPacket);
}
public ObjectGuid MoverGUID;
public Vector2 Direction;
public MoveKnockBackSpeeds Speeds;
public uint SequenceIndex;
}
public class MoveUpdateKnockBack : ServerPacket
{
public MoveUpdateKnockBack() : base(ServerOpcodes.MoveUpdateKnockBack) { }
public override void Write()
{
MovementExtensions.WriteMovementInfo(_worldPacket, Status);
}
public MovementInfo Status;
}
class MoveKnockBackAck : ClientPacket
{
public MoveKnockBackAck(WorldPacket packet) : base(packet) { }
public override void Read()
{
Ack.Read(_worldPacket);
if (_worldPacket.HasBit())
{
Speeds.HasValue = true;
Speeds.Value.Read(_worldPacket);
}
}
public MovementAck Ack;
public Optional<MoveKnockBackSpeeds> Speeds;
}
class MoveSetCollisionHeight : ServerPacket
{
public MoveSetCollisionHeight() : base(ServerOpcodes.MoveSetCollisionHeight) { }
public override void Write()
{
_worldPacket.WritePackedGuid(MoverGUID);
_worldPacket.WriteUInt32(SequenceIndex);
_worldPacket.WriteFloat(Height);
_worldPacket.WriteFloat(Scale);
_worldPacket.WriteUInt32(MountDisplayID);
_worldPacket.WriteInt32(ScaleDuration);
_worldPacket.WriteBits((uint)Reason, 2);
_worldPacket.FlushBits();
}
public float Scale = 1.0f;
public ObjectGuid MoverGUID;
public uint MountDisplayID;
public UpdateCollisionHeightReason Reason = UpdateCollisionHeightReason.Mount;
public uint SequenceIndex;
public int ScaleDuration;
public float Height = 1.0f;
}
public class MoveUpdateCollisionHeight : ServerPacket
{
public MoveUpdateCollisionHeight() : base(ServerOpcodes.MoveUpdateCollisionHeight) { }
public override void Write()
{
MovementExtensions.WriteMovementInfo(_worldPacket, Status);
_worldPacket.WriteFloat(Height);
_worldPacket.WriteFloat(Scale);
}
public MovementInfo Status;
public float Scale = 1.0f;
public float Height = 1.0f;
}
public class MoveSetCollisionHeightAck : ClientPacket
{
public MoveSetCollisionHeightAck(WorldPacket packet) : base(packet) { }
public override void Read()
{
Data.Read(_worldPacket);
Height = _worldPacket.ReadFloat();
MountDisplayID = _worldPacket.ReadUInt32();
Reason = (UpdateCollisionHeightReason)_worldPacket.ReadBits<uint>(2);
}
public MovementAck Data;
public UpdateCollisionHeightReason Reason = UpdateCollisionHeightReason.Mount;
public uint MountDisplayID;
public float Height = 1.0f;
}
class MoveTimeSkipped : ClientPacket
{
public MoveTimeSkipped(WorldPacket packet) : base(packet) { }
public override void Read()
{
MoverGUID = _worldPacket.ReadPackedGuid();
TimeSkipped = _worldPacket.ReadUInt32();
}
public ObjectGuid MoverGUID;
public uint TimeSkipped;
}
class SummonResponse : ClientPacket
{
public SummonResponse(WorldPacket packet) : base(packet) { }
public override void Read()
{
SummonerGUID = _worldPacket.ReadPackedGuid();
Accept = _worldPacket.HasBit();
}
public bool Accept;
public ObjectGuid SummonerGUID;
}
public class ControlUpdate : ServerPacket
{
public ControlUpdate() : base(ServerOpcodes.ControlUpdate) { }
public override void Write()
{
_worldPacket.WritePackedGuid(Guid);
_worldPacket.WriteBit(On);
_worldPacket.FlushBits();
}
public bool On;
public ObjectGuid Guid;
}
class MoveSplineDone : ClientPacket
{
public MoveSplineDone(WorldPacket packet) : base(packet) { }
public override void Read()
{
Status = MovementExtensions.ReadMovementInfo(_worldPacket);
SplineID = _worldPacket.ReadInt32();
}
public MovementInfo Status;
public int SplineID;
}
class SummonRequest : ServerPacket
{
public SummonRequest() : base(ServerOpcodes.SummonRequest, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(SummonerGUID);
_worldPacket.WriteUInt32(SummonerVirtualRealmAddress);
_worldPacket.WriteInt32(AreaID);
_worldPacket.WriteUInt8(Reason);
_worldPacket.WriteBit(SkipStartingArea);
_worldPacket.FlushBits();
}
public ObjectGuid SummonerGUID;
public uint SummonerVirtualRealmAddress;
public int AreaID;
public SummonReason Reason;
public bool SkipStartingArea;
public enum SummonReason
{
Spell = 0,
Scenario = 1
}
}
class SuspendToken : ServerPacket
{
public SuspendToken() : base(ServerOpcodes.SuspendToken, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WriteUInt32(SequenceIndex);
_worldPacket.WriteBits(Reason, 2);
_worldPacket.FlushBits();
}
public uint SequenceIndex = 1;
public uint Reason = 1;
}
class SuspendTokenResponse : ClientPacket
{
public SuspendTokenResponse(WorldPacket packet) : base(packet) { }
public override void Read()
{
SequenceIndex = _worldPacket.ReadUInt32();
}
public uint SequenceIndex;
}
class ResumeToken : ServerPacket
{
public ResumeToken() : base(ServerOpcodes.ResumeToken, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WriteUInt32(SequenceIndex);
_worldPacket.WriteBits(Reason, 2);
_worldPacket.FlushBits();
}
public uint SequenceIndex = 1;
public uint Reason = 1;
}
class MoveSetCompoundState : ServerPacket
{
public MoveSetCompoundState() : base(ServerOpcodes.MoveSetCompoundState, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(MoverGUID);
_worldPacket.WriteUInt32(StateChanges.Count);
foreach (MoveStateChange stateChange in StateChanges)
stateChange.Write(_worldPacket);
}
public ObjectGuid MoverGUID;
public List<MoveStateChange> StateChanges = new List<MoveStateChange>();
public struct CollisionHeightInfo
{
public float Height;
public float Scale;
public UpdateCollisionHeightReason Reason;
}
public struct KnockBackInfo
{
public float HorzSpeed;
public Vector2 Direction;
public float InitVertSpeed;
}
public class MoveStateChange
{
public MoveStateChange(ServerOpcodes messageId, uint sequenceIndex)
{
MessageID = messageId;
SequenceIndex = sequenceIndex;
}
public void Write(WorldPacket data)
{
data.WriteUInt16(MessageID);
data.WriteUInt32(SequenceIndex);
data.WriteBit(Speed.HasValue);
data.WriteBit(KnockBack.HasValue);
data.WriteBit(VehicleRecID.HasValue);
data.WriteBit(CollisionHeight.HasValue);
data.WriteBit(MovementForce_.HasValue);
data.WriteBit(Unknown.HasValue);
data.FlushBits();
if (CollisionHeight.HasValue)
{
data.WriteFloat(CollisionHeight.Value.Height);
data.WriteFloat(CollisionHeight.Value.Scale);
data.WriteBits(CollisionHeight.Value.Reason, 2);
data.FlushBits();
}
if (Speed.HasValue)
data.WriteFloat(Speed.Value);
if (KnockBack.HasValue)
{
data.WriteFloat(KnockBack.Value.HorzSpeed);
data.WriteVector2(KnockBack.Value.Direction);
data.WriteFloat(KnockBack.Value.InitVertSpeed);
}
if (VehicleRecID.HasValue)
data.WriteInt32(VehicleRecID.Value);
if (Unknown.HasValue)
data.WritePackedGuid(Unknown.Value);
if (MovementForce_.HasValue)
MovementForce_.Value.Write(data);
}
public ServerOpcodes MessageID;
public uint SequenceIndex;
public Optional<float> Speed;
public Optional<KnockBackInfo> KnockBack;
public Optional<int> VehicleRecID;
public Optional<CollisionHeightInfo> CollisionHeight;
public Optional<MovementForce> MovementForce_;
public Optional<ObjectGuid> Unknown;
}
}
//Structs
public struct MonsterSplineFilterKey
{
public void Write(WorldPacket data)
{
data.WriteInt16(Idx);
data.WriteUInt16(Speed);
}
public short Idx;
public ushort Speed;
}
public class MonsterSplineFilter
{
public void Write(WorldPacket data)
{
data.WriteUInt32(FilterKeys.Count);
data.WriteFloat(BaseSpeed);
data.WriteInt16(StartOffset);
data.WriteFloat(DistToPrevFilterKey);
data.WriteInt16(AddedToStart);
FilterKeys.ForEach(p => p.Write(data));
data.WriteBits(FilterFlags, 2);
data.FlushBits();
}
public List<MonsterSplineFilterKey> FilterKeys = new List<MonsterSplineFilterKey>();
public byte FilterFlags;
public float BaseSpeed;
public short StartOffset;
public float DistToPrevFilterKey;
public short AddedToStart;
}
public struct MonsterSplineSpellEffectExtraData
{
public void Write(WorldPacket data)
{
data.WritePackedGuid(TargetGuid);
data.WriteUInt32(SpellVisualID);
data.WriteUInt32(ProgressCurveID);
data.WriteUInt32(ParabolicCurveID);
}
public ObjectGuid TargetGuid;
public uint SpellVisualID;
public uint ProgressCurveID;
public uint ParabolicCurveID;
}
public class MovementSpline
{
public void Write(WorldPacket data)
{
data.WriteUInt32(Flags);
data.WriteUInt8(AnimTier);
data.WriteUInt32(TierTransStartTime);
data.WriteInt32(Elapsed);
data.WriteUInt32(MoveTime);
data.WriteFloat(JumpGravity);
data.WriteUInt32(SpecialTime);
data.WriteUInt8(Mode);
data.WriteUInt8(VehicleExitVoluntary);
data.WritePackedGuid(TransportGUID);
data.WriteInt8(VehicleSeat);
data.WriteBits((byte)Face, 2);
data.WriteBits(Points.Count, 16);
data.WriteBits(PackedDeltas.Count, 16);
data.WriteBit(SplineFilter.HasValue);
data.WriteBit(SpellEffectExtraData.HasValue);
data.FlushBits();
if (SplineFilter.HasValue)
SplineFilter.Value.Write(data);
switch (Face)
{
case MonsterMoveType.FacingSpot:
data.WriteVector3(FaceSpot);
break;
case MonsterMoveType.FacingTarget:
data.WriteFloat(FaceDirection);
data.WritePackedGuid(FaceGUID);
break;
case MonsterMoveType.FacingAngle:
data.WriteFloat(FaceDirection);
break;
}
foreach (Vector3 pos in Points)
data.WriteVector3(pos);
foreach (Vector3 pos in PackedDeltas)
data.WritePackXYZ(pos);
if (SpellEffectExtraData.HasValue)
SpellEffectExtraData.Value.Write(data);
}
public uint Flags; // Spline flags
public MonsterMoveType Face; // Movement direction (see MonsterMoveType enum)
public byte AnimTier;
public uint TierTransStartTime;
public int Elapsed;
public uint MoveTime;
public float JumpGravity;
public uint SpecialTime;
public List<Vector3> Points = new List<Vector3>(); // Spline path
public byte Mode; // Spline mode - actually always 0 in this packet - Catmullrom mode appears only in SMSG_UPDATE_OBJECT. In this packet it is determined by flags
public byte VehicleExitVoluntary;
public ObjectGuid TransportGUID;
public sbyte VehicleSeat = -1;
public List<Vector3> PackedDeltas = new List<Vector3>();
public Optional<MonsterSplineFilter> SplineFilter;
public Optional<MonsterSplineSpellEffectExtraData> SpellEffectExtraData;
public float FaceDirection;
public ObjectGuid FaceGUID;
public Vector3 FaceSpot;
}
public class MovementMonsterSpline
{
public MovementMonsterSpline()
{
Move = new MovementSpline();
}
public void Write(WorldPacket data)
{
data.WriteUInt32(ID);
data.WriteVector3(Destination);
data.WriteBit(CrzTeleport);
data.WriteBits(StopDistanceTolerance, 3);
Move.Write(data);
}
public uint ID;
public Vector3 Destination;
public bool CrzTeleport;
public byte StopDistanceTolerance; // Determines how far from spline destination the mover is allowed to stop in place 0, 0, 3.0, 2.76, numeric_limits<float>::max, 1.1, float(INT_MAX); default before this field existed was distance 3.0 (index 2)
public MovementSpline Move;
}
public struct VehicleTeleport
{
public byte VehicleSeatIndex;
public bool VehicleExitVoluntary;
public bool VehicleExitTeleport;
}
public struct MovementForce
{
public void Write(WorldPacket data)
{
data.WritePackedGuid(ID);
data.WriteVector3(Origin);
data.WriteVector3(Direction);
data.WriteUInt32(TransportID);
data.WriteFloat(Magnitude);
data.WriteBits(Type, 2);
data.FlushBits();
}
public ObjectGuid ID;
public Vector3 Origin;
public Vector3 Direction;
public uint TransportID;
public float Magnitude;
public byte Type;
}
public struct MovementAck
{
public void Read(WorldPacket data)
{
Status = MovementExtensions.ReadMovementInfo(data);
AckIndex = data.ReadInt32();
}
public MovementInfo Status;
public int AckIndex;
}
public struct MoveKnockBackSpeeds
{
public void Write(WorldPacket data)
{
data.WriteFloat(HorzSpeed);
data.WriteFloat(VertSpeed);
}
public void Read(WorldPacket data)
{
HorzSpeed = data.ReadFloat();
VertSpeed = data.ReadFloat();
}
public float HorzSpeed;
public float VertSpeed;
}
}