Esempio n. 1
0
        public scriptEvents GetStateEventFlags(string state)
        {
            //m_log.Debug("Get event flags for " + state);

            // Check to see if we've already computed the flags for this state
            scriptEvents eventFlags = scriptEvents.None;

            if (m_stateEvents.TryGetValue(state, out eventFlags))
            {
                return(eventFlags);
            }

            if (m_scriptType == null)
            {
                m_scriptType = m_Script.GetType();
            }
            try
            {
                // Fill in the events for this state, cache the results in the map
                foreach (KeyValuePair <string, scriptEvents> kvp in m_eventFlagsMap)
                {
                    MethodInfo ev     = null;
                    string     evname = state + "_event_" + kvp.Key;
                    //m_log.Debug("Trying event "+evname);

                    if (!Events.TryGetValue(evname, out ev))
                    {
                        ev = m_scriptType.GetMethod(evname);
                    }
                    if (ev != null)
                    {
                        //m_log.Debug("Found handler for " + kvp.Key);
                        eventFlags |= kvp.Value;
                    }
                }
            }
            catch (Exception)
            {
                //m_log.Debug("Exeption in GetMethod:\n"+e.ToString());
            }

            // Save the flags we just computed and return the result
            if (eventFlags != 0)
            {
                m_stateEvents.Add(state, eventFlags);
            }

            //m_log.Debug("Returning {0:x}", eventFlags);
            return(eventFlags);
        }
Esempio n. 2
0
        public scriptEvents GetStateEventFlags(string state)
        {
            // Check to see if we've already computed the flags for this state
            scriptEvents eventFlags = scriptEvents.None;

            if (m_stateEvents.TryGetValue(state, out eventFlags))
            {
                return(eventFlags);
            }

            if (m_scriptType == null)
            {
                m_scriptType = m_Script.GetType();
            }
            // Fill in the events for this state, cache the results in the map
            foreach (KeyValuePair <string, scriptEvents> kvp in m_eventFlagsMap)
            {
                try {
                    MethodInfo ev     = null;
                    string     evname = state == "" ? "" : state + "_event_";
                    evname += kvp.Key;
                    //MainConsole.Instance.Debug("Trying event "+evname);

                    ev = m_scriptType.GetMethod(evname);
                    if (ev != null)
                    {
                        //MainConsole.Instance.Debug("Found handler for " + kvp.Key);
                        eventFlags |= kvp.Value;
                    }
                }
                catch (Exception e) {
                    MainConsole.Instance.Debug("Exception in GetMethod for state: " + state + "\n" + e);
                }
            }

            // Save the flags we just computed and return the result
            if (eventFlags != 0)
            {
                try {
                    m_stateEvents.Add(state, eventFlags);
                } catch (Exception e) {
                    MainConsole.Instance.Debug("Exception adding state event for state: " + state + "\n" + e);
                }
            }

            //MainConsole.Instance.Debug("Returning {0:x}", eventFlags);
            return(eventFlags);
        }
