public ViewerCircuit(
     UDPCircuitsManager server,
     UInt32 circuitcode,
     UUID sessionID,
     UUID agentID,
     EndPoint remoteEndPoint)
     : base(server, circuitcode)
 {
     RegionData     = new RegionHandshakeData();
     RemoteEndPoint = remoteEndPoint;
     SessionID      = sessionID;
     AgentID        = agentID;
     MessageRouting.Add(MessageType.UpdateCreateInventoryItem, (m) => OnUpdateCreateInventoryItem?.Invoke(m));
     MessageRouting.Add(MessageType.BulkUpdateInventory, (m) => OnBulkUpdateInventory?.Invoke(m));
 }
        protected override void OnCircuitSpecificPacketReceived(MessageType mType, UDPPacket pck)
        {
            Func <UDPPacket, Message> del;

            if (m_PacketDecoder.PacketTypes.TryGetValue(mType, out del))
            {
                Message m = del(pck);
                /* we got a decoder, so we can make use of it */
                m.CircuitAgentID = AgentID;
                try
                {
                    m.CircuitAgentOwner = UGUI.Unknown;
                    m.CircuitSessionID  = SessionID;
                    m.CircuitSceneID    = UUID.Zero;
                }
                catch
                {
                    /* this is a specific error that happens only during logout */
                    return;
                }

                if (m.Number == MessageType.RegionHandshake)
                {
                    RegionData = new RegionHandshakeData((RegionHandshake)m);
                    var reply = new RegionHandshakeReply()
                    {
                        SessionID = SessionID,
                        AgentID   = AgentID,
                        Flags     = 0
                    };
                    SendMessage(reply);
                }
                else if (m.Number == MessageType.EconomyData)
                {
                    var ed = (EconomyData)m;
                    EconomyInfo = new EconomyInfo()
                    {
                        ObjectCapacity          = ed.ObjectCapacity,
                        ObjectCount             = ed.ObjectCount,
                        PriceEnergyUnit         = ed.PriceEnergyUnit,
                        PriceObjectClaim        = ed.PriceObjectClaim,
                        PricePublicObjectDecay  = ed.PricePublicObjectDecay,
                        PricePublicObjectDelete = ed.PricePublicObjectDelete,
                        PriceParcelClaim        = ed.PriceParcelClaim,
                        PriceParcelClaimFactor  = ed.PriceParcelClaimFactor,
                        PriceUpload             = ed.PriceUpload,
                        PriceRentLight          = ed.PriceRentLight,
                        TeleportMinPrice        = ed.TeleportMinPrice,
                        TeleportPriceExponent   = ed.TeleportPriceExponent,
                        EnergyEfficiency        = ed.EnergyEfficiency,
                        PriceObjectRent         = ed.PriceObjectRent,
                        PriceObjectScaleFactor  = ed.PriceObjectScaleFactor,
                        PriceParcelRent         = ed.PriceParcelRent,
                        PriceGroupCreate        = ed.PriceGroupCreate
                    };
                }

                /* we keep the circuit relatively dumb so that we have no other logic than how to send and receive messages to the remote sim.
                 * It merely collects delegates to other objects as well to call specific functions.
                 */
                Action <Message> mdel;
                if (MessageRouting.TryGetValue(m.Number, out mdel))
                {
                    mdel(m);
                }
                else if (m.Number == MessageType.ImprovedInstantMessage)
                {
                    var im = (ImprovedInstantMessage)m;
                    if (im.CircuitAgentID != im.AgentID ||
                        im.CircuitSessionID != im.SessionID)
                    {
                        return;
                    }
                    if (IMMessageRouting.TryGetValue(im.Dialog, out mdel))
                    {
                        mdel(m);
                    }
                    else if (EnableReceiveQueue)
                    {
                        ReceiveQueue.Enqueue(m);
                    }
                }
                else if (m.Number == MessageType.GenericMessage)
                {
                    var genMsg = (GenericMessage)m;
                    if (GenericMessageRouting.TryGetValue(genMsg.Method, out mdel))
                    {
                        mdel(m);
                    }
                    else if (EnableReceiveQueue)
                    {
                        ReceiveQueue.Enqueue(m);
                    }
                }
                else if (m.Number == MessageType.LargeGenericMessage)
                {
                    var genMsg = (LargeGenericMessage)m;
                    if (LargeGenericMessageRouting.TryGetValue(genMsg.Method, out mdel))
                    {
                        mdel(m);
                    }
                    else if (EnableReceiveQueue)
                    {
                        ReceiveQueue.Enqueue(m);
                    }
                }
                else if (m.Number == MessageType.GodlikeMessage)
                {
                    var genMsg = (GodlikeMessage)m;
                    if (GodlikeMessageRouting.TryGetValue(genMsg.Method, out mdel))
                    {
                        mdel(m);
                    }
                    else if (EnableReceiveQueue)
                    {
                        ReceiveQueue.Enqueue(m);
                    }
                }
                else if (EnableReceiveQueue)
                {
                    ReceiveQueue.Enqueue(m);
                }
            }
            else
            {
                /* Ignore we have no decoder for that */
            }
        }