public static void WriteCastInfo(this PacketWriter writerOrg, CastInfo data) { byte[] buffer; using (var stream = new MemoryStream()) { using (var writer = new PacketWriter(stream, true)) { writer.WriteUInt32(data.SpellHash); writer.WriteNetID(data.SpellNetID); writer.WriteByte(data.SpellLevel); writer.WriteFloat(data.AttackSpeedModifier); writer.WriteNetID(data.CasterNetID); writer.WriteNetID(data.SpellChainOwnerNetID); writer.WriteUInt32(data.PackageHash); writer.WriteNetID(data.MissileNetID); writer.WriteVector3(data.TargetPosition); writer.WriteVector3(data.TargetPositionEnd); int targetCount = data.Targets.Count; if (targetCount > 32) { throw new IOException("CastInfo targets > 32!!!"); } writer.WriteByte((byte)targetCount); foreach (var target in data.Targets) { writer.WriteNetID(target.Item1); writer.WriteHitResult(target.Item2); } writer.WriteFloat(data.DesignerCastTime); writer.WriteFloat(data.ExtraCastTime); writer.WriteFloat(data.DesignerTotalTime); writer.WriteFloat(data.Cooldown); writer.WriteFloat(data.StartCastTime); byte bitfield = 0; if (data.IsAutoAttack) { bitfield |= 1; } if (data.IsSecondAutoAttack) { bitfield |= 2; } if (data.IsForceCastingOrChannel) { bitfield |= 4; } if (data.IsOverrideCastPosition) { bitfield |= 8; } if (data.IsClickCasted) { bitfield |= 16; } writer.WriteByte(bitfield); writer.WriteByte(data.SpellSlot); writer.WriteFloat(data.ManaCost); writer.WriteVector3(data.SpellCastLaunchPosition); writer.WriteInt32(data.AmmoUsed); writer.WriteFloat(data.AmmoRechargeTime); } buffer = new byte[stream.Length]; Buffer.BlockCopy(stream.GetBuffer(), 0, buffer, 0, buffer.Length); } writerOrg.WriteUInt16((ushort)(buffer.Length + 2)); writerOrg.WriteBytes(buffer); }