Esempio n. 3
0
        public void aggregateScriptEvents()
        {
            AggregateScriptEvents = 0;

            // Aggregate script events
            lock (m_scriptEvents)
            {
                foreach (scriptEvents s in m_scriptEvents.Values)
                {
                    AggregateScriptEvents |= s;
                }
            }

            uint objectflagupdate = 0;

            if (
                ((AggregateScriptEvents & scriptEvents.touch) != 0) ||
                ((AggregateScriptEvents & scriptEvents.touch_end) != 0) ||
                ((AggregateScriptEvents & scriptEvents.touch_start) != 0)
                )
            {
                objectflagupdate |= (uint) PrimFlags.Touch;
            }

            if ((AggregateScriptEvents & scriptEvents.money) != 0)
            {
                objectflagupdate |= (uint) PrimFlags.Money;
            }

            if (AllowedDrop)
            {
                objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
            }

            if (
                ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
                ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
                ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
                ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
                ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
                ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
                (CollisionSound != UUID.Zero)
                )
            {
                // subscribe to physics updates.
                if (PhysActor != null)
                {
                    PhysActor.OnCollisionUpdate += PhysicsCollision;
                    PhysActor.SubscribeEvents(1000);
                }
            }
            else
            {
                if (PhysActor != null)
                {
                    PhysActor.UnSubscribeEvents();
                    PhysActor.OnCollisionUpdate -= PhysicsCollision;
                }
            }

            //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
            //{
            //    ParentGroup.Scene.EventManager.OnScriptTimerEvent += handleTimerAccounting;
            //}
            //else
            //{
            //    ParentGroup.Scene.EventManager.OnScriptTimerEvent -= handleTimerAccounting;
            //}

            LocalFlags = (PrimFlags)objectflagupdate;

            if (ParentGroup != null && ParentGroup.RootPart == this)
            {
                ParentGroup.aggregateScriptEvents();
            }
            else
            {
//                m_log.DebugFormat(
//                    "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents()", Name, LocalId);
                ScheduleFullUpdate();
            }
        }
Esempio n. 4
0
        public void RemoveScriptEvents(UUID scriptid)
        {
            lock (m_scriptEvents)
            {
                if (m_scriptEvents.ContainsKey(scriptid))
                {
                    scriptEvents oldparts = scriptEvents.None;
                    oldparts = (scriptEvents) m_scriptEvents[scriptid];

                    // remove values from aggregated script events
                    AggregateScriptEvents &= ~oldparts;
                    m_scriptEvents.Remove(scriptid);
                    aggregateScriptEvents();
                }
            }
        }
Esempio n. 5
0
        private void SendLandCollisionEvent(SceneObjectGroup dest, scriptEvents ev, ScriptCollidingNotification notify)
        {
            if ((dest.RootPart.ScriptEvents & ev) != 0)
            {
                ColliderArgs LandCollidingMessage = new ColliderArgs();
                List<DetectedObject> colliding = new List<DetectedObject>();

                colliding.Add(CreateDetObjectForGround());
                LandCollidingMessage.Colliders = colliding;

                notify(dest.RootPart.LocalId, LandCollidingMessage);
            }
        }
Esempio n. 6
0
        private void SendCollisionEvent(SceneObjectGroup dest, scriptEvents ev, List<uint> colliders, ScriptCollidingNotification notify)
        {
            ColliderArgs CollidingMessage;

            if (colliders.Count > 0)
            {
                if ((dest.RootPart.ScriptEvents & ev) != 0)
                {
                    CollidingMessage = CreateColliderArgs(dest.RootPart, colliders);

                    if (CollidingMessage.Colliders.Count > 0)
                        notify(dest.RootPart.LocalId, CollidingMessage);
                }
            }
        }
Esempio n. 7
0
        public void aggregateScriptEvents()
        {
            AggregateScriptEvents = 0;

            // Aggregate script events
            lock (m_scriptEvents)
            {
                foreach (scriptEvents s in m_scriptEvents.Values)
                {
                    AggregateScriptEvents |= s;
                }
            }

            uint objectflagupdate = 0;

            if (
                ((AggregateScriptEvents & scriptEvents.touch) != 0) ||
                ((AggregateScriptEvents & scriptEvents.touch_end) != 0) ||
                ((AggregateScriptEvents & scriptEvents.touch_start) != 0)
                )
            {
                objectflagupdate |= (uint) PrimFlags.Touch;
            }

            if ((AggregateScriptEvents & scriptEvents.money) != 0)
            {
                objectflagupdate |= (uint) PrimFlags.Money;
            }

            if (AllowedDrop)
            {
                objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
            }

            // subscribe to physics updates.
            if (PhysActor != null)
            {
                PhysActor.OnCollisionUpdate += PhysicsCollision;
                PhysActor.SubscribeEvents(1000);
            }

            if (m_parentGroup == null)
            {
//                m_log.DebugFormat(
//                    "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents() since m_parentGroup == null", Name, LocalId);
                ScheduleUpdate(PrimUpdateFlags.FullUpdate);
                return;
            }

            LocalFlags=(PrimFlags)objectflagupdate;

            if (m_parentGroup != null && m_parentGroup.RootPart == this)
            {
                m_parentGroup.aggregateScriptEvents();
            }
            else
            {
//                m_log.DebugFormat(
//                    "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents()", Name, LocalId);
                ScheduleUpdate(PrimUpdateFlags.PrimFlags);
            }
        }
