// unpack a message we received public static T UnpackFromByteArray <T>(byte[] data) where T : struct, NetworkMessage { using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(data)) { int msgType = MessagePacker.GetId <T>(); int id = networkReader.ReadUInt16(); if (id != msgType) { throw new FormatException("Invalid message, could not unpack " + typeof(T).FullName); } return(networkReader.Read <T>()); } }
/// <summary> /// Internal method to get the current Queue Item from the stream at its current position /// </summary> /// <returns>FrameQueueItem</returns> private RpcFrameQueueItem GetCurrentQueueItem() { //Write the packed version of the queueItem to our current queue history buffer m_CurrentQueueItem.QueueItemType = (RpcQueueContainer.QueueItemType)QueueReader.ReadUInt16(); m_CurrentQueueItem.Timestamp = QueueReader.ReadSingle(); m_CurrentQueueItem.NetworkId = QueueReader.ReadUInt64(); //Clear out any current value for the client ids m_CurrentQueueItem.ClientNetworkIds = new ulong[0]; //If outbound, determine if any client ids needs to be added if (m_QueueFrameType == QueueFrameType.Outbound) { //Outbound we care about both channel and clients m_CurrentQueueItem.NetworkChannel = (NetworkChannel)QueueReader.ReadByteDirect(); int numClients = QueueReader.ReadInt32(); if (numClients > 0 && numClients < m_MaximumClients) { ulong[] clientIdArray = new ulong[numClients]; for (int i = 0; i < numClients; i++) { clientIdArray[i] = QueueReader.ReadUInt64(); } if (m_CurrentQueueItem.ClientNetworkIds == null) { m_CurrentQueueItem.ClientNetworkIds = clientIdArray; } else { m_CurrentQueueItem.ClientNetworkIds = clientIdArray; } } } m_CurrentQueueItem.UpdateStage = m_StreamUpdateStage; //Get the stream size m_CurrentQueueItem.StreamSize = QueueReader.ReadInt64(); //Sanity checking for boundaries if (m_CurrentQueueItem.StreamSize < m_MaxStreamBounds && m_CurrentQueueItem.StreamSize > k_MinStreamBounds) { //Inbound and Outbound message streams are handled differently if (m_QueueFrameType == QueueFrameType.Inbound) { //Get our offset long position = QueueReader.ReadInt64(); //Always make sure we are positioned at the start of the stream before we write m_CurrentQueueItem.NetworkBuffer.Position = 0; //Write the entire message to the m_CurrentQueueItem stream (1 stream is re-used for all incoming RPCs) m_CurrentQueueItem.NetworkWriter.ReadAndWrite(QueueReader, m_CurrentQueueItem.StreamSize); //Reset the position back to the offset so std rpc API can process the message properly //(i.e. minus the already processed header) m_CurrentQueueItem.NetworkBuffer.Position = position; } else { //Create a byte array segment for outbound sending m_CurrentQueueItem.MessageData = QueueReader.CreateArraySegment((int)m_CurrentQueueItem.StreamSize, (int)QueueBuffer.Position); } } else { UnityEngine.Debug.LogWarning($"{nameof(m_CurrentQueueItem)}.{nameof(RpcFrameQueueItem.StreamSize)} exceeds allowed size ({m_MaxStreamBounds} vs {m_CurrentQueueItem.StreamSize})! Exiting from the current RpcQueue enumeration loop!"); m_CurrentQueueItem.QueueItemType = RpcQueueContainer.QueueItemType.None; } return(m_CurrentQueueItem); }