///--------------------------------------------------------------------
        /// MirrorpunchCommon methods
        ///--------------------------------------------------------------------

        /// <summary>
        /// Initialize unique functionality and variables
        /// </summary>
        public virtual void Init()
        {
            Output.Log($"Initializing {Name}");

            if (MpSteam == null)
            {
                Output.LogError($"{Name}: Reference to MirrorpunchSteam is null in Init, can't proceed");
                ResetStatus();
                return;
            }

            RegisterCallbacks();
        }
        /// <summary>
        /// Static method to process any messages in the receive queue
        /// </summary>
        public static bool ProcessMessages(MirrorpunchCommon a)
        {
            if (!a.Active)
            {
                return(false);   // Don't process messages if inactive
            }
            if (!a.ReceiveQueue.HasNodes)
            {
                return(true);    // Only return false if something goes wrong
            }
            DateTime timer = DateTime.Now;

            try
            {
                // Want to avoid a potential infinite loop, so only looping through a known number of nodes
                for (int i = 0; i < a.ReceiveQueue.Length; i++)
                {
                    P2Packet?packet = a.ReceiveQueue.Dequeue();

                    if (packet == null)
                    {
                        continue;
                    }

                    SteamId senderId = packet.Value.SteamId;

                    if (packet.Value.Data == null || packet.Value.Data.Length == 0)
                    {
                        continue;
                    }

                    if (!a.IsKnown(senderId))
                    {
                        byte byteType = packet.Value.Data[0];

                        if (byteType < 0 || byteType >= (byte)PacketType.NUM_TYPES)
                        {
                            throw new Exception("Packet with invalid PacketType received from unexpected SteamId; check sending code?");
                        }

                        PacketType packetType = (PacketType)byteType;

                        switch (packetType)
                        {
                        case PacketType.CONNECT:
                            Output.Log($"Connection requested by {senderId}");
                            a.OnSessionRequest(senderId);
                            break;

                        case PacketType.CONNECTION_ACCEPTED:
                            Output.Log($"Connection accepted by {senderId}");
                            break;

                        default:
                            throw new Exception($"Unexpected packet type received from {senderId} [{byteType}]");
                        }

                        // Packet from unknown sender handled without exception, continue
                        continue;
                    }

                    // Received a packet from a known sender, handle received data
                    byte[] data = packet.Value.Data;
                    a.OnReceivedData(senderId, data);
                }

                TimeSpan checkTimer = DateTime.Now - timer;

                if (checkTimer.TotalMilliseconds >= MP_PROCESS_WARNING)
                {
                    Output.LogWarning($"{a.Name}: ProcessMessages took longer than expected ({checkTimer.TotalMilliseconds} ms)");
                }

                // We made it here without an exception, report success
                return(true);
            }
            catch (Exception e)
            {
                Output.LogError($"{a.Name}: Exception in ProcessMessages ({e.Message})");
                return(false);
            }
        }