Esempio n. 8
0
        public void aggregateScriptEvents()
        {
            if (ParentGroup == null || ParentGroup.RootPart == null)
                return;

            AggregateScriptEvents = 0;

            // Aggregate script events
            lock (m_scriptEvents)
            {
                foreach (scriptEvents s in m_scriptEvents.Values)
                {
                    AggregateScriptEvents |= s;
                }
            }

            uint objectflagupdate = 0;

            if (
                ((AggregateScriptEvents & scriptEvents.touch) != 0) ||
                ((AggregateScriptEvents & scriptEvents.touch_end) != 0) ||
                ((AggregateScriptEvents & scriptEvents.touch_start) != 0)
                )
            {
                objectflagupdate |= (uint) PrimFlags.Touch;
            }

            if ((AggregateScriptEvents & scriptEvents.money) != 0)
            {
                objectflagupdate |= (uint) PrimFlags.Money;
            }

            if (AllowedDrop)
            {
                objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
            }

            SubscribeForCollisionEvents();

            //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
            //{
            //    ParentGroup.Scene.EventManager.OnScriptTimerEvent += handleTimerAccounting;
            //}
            //else
            //{
            //    ParentGroup.Scene.EventManager.OnScriptTimerEvent -= handleTimerAccounting;
            //}

            LocalFlags = (PrimFlags)objectflagupdate;

            if (ParentGroup != null && ParentGroup.RootPart == this)
            {
                ParentGroup.aggregateScriptEvents();
            }
            else
            {
//                m_log.DebugFormat(
//                    "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents()", Name, LocalId);
                ScheduleFullUpdate();
            }
        }
Esempio n. 9
0
        private void SendCollisionEvent(scriptEvents ev, List<uint> colliders, ScriptCollidingNotification notify)
        {
            bool sendToRoot = false;
            ColliderArgs CollidingMessage;

            if (colliders.Count > 0)
            {
                if ((ScriptEvents & ev) != 0)
                {
                    CollidingMessage = CreateColliderArgs(this, colliders);

                    if (CollidingMessage.Colliders.Count > 0)
                        notify(LocalId, CollidingMessage);

                    if (PassCollisions)
                        sendToRoot = true;
                }
                else
                {
                    if ((ParentGroup.RootPart.ScriptEvents & ev) != 0)
                        sendToRoot = true;
                }
                if (sendToRoot && ParentGroup.RootPart != this)
                {
                    CollidingMessage = CreateColliderArgs(ParentGroup.RootPart, colliders);
                    if (CollidingMessage.Colliders.Count > 0)
                        notify(ParentGroup.RootPart.LocalId, CollidingMessage);
                }
            }
        }
