/// <summary>
        /// Calls <see cref="ClientInterestArea.OnItemSubscribed">ClientInterestArea.OnItemSubscribed</see> and sends event <see cref="ItemSubscribed"/> to the client.
        /// </summary>
        /// <param name="snapshot">
        /// The item snapshot.
        /// </param>
        protected override void OnItemSubscribed(ItemSnapshot snapshot)
        {
            base.OnItemSubscribed(snapshot);

            var mmoSnapshot = (MmoItemSnapshot)snapshot;
            var item = snapshot.Source;

            var subscribeEvent = new ItemSubscribed
                {
                    ItemId = item.Id,
                    ItemType = item.Type,
                    Position = mmoSnapshot.Coordinate,
                    PropertiesRevision = snapshot.PropertiesRevision,
                    InterestAreaId = this.Id,
                    Rotation = mmoSnapshot.Rotation

                };

            #region PopBloop

            var mmoItem = (MmoItem)item;

            if (mmoItem != null)
            {
                subscribeEvent.AvatarName = mmoItem.AvatarName;
                subscribeEvent.Animation = mmoItem.Animation;
                subscribeEvent.AnimationSpeed = mmoItem.AnimationSpeed;
                subscribeEvent.AnimationWrap = mmoItem.AnimationWrap;
            }
            else
            {
                subscribeEvent.AvatarName = "Unknown";
            }

            #endregion

            var eventData = new EventData((byte)EventCode.ItemSubscribed, subscribeEvent);
            this.Peer.SendEvent(eventData, new SendParameters { ChannelId = Settings.ItemEventChannel });
        }
        /// <summary>
        ///   Receives the <see cref = "ItemSnapshot" />.
        ///   auto subscribes item if necessary.
        /// </summary>
        /// <param name = "message">
        ///   The message.
        /// </param>
        internal void ReceiveItemSnapshot(ItemSnapshot message)
        {
            lock (this.SyncRoot)
            {
                // auto subscribe item?
                if (this.AutoSubscribeItem(message.Source) == false)
                {
                    return;
                }

                ItemAutoSubscription subscription;

                // already subscribed
                if (this.autoManagedItemSubscriptions.TryGetValue(message.Source, out subscription))
                {
                    // dropped out of world, unsubscribe
                    if (message.WorldRegion == null)
                    {
                        this.AutoUnsubscribeItem(subscription);
                        return;
                    }

                    // update position
                    subscription.ItemPosition = message.Position;
                    subscription.WorldRegion = message.WorldRegion;
                    return;
                }

                // already subscribed
                if (this.manualManagedItemSubscriptions.ContainsKey(message.Source))
                {
                    return;
                }

                // item not in view
                if (message.WorldRegion == null || this.subscribedWorldRegions.ContainsKey(message.WorldRegion) == false)
                {
                    return;
                }

                // unsubscribe if item is disposed
                IDisposable disposeListener = message.Source.DisposeChannel.Subscribe(this.subscriptionManagementFiber, this.AutoSubscribedItem_OnItemDisposed);

                // unsubscribe if item moves out of range
                IDisposable itemPositionEvaluator = message.Source.PositionUpdateChannel.SubscribeToLast(
                    this.subscriptionManagementFiber, this.AutoSubscribedItem_OnItemPosition, ItemAutoUnsubcribeDelayMilliseconds);

                var itemSubscription = new ItemAutoSubscription(
                    message.Source, message.Position, message.WorldRegion, new UnsubscriberCollection(disposeListener, itemPositionEvaluator));
                this.autoManagedItemSubscriptions.Add(message.Source, itemSubscription);

                this.OnItemSubscribed(message);
            }
        }
 /// <summary>
 ///   Does nothing.
 ///   Called after subscribing an <see cref = "Item" />, either manually (<see cref = "SubscribeItem">SubscribeItem</see>) or automatically.
 /// </summary>
 /// <param name = "itemSnapshot">
 ///   The hearbeat message from the subscribed item.
 /// </param>
 /// <remarks>
 ///   Thread Safety: This method does not provide thread safe access to the <see cref = "Item" />. 
 ///   Instead of accessing the item directly override <see cref = "Item.GetItemSnapshot" /> subsclass that contains a copy of the required values.
 /// </remarks>
 /// <remarks>
 ///   Thread Safety: This method is executed while having an exclusive lock on <see cref = "SyncRoot" />.
 /// </remarks>
 protected virtual void OnItemSubscribed(ItemSnapshot itemSnapshot)
 {
 }
        /// <summary>
        ///   Subscribes the <see cref = "PeerBase" /> to the item's <see cref = "Item.EventChannel" />.
        /// </summary>
        /// <param name = "itemSnapshot">
        ///   The item snapshot message.
        /// </param>
        protected override void OnItemSubscribed(ItemSnapshot itemSnapshot)
        {
            Item item = itemSnapshot.Source;

            // publish event messages
            IDisposable messageReceiver = item.EventChannel.Subscribe(this.fiber, this.SubscribedItem_OnItemEvent);
            this.eventChannelSubscriptions.Add(item, messageReceiver);
        }