diff --git a/Lidgren XNA Extensions/Lidgren XNA Extensions.sln b/Lidgren XNA Extensions/Lidgren XNA Extensions.sln new file mode 100644 index 0000000..702969f --- /dev/null +++ b/Lidgren XNA Extensions/Lidgren XNA Extensions.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lidgren XNA Extensions", "Lidgren XNA Extensions\Lidgren XNA Extensions.csproj", "{2B661ABD-63A8-4916-A94B-034729231271}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lidgren.Network", "..\Lidgren.Network\Lidgren.Network.csproj", "{FA245447-5F23-4AA1-BD5F-8D2DDF33CFBD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2B661ABD-63A8-4916-A94B-034729231271}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2B661ABD-63A8-4916-A94B-034729231271}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2B661ABD-63A8-4916-A94B-034729231271}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2B661ABD-63A8-4916-A94B-034729231271}.Release|Any CPU.Build.0 = Release|Any CPU + {FA245447-5F23-4AA1-BD5F-8D2DDF33CFBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FA245447-5F23-4AA1-BD5F-8D2DDF33CFBD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FA245447-5F23-4AA1-BD5F-8D2DDF33CFBD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FA245447-5F23-4AA1-BD5F-8D2DDF33CFBD}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Lidgren XNA Extensions/Lidgren XNA Extensions/Lidgren XNA Extensions.csproj b/Lidgren XNA Extensions/Lidgren XNA Extensions/Lidgren XNA Extensions.csproj new file mode 100644 index 0000000..aa2bc4e --- /dev/null +++ b/Lidgren XNA Extensions/Lidgren XNA Extensions/Lidgren XNA Extensions.csproj @@ -0,0 +1,66 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {2B661ABD-63A8-4916-A94B-034729231271} + Library + Properties + Lidgren.Network.Xna + Lidgren.Network.Xna + v3.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + 3.5 + + + 3.5 + + + 3.5 + + + + + + + + + + + {FA245447-5F23-4AA1-BD5F-8D2DDF33CFBD} + Lidgren.Network + + + + + \ No newline at end of file diff --git a/Lidgren XNA Extensions/Lidgren XNA Extensions/Properties/AssemblyInfo.cs b/Lidgren XNA Extensions/Lidgren XNA Extensions/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f71e8ae --- /dev/null +++ b/Lidgren XNA Extensions/Lidgren XNA Extensions/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Lidgren XNA Extensions")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("Lidgren XNA Extensions")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("f9189a05-8455-4b82-b114-a806db01c367")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Lidgren XNA Extensions/Lidgren XNA Extensions/XNAExtensions.cs b/Lidgren XNA Extensions/Lidgren XNA Extensions/XNAExtensions.cs new file mode 100644 index 0000000..d6ef3a6 --- /dev/null +++ b/Lidgren XNA Extensions/Lidgren XNA Extensions/XNAExtensions.cs @@ -0,0 +1,296 @@ +using System; +using System.Collections.Generic; + +using Lidgren.Network; + +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics.PackedVector; + +namespace Lidgren.Network.Xna +{ + public static class XNAExtensions + { + /// + /// Write a Point + /// + public static void Write(this NetOutgoingMessage message, Point value) + { + message.Write(value.X); + message.Write(value.Y); + } + + /// + /// Read a Point + /// + public static Point ReadPoint(this NetIncomingMessage message) + { + return new Point(message.ReadInt32(), message.ReadInt32()); + } + + /// + /// Write a Single with half precision (16 bits) + /// + public static void WriteHalfPrecision(this NetOutgoingMessage message, float value) + { + message.Write(new HalfSingle(value).PackedValue); + } + + /// + /// Reads a half precision Single written using WriteHalfPrecision(float) + /// + public static float ReadHalfPrecisionSingle(this NetIncomingMessage message) + { + HalfSingle h = new HalfSingle(); + h.PackedValue = message.ReadUInt16(); + return h.ToSingle(); + } + + /// + /// Writes a Vector2 + /// + public static void Write(this NetOutgoingMessage message, Vector2 vector) + { + message.Write(vector.X); + message.Write(vector.Y); + } + + /// + /// Reads a Vector2 + /// + public static Vector2 ReadVector2(this NetIncomingMessage message) + { + Vector2 retval; + retval.X = message.ReadSingle(); + retval.Y = message.ReadSingle(); + return retval; + } + + /// + /// Writes a Vector3 + /// + public static void Write(this NetOutgoingMessage message, Vector3 vector) + { + message.Write(vector.X); + message.Write(vector.Y); + message.Write(vector.Z); + } + + /// + /// Writes a Vector3 at half precision + /// + public static void WriteHalfPrecision(this NetOutgoingMessage message, Vector3 vector) + { + message.Write(new HalfSingle(vector.X).PackedValue); + message.Write(new HalfSingle(vector.Y).PackedValue); + message.Write(new HalfSingle(vector.Z).PackedValue); + } + + /// + /// Reads a Vector3 + /// + public static Vector3 ReadVector3(this NetIncomingMessage message) + { + Vector3 retval; + retval.X = message.ReadSingle(); + retval.Y = message.ReadSingle(); + retval.Z = message.ReadSingle(); + return retval; + } + + /// + /// Writes a Vector3 at half precision + /// + public static Vector3 ReadHalfPrecisionVector3(this NetIncomingMessage message) + { + HalfSingle hx = new HalfSingle(); + hx.PackedValue = message.ReadUInt16(); + + HalfSingle hy = new HalfSingle(); + hy.PackedValue = message.ReadUInt16(); + + HalfSingle hz = new HalfSingle(); + hz.PackedValue = message.ReadUInt16(); + + Vector3 retval; + retval.X = hx.ToSingle(); + retval.Y = hy.ToSingle(); + retval.Z = hz.ToSingle(); + return retval; + } + + /// + /// Writes a Vector4 + /// + public static void Write(this NetOutgoingMessage message, Vector4 vector) + { + message.Write(vector.X); + message.Write(vector.Y); + message.Write(vector.Z); + message.Write(vector.W); + } + + /// + /// Reads a Vector4 + /// + public static Vector4 ReadVector4(this NetIncomingMessage message) + { + Vector4 retval; + retval.X = message.ReadSingle(); + retval.Y = message.ReadSingle(); + retval.Z = message.ReadSingle(); + retval.W = message.ReadSingle(); + return retval; + } + + + /// + /// Writes a unit vector (ie. a vector of length 1.0, for example a surface normal) + /// using specified number of bits + /// + public static void WriteUnitVector3(this NetOutgoingMessage message, Vector3 unitVector, int numberOfBits) + { + float x = unitVector.X; + float y = unitVector.Y; + float z = unitVector.Z; + double invPi = 1.0 / Math.PI; + float phi = (float)(Math.Atan2(x, y) * invPi); + float theta = (float)(Math.Atan2(z, Math.Sqrt(x * x + y * y)) * (invPi * 2)); + + int halfBits = numberOfBits / 2; + message.WriteSignedSingle(phi, halfBits); + message.WriteSignedSingle(theta, numberOfBits - halfBits); + } + + /// + /// Reads a unit vector written using WriteUnitVector3(numberOfBits) + /// + public static Vector3 ReadUnitVector3(this NetIncomingMessage message, int numberOfBits) + { + int halfBits = numberOfBits / 2; + float phi = message.ReadSignedSingle(halfBits) * (float)Math.PI; + float theta = message.ReadSignedSingle(numberOfBits - halfBits) * (float)(Math.PI * 0.5); + + Vector3 retval; + retval.X = (float)(Math.Sin(phi) * Math.Cos(theta)); + retval.Y = (float)(Math.Cos(phi) * Math.Cos(theta)); + retval.Z = (float)Math.Sin(theta); + + return retval; + } + + /// + /// Writes a unit quaternion using the specified number of bits per element + /// for a total of 4 x bitsPerElements bits. Suggested value is 8 to 24 bits. + /// + public static void WriteRotation(this NetOutgoingMessage message, Quaternion quaternion, int bitsPerElement) + { + if (quaternion.X > 1.0f) + quaternion.X = 1.0f; + if (quaternion.Y > 1.0f) + quaternion.Y = 1.0f; + if (quaternion.Z > 1.0f) + quaternion.Z = 1.0f; + if (quaternion.W > 1.0f) + quaternion.W = 1.0f; + if (quaternion.X < -1.0f) + quaternion.X = -1.0f; + if (quaternion.Y < -1.0f) + quaternion.Y = -1.0f; + if (quaternion.Z < -1.0f) + quaternion.Z = -1.0f; + if (quaternion.W < -1.0f) + quaternion.W = -1.0f; + + message.WriteSignedSingle(quaternion.X, bitsPerElement); + message.WriteSignedSingle(quaternion.Y, bitsPerElement); + message.WriteSignedSingle(quaternion.Z, bitsPerElement); + message.WriteSignedSingle(quaternion.W, bitsPerElement); + } + + /// + /// Reads a unit quaternion written using WriteRotation(... ,bitsPerElement) + /// + public static Quaternion ReadRotation(this NetIncomingMessage message, int bitsPerElement) + { + Quaternion retval; + retval.X = message.ReadSignedSingle(bitsPerElement); + retval.Y = message.ReadSignedSingle(bitsPerElement); + retval.Z = message.ReadSignedSingle(bitsPerElement); + retval.W = message.ReadSignedSingle(bitsPerElement); + return retval; + } + + /// + /// Writes an orthonormal matrix (rotation, translation but not scaling or projection) + /// + public static void WriteMatrix(this NetOutgoingMessage message, ref Matrix matrix) + { + Quaternion rot = Quaternion.CreateFromRotationMatrix(matrix); + WriteRotation(message, rot, 24); + message.Write(matrix.M41); + message.Write(matrix.M42); + message.Write(matrix.M43); + } + + /// + /// Writes an orthonormal matrix (rotation, translation but no scaling or projection) + /// + public static void WriteMatrix(this NetOutgoingMessage message, Matrix matrix) + { + Quaternion rot = Quaternion.CreateFromRotationMatrix(matrix); + WriteRotation(message, rot, 24); + message.Write(matrix.M41); + message.Write(matrix.M42); + message.Write(matrix.M43); + } + + /// + /// Reads a matrix written using WriteMatrix() + /// + public static Matrix ReadMatrix(this NetIncomingMessage message) + { + Quaternion rot = ReadRotation(message, 24); + Matrix retval = Matrix.CreateFromQuaternion(rot); + retval.M41 = message.ReadSingle(); + retval.M42 = message.ReadSingle(); + retval.M43 = message.ReadSingle(); + return retval; + } + + /// + /// Reads a matrix written using WriteMatrix() + /// + public static void ReadMatrix(this NetIncomingMessage message, ref Matrix destination) + { + Quaternion rot = ReadRotation(message, 24); + destination = Matrix.CreateFromQuaternion(rot); + destination.M41 = message.ReadSingle(); + destination.M42 = message.ReadSingle(); + destination.M43 = message.ReadSingle(); + } + + /// + /// Writes a bounding sphere + /// + public static void Write(this NetOutgoingMessage message, BoundingSphere bounds) + { + message.Write(bounds.Center.X); + message.Write(bounds.Center.Y); + message.Write(bounds.Center.Z); + message.Write(bounds.Radius); + } + + /// + /// Reads a bounding sphere written using Write(message, BoundingSphere) + /// + public static BoundingSphere ReadBoundingSphere(this NetIncomingMessage message) + { + BoundingSphere retval; + retval.Center.X = message.ReadSingle(); + retval.Center.Y = message.ReadSingle(); + retval.Center.Z = message.ReadSingle(); + retval.Radius = message.ReadSingle(); + return retval; + } + } +} diff --git a/Lidgren.Network/NetPeer.cs b/Lidgren.Network/NetPeer.cs index 60034a6..98b0b89 100644 --- a/Lidgren.Network/NetPeer.cs +++ b/Lidgren.Network/NetPeer.cs @@ -224,6 +224,11 @@ namespace Lidgren.Network /// /// Send a message to an existing connection /// + /// The NetOutgoingMessage to send + /// The recipient connection + /// How to deliver the message + /// Delivery channel (0-31) + /// True if the message was queued for delivery, else false public bool SendMessage(NetOutgoingMessage msg, NetConnection recipient, NetDeliveryMethod deliveryMethod, int channel) { if (msg.IsSent) @@ -246,12 +251,13 @@ namespace Lidgren.Network /// /// Send a message to a number of existing connections /// + /// Delivery channel (0-31) public bool SendMessage(NetOutgoingMessage msg, IEnumerable recipients, NetDeliveryMethod deliveryMethod, int channel) { if (msg.IsSent) throw new NetException("Message has already been sent!"); - if (channel < 0 || channel > 63) - throw new NetException("Channel must be between 0 and 63"); + if (channel < 0 || channel > NetConstants.NetChannelsPerDeliveryMethod) + throw new NetException("Channel must be between 0 and " + (NetConstants.NetChannelsPerDeliveryMethod - 1)); if (channel != 0 && (deliveryMethod == NetDeliveryMethod.Unreliable || deliveryMethod == NetDeliveryMethod.ReliableUnordered)) throw new NetException("Channel must be 0 for Unreliable and ReliableUnordered");