Esempio n. 10
0
        /// <summary>
        /// This checks the minimum amount of time between script firings as well as control events, making sure that events do NOT fire after scripts reset, close or restart, etc
        /// </summary>
        /// <param name="ID"></param>
        /// <param name="FunctionName"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        private bool CheckIfEventShouldFire(ScriptData ID, string FunctionName, object[] param)
        {
            if (ID.Loading)
            {
                //If the script is loading, enqueue all events
                return(true);
            }
            //This will happen if the script doesn't compile correctly
            if (ID.Script == null)
            {
                m_log.Info("[AuroraDotNetEngine]: Could not load script from item '" + ID.InventoryItem.Name + "' to fire event " + FunctionName);
                return(false);
            }
            scriptEvents eventType = (scriptEvents)Enum.Parse(typeof(scriptEvents), FunctionName);

            // this must be done even if there is no event method

            if (eventType == scriptEvents.touch_start)
            {
                ID.RemoveTouchEvents = false;
            }
            else if (eventType == scriptEvents.collision_start)
            {
                ID.RemoveCollisionEvents = false;
            }
            else if (eventType == scriptEvents.land_collision_start)
            {
                ID.RemoveLandCollisionEvents = false;
            }


            if ((ID.Script.GetStateEventFlags(ID.State) & (long)eventType) == 0)
            {
                return(false); //If the script doesn't contain the state, don't even bother queueing it
            }
            //Make sure we can execute events at position
            if (!m_scriptEngine.PipeEventsForScript(ID.Part))
            {
                return(false);
            }

            if (eventType == scriptEvents.timer)
            {
                if (ID.TimerQueued)
                {
                    return(false);
                }
                ID.TimerQueued = true;
            }
            else if (eventType == scriptEvents.control)
            {
                int held = ((LSL_Types.LSLInteger)param[1]).value;
                // int changed = ((LSL_Types.LSLInteger)data.Params[2]).value;

                // If the last message was a 0 (nothing held)
                // and this one is also nothing held, drop it
                //
                if (ID.LastControlLevel == held && held == 0)
                {
                    return(true);
                }

                // If there is one or more queued, then queue
                // only changed ones, else queue unconditionally
                //
                if (ID.ControlEventsInQueue > 0)
                {
                    if (ID.LastControlLevel == held)
                    {
                        return(false);
                    }
                }
            }
            else if (eventType == scriptEvents.collision)
            {
                if (ID.CollisionInQueue || ID.RemoveCollisionEvents)
                {
                    return(false);
                }

                ID.CollisionInQueue = true;
            }
            else if (eventType == scriptEvents.moving_start)
            {
                if (ID.MovingInQueue) //Block all other moving_starts until moving_end is called
                {
                    return(false);
                }
                ID.MovingInQueue = true;
            }
            else if (eventType == scriptEvents.moving_end)
            {
                if (!ID.MovingInQueue) //If we get a moving_end after we have sent one event, don't fire another
                {
                    return(false);
                }
            }
            else if (eventType == scriptEvents.collision_end)
            {
                if (ID.RemoveCollisionEvents)
                {
                    return(false);
                }
            }
            else if (eventType == scriptEvents.touch)
            {
                if (ID.TouchInQueue || ID.RemoveTouchEvents)
                {
                    return(false);
                }

                ID.TouchInQueue = true;
            }
            else if (eventType == scriptEvents.touch_end)
            {
                if (ID.RemoveTouchEvents)
                {
                    return(false);
                }
            }
            else if (eventType == scriptEvents.land_collision)
            {
                if (ID.LandCollisionInQueue || ID.RemoveLandCollisionEvents)
                {
                    return(false);
                }

                ID.LandCollisionInQueue = true;
            }
            else if (eventType == scriptEvents.land_collision_end)
            {
                if (ID.RemoveLandCollisionEvents)
                {
                    return(false);
                }
            }
            else if (eventType == scriptEvents.changed)
            {
                Changed changed;
                if (param[0] is Changed)
                {
                    changed = (Changed)param[0];
                }
                else
                {
                    changed = (Changed)(((LSL_Types.LSLInteger)param[0]).value);
                }
                if (ID.ChangedInQueue.Contains(changed))
                {
                    return(false);
                }
                ID.ChangedInQueue.Add(changed);
            }

            if (FunctionName == "state_entry")
            {
                ID.ResetEvents();
            }
            return(true);
        }
