Example #1
0
 public void SetPropertyValues(HashSet <SyncableProperties.Type> properties)
 {
     foreach (SyncableProperties.Type property in properties)
     {
         SyncedProperty syncedProperty;
         CurrentlySyncedProperties.TryGetValue(property, out syncedProperty);
         if (syncedProperty != null)
         {
             SetPropertyValue(syncedProperty);
         }
     }
 }
Example #2
0
        /// <summary>
        /// Compare the value (not "reference") of the given property.
        /// Assumption: the caller has already checked if PhysActor exists
        /// if there are physics properties updated.
        /// If the value maintained here is different from that in SP data,
        /// synchronize the two:
        /// (1) if the cached value has a timestamp newer than lastUpdateByLocalTS
        /// overwrite the SP's property with the cached value (effectively
        /// undoing the local write operation that just happened).
        /// (2) otherwise, copy SP's data and update timestamp and syncID
        /// as indicated by "lastUpdateByLocalTS" and "syncID".
        /// </summary>
        /// <param name="sp"></param>
        /// <param name="property"></param>
        /// <param name="lastUpdateByLocalTS"></param>
        /// <param name="syncID"></param>
        /// <returns>Return true if the property's value maintained in this
        /// RegionSyncModule is replaced by SP's data.</returns>
        private bool CompareValue_UpdateByLocal(ScenePresence sp, SyncableProperties.Type property, long lastUpdateByLocalTS, string syncID)
        {
            //DebugLog.WarnFormat("[SYNC INFO PRESENCE] CompareValue_UpdateByLocal: Updating property {0} on sp {1}", property.ToString(), sp.UUID);
            // Check to see if this property is in the sync cache for this object.
            // If not, add it and initialize value to value in ScenePresence.
            bool ret = false;

            SyncedProperty syncedProperty;

            CurrentlySyncedProperties.TryGetValue(property, out syncedProperty);

            // If synced property is not in cache, add it now
            if (syncedProperty == null)
            {
                Object initValue = GetPropertyValue(sp, property);
                if (initValue != null)
                {
                    CurrentlySyncedProperties.Add(property, new SyncedProperty(property, initValue, lastUpdateByLocalTS, syncID));
                    ret = true;
                }
                return(ret);
            }

            // First, check if the value maintained here is different from that in SP's.
            // If different, next check if the timestamp in SyncInfo is newer than lastUpdateByLocalTS;
            // if so (although ideally should not happen, but due to things likc clock not so perfectly
            // sync'ed, it might happen), overwrite SP's value with what's maintained
            // in SyncInfo; otherwise, copy SP's data to SyncInfo.
            Object value = GetPropertyValue(sp, property);

            // If both null, no update needed
            if (syncedProperty.LastUpdateValue == null && value == null)
            {
                return(false);
            }

            switch (property)
            {
            default:
                // If one is null and the other is not, or if the references are different, the property was changed.
                // This will perform a value comparison for strings in C#. We could use String.Clone instead for string properties.
                if ((value == null && syncedProperty.LastUpdateValue != null) ||
                    (value != null && syncedProperty.LastUpdateValue == null) ||
                    (!value.Equals(syncedProperty.LastUpdateValue)))
                {
                    if (value != null)
                    {
                        // Some values, even if they are not 'equal', might be close enough to be equal.
                        // Note that the 'Equals()' above will most always return 'false' for lists and OSDMaps
                        //     since they are probably not the same object.
                        // Returning a 'false' here means the values don't need any updating (they are equal enough).
                        switch (property)
                        {
                        case SyncableProperties.Type.AvatarAppearance:
                            String stringValue     = OSDParser.SerializeJsonString((OSDMap)value);
                            String lastStringValue = OSDParser.SerializeJsonString((OSDMap)syncedProperty.LastUpdateValue);
                            if (stringValue == lastStringValue)
                            {
                                return(false);
                            }
                            break;

                        case SyncableProperties.Type.Animations:
                            if (syncedProperty.LastUpdateValue != null)
                            {
                                AnimationSet lastAnimations = new AnimationSet((OSDArray)syncedProperty.LastUpdateValue);

                                // Get the home region for this presence (the client manager the presence is connected to).
                                string cachedRealRegionName = (string)(CurrentlySyncedProperties[SyncableProperties.Type.RealRegion].LastUpdateValue);
                                if (cachedRealRegionName != Scene.Name && sp.Animator.Animations.ToArray().Length == 0)
                                {
                                    // If this is not the originating region for this presence and there is no additional
                                    //   animations being added, this simulator does not change the animation.
                                    // THIS IS A HORRIBLE KLUDGE. FIGURE OUT THE REAL SOLUTION!!
                                    // The problem is that animations are changed by every simulator (setting default
                                    //   sit and stand when parentID changes) and the updates conflict/override the real
                                    //   settings (like a scripted sit animation).
                                    // DebugLog.DebugFormat("{0} CompareValue_UpdateByLocal. Not home sim or no anim change. spID={1}, homeSim={2}, thisSim={3}, anims={4}",
                                    //                     LogHeader, sp.LocalId, cachedRealRegionName, Scene.Name, sp.Animator.Animations.ToArray().Length); // DEBUG DEBUG

                                    return(false);
                                }

                                if (lastAnimations.Equals(sp.Animator.Animations))
                                {
                                    // DebugLog.DebugFormat("{0} CompareValue_UpdateByLocal. Equal anims. spID={1}, sp.Anim={2}, lastAnim={3}",
                                    //                     LogHeader, sp.LocalId, sp.Animator.Animations, lastAnimations); // DEBUG DEBUG
                                    return(false);
                                }
                                else
                                {
                                    // If locally storing a new value of the animation, don't check for the time.
                                    // DebugLog.DebugFormat("{0} CompareValue_UpdateByLocal. Not equal anims. spID={1}, sp.Anim={2}, lastAnim={3}",
                                    //                     LogHeader, sp.LocalId, sp.Animator.Animations, lastAnimations); // DEBUG DEBUG
                                    syncedProperty.UpdateSyncInfoByLocal(lastUpdateByLocalTS, syncID, value);
                                    return(true);
                                }
                            }
                            break;

                        case SyncableProperties.Type.Velocity:
                        case SyncableProperties.Type.PA_Velocity:
                        case SyncableProperties.Type.PA_TargetVelocity:
                        case SyncableProperties.Type.RotationalVelocity:
                        case SyncableProperties.Type.AngularVelocity:
                        {
                            Vector3 partVal = (Vector3)value;
                            Vector3 lastVal = (Vector3)syncedProperty.LastUpdateValue;
                            // If velocity difference is small but not zero, don't update
                            if (partVal.ApproxEquals(lastVal, VELOCITY_TOLERANCE) && !partVal.Equals(Vector3.Zero))
                            {
                                return(false);
                            }
                            break;
                        }

                        case SyncableProperties.Type.RotationOffset:
                        case SyncableProperties.Type.Orientation:
                        {
                            Quaternion partVal = (Quaternion)value;
                            Quaternion lastVal = (Quaternion)syncedProperty.LastUpdateValue;
                            if (partVal.ApproxEquals(lastVal, ROTATION_TOLERANCE))
                            {
                                return(false);
                            }
                            break;
                        }

                        case SyncableProperties.Type.OffsetPosition:
                        case SyncableProperties.Type.AbsolutePosition:
                        case SyncableProperties.Type.Position:
                        case SyncableProperties.Type.GroupPosition:
                        {
                            Vector3 partVal = (Vector3)value;
                            Vector3 lastVal = (Vector3)syncedProperty.LastUpdateValue;
                            if (partVal.ApproxEquals(lastVal, POSITION_TOLERANCE))
                            {
                                return(false);
                            }
                            break;
                        }
                        }
                    }

                    // If we get here, the values are not equal and we need to update the cached value if the
                    //     new value is timestamp newer.
                    if (lastUpdateByLocalTS >= syncedProperty.LastUpdateTimeStamp)
                    {
                        // DebugLog.DebugFormat("{0} CompareValue_UpdateByLocal (property={1}): TS >= lastTS (updating SyncInfo)", LogHeader, property);
                        syncedProperty.UpdateSyncInfoByLocal(lastUpdateByLocalTS, syncID, value);
                        return(true);
                    }
                }
                break;
            }
            return(false);
        }