Esempio n. 11
0
        public void aggregateScriptEvents()
        {
            AggregateScriptEvents = 0;

            // Aggregate script events
            lock (m_scriptEvents)
            {
                foreach (scriptEvents s in m_scriptEvents.Values)
                {
                    AggregateScriptEvents |= s;
                }
            }

            uint objectflagupdate = 0;

            if (
                ((AggregateScriptEvents & scriptEvents.touch) != 0) ||
                ((AggregateScriptEvents & scriptEvents.touch_end) != 0) ||
                ((AggregateScriptEvents & scriptEvents.touch_start) != 0)
                )
            {
                objectflagupdate |= (uint) PrimFlags.Touch;
            }

            if ((AggregateScriptEvents & scriptEvents.money) != 0)
            {
                objectflagupdate |= (uint) PrimFlags.Money;
            }

            if (AllowedDrop)
            {
                objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
            }

            // subscribe to physics updates.
            //We subscribe by default now... so 'shouldn't' need this
            if ((((AggregateScriptEvents & scriptEvents.collision) != 0) ||
                 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
                 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
                 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
                 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
                 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0)
                ) && PhysActor != null)
            {
                if (!m_hasSubscribedToCollisionEvent)
                {
                    m_hasSubscribedToCollisionEvent = true;
                    PhysActor.OnCollisionUpdate += PhysicsCollision;
                    PhysActor.SubscribeEvents(1000);
                }
            }
            else if (PhysActor != null)
            {
                if (m_hasSubscribedToCollisionEvent)
                {
                    m_hasSubscribedToCollisionEvent = false;
                    PhysActor.OnCollisionUpdate -= PhysicsCollision;
                }
            }

            if (m_parentGroup == null)
            {
//                MainConsole.Instance.DebugFormat(
//                    "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents() since m_parentGroup == null", Name, LocalId);
                ScheduleUpdate(PrimUpdateFlags.FullUpdate);
                return;
            }

            LocalFlags = (PrimFlags) objectflagupdate;

            if (m_parentGroup != null && m_parentGroup.RootPart == this)
            {
                m_parentGroup.aggregateScriptEvents();
            }
            else
            {
//                MainConsole.Instance.DebugFormat(
//                    "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents()", Name, LocalId);
                ScheduleUpdate(PrimUpdateFlags.PrimFlags);
            }
        }
Esempio n. 12
0
        private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify)
        {
            bool sendToRoot = true;

            ColliderArgs LandCollidingMessage = new ColliderArgs();
            List<DetectedObject> colliding = new List<DetectedObject>();
                
            colliding.Add(CreateDetObjectForGround());
            LandCollidingMessage.Colliders = colliding;

            if (Inventory.ContainsScripts())
            {
                if (!PassCollisions)
                    sendToRoot = false;
            }
            if ((ScriptEvents & ev) != 0)
                notify(LocalId, LandCollidingMessage);

            if ((ParentGroup.RootPart.ScriptEvents & ev) != 0 && sendToRoot)
            {
                notify(ParentGroup.RootPart.LocalId, LandCollidingMessage);
            }
        }
Esempio n. 13
0
        /// <summary>
        ///     This removes the event from the queue and allows it to be fired again
        /// </summary>
        /// <param name="QIS"></param>
        public void EventComplete(QueueItemStruct QIS)
        {
            lock (QIS.ID.ScriptEventLock)
            {
                scriptEvents eventType = (scriptEvents)Enum.Parse(typeof(scriptEvents), QIS.functionName);
                switch (eventType)
                {
                case scriptEvents.timer:
                    QIS.ID.TimerInQueue = false;
                    break;

                case scriptEvents.control:
                    if (QIS.ID.ControlEventsInQueue > 0)
                    {
                        QIS.ID.ControlEventsInQueue--;
                    }
                    break;

                case scriptEvents.collision:
                    QIS.ID.CollisionInQueue = false;
                    break;

                case scriptEvents.collision_end:
                    QIS.ID.CollisionInQueue = false;
                    break;

                case scriptEvents.moving_end:
                    QIS.ID.MovingInQueue = false;
                    break;

                case scriptEvents.touch:
                    QIS.ID.TouchInQueue = false;
                    break;

                case scriptEvents.touch_end:
                    QIS.ID.TouchInQueue = false;
                    break;

                case scriptEvents.land_collision:
                    QIS.ID.LandCollisionInQueue = false;
                    break;

                case scriptEvents.land_collision_end:
                    QIS.ID.LandCollisionInQueue = false;
                    break;

                case scriptEvents.sensor:
                    QIS.ID.SensorInQueue = false;
                    break;

                case scriptEvents.no_sensor:
                    QIS.ID.NoSensorInQueue = false;
                    break;

                case scriptEvents.at_target:
                    QIS.ID.AtTargetInQueue = false;
                    break;

                case scriptEvents.not_at_target:
                    QIS.ID.NotAtTargetInQueue = false;
                    break;

                case scriptEvents.at_rot_target:
                    QIS.ID.AtRotTargetInQueue = false;
                    break;

                case scriptEvents.not_at_rot_target:
                    QIS.ID.NotAtRotTargetInQueue = false;
                    break;

                case scriptEvents.changed:
                    Changed scriptChanged;
                    if (QIS.param[0] is Changed)
                    {
                        scriptChanged = (Changed)QIS.param[0];
                    }
                    else
                    {
                        scriptChanged = (Changed)(((LSL_Types.LSLInteger)QIS.param[0]).value);
                    }
                    QIS.ID.ChangedInQueue.Remove(scriptChanged);
                    break;
                }
            }
        }
Esempio n. 14
0
 public void RemoveScriptEvents(UUID scriptid)
 {
     scriptEvents oldparts;
     if (m_scriptEvents.Remove(scriptid, out oldparts))
     {
         // remove values from aggregated script events
         AggregateScriptEvents &= ~oldparts;
         aggregateScriptEvents();
     }
 }
Esempio n. 15
0
        public void aggregateScriptEvents()
        {
            AggregateScriptEvents = 0;

            // Aggregate script events
            lock (m_scriptEvents)
            {
                foreach (scriptEvents s in m_scriptEvents.Values)
                {
                    AggregateScriptEvents |= s;
                }
            }

            uint objectflagupdate = 0;

            if (
                ((AggregateScriptEvents & scriptEvents.touch) != 0) ||
                ((AggregateScriptEvents & scriptEvents.touch_end) != 0) ||
                ((AggregateScriptEvents & scriptEvents.touch_start) != 0)
                )
            {
                objectflagupdate |= (uint) PrimFlags.Touch;
            }

            if ((AggregateScriptEvents & scriptEvents.money) != 0)
            {
                objectflagupdate |= (uint) PrimFlags.Money;
            }

            if (AllowedDrop)
            {
                objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
            }

            if (
                ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
                ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
                ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
                (CollisionSound != UUID.Zero)
                )
            {
                // subscribe to physics updates.
                if (PhysActor != null)
                {
                    PhysActor.OnCollisionUpdate += PhysicsCollision;
                    PhysActor.SubscribeEvents(1000);

                }
            }
            else
            {
                if (PhysActor != null)
                {
                    PhysActor.UnSubscribeEvents();
                    PhysActor.OnCollisionUpdate -= PhysicsCollision;
                }
            }

            if (m_parentGroup == null)
            {
                ScheduleFullUpdate();
                return;
            }

            if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
            {
                m_parentGroup.Scene.EventManager.OnScriptTimerEvent += handleTimerAccounting;
            }
            else
            {
                m_parentGroup.Scene.EventManager.OnScriptTimerEvent -= handleTimerAccounting;
            }

            LocalFlags=(PrimFlags)objectflagupdate;

            if (m_parentGroup != null && m_parentGroup.RootPart == this)
                m_parentGroup.aggregateScriptEvents();
            else
                ScheduleFullUpdate();
        }