From 4a73cc81dc4e03b2b7c46829cecfc0627c3fddb4 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 28 Dec 2018 13:52:59 +0000 Subject: [PATCH] now break several things at same time... sog/sop updates, threads options,... --- OpenSim/Framework/IClientAPI.cs | 18 +- OpenSim/Framework/Monitoring/WorkManager.cs | 68 +-- .../Linden/Caps/ServerReleaseNotesModule.cs | 2 - .../Linden/Caps/SimulatorFeaturesModule.cs | 5 + .../ClientStack/Linden/UDP/LLClientView.cs | 84 +++- .../ClientStack/Linden/UDP/LLUDPServer.cs | 14 - .../Scripting/XMLRPC/XMLRPCModule.cs | 12 +- .../World/Archiver/ArchiveWriteRequest.cs | 1 + .../World/Archiver/AssetsRequest.cs | 3 +- OpenSim/Region/Framework/Scenes/Scene.cs | 26 +- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 126 +++-- .../Framework/Scenes/SceneObjectGroup.cs | 27 +- .../Framework/Scenes/SceneObjectPart.cs | 452 +++++++++++------- .../Region/Framework/Scenes/ScenePresence.cs | 145 ++---- .../Server/IRCClientView.cs | 3 +- .../Server/IRCServer.cs | 2 +- .../Avatar/Chat/IRCConnector.cs | 2 +- .../OptionalModules/World/NPC/NPCAvatar.cs | 1 + .../BasicPhysics/BasicPhysicsScene.cs | 10 - .../Region/PhysicsModules/BulletS/BSScene.cs | 12 +- OpenSim/Region/PhysicsModules/Ode/OdeScene.cs | 10 - OpenSim/Region/PhysicsModules/POS/POSScene.cs | 10 - .../SharedBase/NullPhysicsScene.cs | 10 - .../Services/GridService/HypergridLinker.cs | 3 +- OpenSim/Tests/Common/Mock/TestClient.cs | 1 + 25 files changed, 548 insertions(+), 499 deletions(-) diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 1c042c451d..961750534f 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -683,9 +683,16 @@ namespace OpenSim.Framework ExtraData = 1 << 20, Sound = 1 << 21, Joint = 1 << 22, - FullUpdate = 0x0fffffff, - SendInTransit = 0x20000000, - CancelKill = 0x4fffffff, // 1 << 30 + + TerseUpdate = Position | Rotation | Velocity | Acceleration | AngularVelocity, + FullUpdate = 0x00ffffff, + + Animations = 1 << 24, + + FullUpdatewithAnim = FullUpdate | Animations, + + SendInTransit = 0x20000000, // 1 << 29 + CancelKill = 0x41ffffff, // 1 << 30 Kill = 0x80000000 // 1 << 31 } @@ -736,9 +743,6 @@ namespace OpenSim.Framework List SelectedObjects { get; } - // [Obsolete("LLClientView Specific - Replace with ???")] - int NextAnimationSequenceNumber { get; } - /// /// Returns the full name of the agent/avatar represented by this client /// @@ -765,6 +769,8 @@ namespace OpenSim.Framework bool SendLogoutPacketWhenClosing { set; } + int NextAnimationSequenceNumber {get; set;} + // [Obsolete("LLClientView Specific - Circuits are unique to LLClientView")] uint CircuitCode { get; } diff --git a/OpenSim/Framework/Monitoring/WorkManager.cs b/OpenSim/Framework/Monitoring/WorkManager.cs index 5d9b185f29..c6d97e1acb 100644 --- a/OpenSim/Framework/Monitoring/WorkManager.cs +++ b/OpenSim/Framework/Monitoring/WorkManager.cs @@ -88,6 +88,11 @@ namespace OpenSim.Framework.Monitoring Watchdog.Stop(); } + public static Thread StartThread(ThreadStart start, string name, bool alarmIfTimeout = false, bool log = true) + { + return StartThread(start, name, ThreadPriority.Normal, true, alarmIfTimeout, null, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS, log); + } + /// /// Start a new long-lived thread. /// @@ -99,9 +104,9 @@ namespace OpenSim.Framework.Monitoring /// If true then creation of thread is logged. /// The newly created Thread object public static Thread StartThread( - ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout, bool log = true) + ThreadStart start, string name, ThreadPriority priority, bool alarmIfTimeout, bool log = true) { - return StartThread(start, name, priority, isBackground, alarmIfTimeout, null, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS, log); + return StartThread(start, name, priority, true, alarmIfTimeout, null, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS, log); } /// @@ -162,15 +167,22 @@ namespace OpenSim.Framework.Monitoring { Culture.SetCurrentCulture(); callback(obj); - Watchdog.RemoveThread(log:false); } catch (Exception e) { m_log.Error(string.Format("[WATCHDOG]: Exception in thread {0}.", name), e); } + finally + { + try + { + Watchdog.RemoveThread(log: false); + } + catch { } + } }); - StartThread(ts, name, ThreadPriority.Normal, true, false, log:log); + StartThread(ts, name, false, log:log); } /// @@ -187,54 +199,6 @@ namespace OpenSim.Framework.Monitoring Util.FireAndForget(callback, obj, name, timeout); } - /// - /// Run a job. - /// - /// - /// This differs from direct scheduling (e.g. Util.FireAndForget) in that a job can be run in the job - /// engine if it is running, where all jobs are currently performed in sequence on a single thread. This is - /// to prevent observed overload and server freeze problems when there are hundreds of connections which all attempt to - /// perform work at once (e.g. in conference situations). With lower numbers of connections, the small - /// delay in performing jobs in sequence rather than concurrently has not been notiecable in testing, though a future more - /// sophisticated implementation could perform jobs concurrently when the server is under low load. - /// - /// However, be advised that some callers of this function rely on all jobs being performed in sequence if any - /// jobs are performed in sequence (i.e. if jobengine is active or not). Therefore, expanding the jobengine - /// beyond a single thread will require considerable thought. - /// - /// Also, any jobs submitted must be guaranteed to complete within a reasonable timeframe (e.g. they cannot - /// incorporate a network delay with a long timeout). At the moment, work that could suffer such issues - /// should still be run directly with RunInThread(), Util.FireAndForget(), etc. This is another area where - /// the job engine could be improved and so CPU utilization improved by better management of concurrency within - /// OpenSimulator. - /// - /// General classification for the job (e.g. "RezAttachments"). - /// Callback for job. - /// Object to pass to callback when run - /// Specific name of job (e.g. "RezAttachments for Joe Bloggs" - /// If set to true then the job may be run in ths calling thread. - /// If the true then the job must never timeout. - /// If set to true then extra logging is performed. - public static void RunJob( - string jobType, WaitCallback callback, object obj, string name, - bool canRunInThisThread = false, bool mustNotTimeout = false, - bool log = false) - { - if (Util.FireAndForgetMethod == FireAndForgetMethod.RegressionTest) - { - Culture.SetCurrentCulture(); - callback(obj); - return; - } - - if (JobEngine.IsRunning) - JobEngine.QueueJob(name, () => callback(obj)); - else if (canRunInThisThread) - callback(obj); - else - Util.FireAndForget(callback, obj, name, !mustNotTimeout); - } - private static void HandleControlCommand(string module, string[] args) { // if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ServerReleaseNotesModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/ServerReleaseNotesModule.cs index e172db7461..cf799823bf 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/ServerReleaseNotesModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/ServerReleaseNotesModule.cs @@ -126,8 +126,6 @@ namespace OpenSim.Region.ClientStack.LindenCaps Hashtable responsedata = new Hashtable(); responsedata["int_response_code"] = 301; responsedata["str_redirect_location"] = m_ServerReleaseNotesURL; - responsedata["content_type"] = "text/plain"; - return responsedata; } } diff --git a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs index b06e93c0b1..b52f2fd9ae 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs @@ -172,6 +172,11 @@ namespace OpenSim.Region.ClientStack.Linden if(m_doScriptSyntax && m_scriptSyntaxID != UUID.Zero) m_features["LSLSyntaxId"] = OSD.FromUUID(m_scriptSyntaxID); + OSDMap meshAnim = new OSDMap(); + meshAnim["AnimatedObjectMaxTris"] = OSD.FromInteger(10000); + meshAnim["MaxAgentAnimatedObjectAttachments"] = OSD.FromInteger(2); + m_features["AnimatedObjects"] = meshAnim; + // Extra information for viewers that want to use it // TODO: Take these out of here into their respective modules, like map-server-url OSDMap extrasMap; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index c42446c8c7..882f22f84f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -454,9 +454,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP public string Name { get { return FirstName + " " + LastName; } } public uint CircuitCode { get { return m_circuitCode; } } + + protected int m_animationSequenceNumber = (int)(Util.GetTimeStampTicks() & 0x5fffafL); public int NextAnimationSequenceNumber { - get { return m_udpServer.NextAnimationSequenceNumber; } + get + { + int ret = Interlocked.Increment(ref m_animationSequenceNumber); + if (ret <= 0) + { + m_animationSequenceNumber = (int)(Util.GetTimeStampTicks() & 0xafff5fL); + ret = Interlocked.Increment(ref m_animationSequenceNumber); + } + return ret; + } + set + { + m_animationSequenceNumber = value; + } } /// @@ -3904,6 +3919,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(ani, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); } + public void SendObjectAnimations(UUID[] animations, int[] seqs, UUID senderId) + { + // m_log.DebugFormat("[LLCLIENTVIEW]: Sending Object animations for {0} to {1}", sourceAgentId, Name); + + ObjectAnimationPacket ani = (ObjectAnimationPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAnimation); + // TODO: don't create new blocks if recycling an old packet + ani.Sender = new ObjectAnimationPacket.SenderBlock(); + ani.Sender.ID = senderId; + ani.AnimationList = new ObjectAnimationPacket.AnimationListBlock[animations.Length]; + + for (int i = 0; i < animations.Length; ++i) + { + ani.AnimationList[i] = new ObjectAnimationPacket.AnimationListBlock(); + ani.AnimationList[i].AnimID = animations[i]; + ani.AnimationList[i].AnimSequenceID = seqs[i]; + } + OutPacket(ani, ThrottleOutPacketType.Task); + } + #endregion #region Avatar Packet/Data Sending Methods @@ -4127,6 +4161,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP OpenSim.Framework.Lazy> compressedUpdates = new OpenSim.Framework.Lazy>(); OpenSim.Framework.Lazy> terseUpdates = new OpenSim.Framework.Lazy>(); OpenSim.Framework.Lazy> terseAgentUpdates = new OpenSim.Framework.Lazy>(); + OpenSim.Framework.Lazy> ObjectAnimationUpdates = new OpenSim.Framework.Lazy>(); // Check to see if this is a flush if (maxUpdatesBytes <= 0) @@ -4297,12 +4332,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP bool canUseCompressed = true; bool canUseImproved = true; - // Compressed object updates only make sense for LL primitives if (!(update.Entity is SceneObjectPart)) { canUseCompressed = false; } + else + { + if(updateFlags.HasFlag(PrimUpdateFlags.Animations)) + { + updateFlags &= ~PrimUpdateFlags.Animations; + SceneObjectPart sop = (SceneObjectPart)update.Entity; + if(sop.Animations != null) + { + ObjectAnimationUpdates.Value.Add(sop); + maxUpdatesBytes -= 32 * sop.Animations.Count + 16; + } + } + } if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) { @@ -4443,6 +4490,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); } + foreach (SceneObjectPart sop in ObjectAnimationUpdates.Value) + { + if (sop.Animations == null) + continue; + SceneObjectGroup sog = sop.ParentGroup; + if (sog == null || sog.IsDeleted) + continue; + + SceneObjectPart root = sog.RootPart; + if (root == null || root.Shape == null || !root.Shape.MeshFlagEntry) + continue; + + UUID[] ids = null; + int[] seqs = null; + int count = sop.GetAnimations(out ids, out seqs); + if(count < 0) + continue; + + ObjectAnimationPacket ani = (ObjectAnimationPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAnimation); + ani.Sender = new ObjectAnimationPacket.SenderBlock(); + ani.Sender.ID = sop.UUID; + ani.AnimationList = new ObjectAnimationPacket.AnimationListBlock[sop.Animations.Count]; + + for(int i = 0; i< count; i++) + { + ani.AnimationList[i] = new ObjectAnimationPacket.AnimationListBlock(); + ani.AnimationList[i].AnimID = ids[i]; + ani.AnimationList[i].AnimSequenceID = seqs[i]; + } + OutPacket(ani, ThrottleOutPacketType.Task); + } + #endregion Packet Sending #region Handle deleted objects @@ -4462,6 +4541,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP GroupsInView.Add(grp); } } + #endregion } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 567bbb5cde..70cca5117e 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -341,19 +341,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Flag to signal when clients should send pings protected bool m_sendPing; - protected int m_animationSequenceNumber; - - public int NextAnimationSequenceNumber - { - get - { - m_animationSequenceNumber++; - if (m_animationSequenceNumber > 2147482624) - m_animationSequenceNumber = 1; - return m_animationSequenceNumber; - } - } - protected ExpiringCache> m_pendingCache = new ExpiringCache>(); protected Pool m_incomingPacketPool; @@ -507,7 +494,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP ThrottleRates = new ThrottleRates(configSource); Random rnd = new Random(Util.EnvironmentTickCount()); - m_animationSequenceNumber = rnd.Next(11474826); // if (usePools) // EnablePools(); diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs index 6028eefd37..c9e3698401 100644 --- a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs @@ -658,7 +658,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC public void Process() { _finished = false; - httpThread = WorkManager.StartThread(SendRequest, "XMLRPCreqThread", ThreadPriority.BelowNormal, true, false, null, int.MaxValue); + httpThread = WorkManager.StartThread(SendRequest, "XMLRPCreqThread", ThreadPriority.Normal, true, false, null, int.MaxValue); } /* @@ -728,10 +728,12 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC m_log.Warn("[SendRemoteDataRequest]: Request failed"); m_log.Warn(we.StackTrace); } - - _finished = true; - - Watchdog.RemoveThread(); + finally + { + _finished = true; + httpThread = null; + Watchdog.RemoveThread(); + } } public void Stop() diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs index fe74cf1a88..060e753c70 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs @@ -290,6 +290,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver assetGatherer.GatherAll(); GC.Collect(); + int errors = assetGatherer.FailedUUIDs.Count; m_log.DebugFormat( "[ARCHIVER]: {0} region scene objects to save reference {1} possible assets", diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index 6e810253c0..9a0f16b0b1 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs @@ -137,6 +137,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver foreach (KeyValuePair kvp in m_uuids) { + string thiskey = kvp.Key.ToString(); try { @@ -162,7 +163,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_foundAssetUuids.Add(asset.FullID); m_assetsArchiver.WriteAsset(PostProcess(asset)); - if(++gccontrol > 5000) + if(++gccontrol > 10000) { gccontrol = 0; GC.Collect(); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 502bbda4dd..e5aa21e953 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -62,9 +62,23 @@ namespace OpenSim.Region.Framework.Scenes private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L; private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L; - public delegate void SynchronizeSceneHandler(Scene scene); + protected static int m_animationSequenceNumber = (int)(Util.GetTimeStampTicks() & 0x5fffafL); + + public int NextObjectAnimationSequenceNumber + { + get + { + int ret = Interlocked.Increment(ref m_animationSequenceNumber); + if (ret <= 0 ) + { + m_animationSequenceNumber = (int)(Util.GetTimeStampTicks() & 0xafff5fL); + ret = Interlocked.Increment(ref m_animationSequenceNumber); + } + return ret; + } + } #region Fields /// @@ -945,6 +959,7 @@ namespace OpenSim.Region.Framework.Scenes PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); + m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); if (RegionInfo.NonphysPrimMin > 0) { @@ -1547,10 +1562,9 @@ namespace OpenSim.Region.Framework.Scenes // tell physics to finish building actor m_sceneGraph.ProcessPhysicsPreSimulation(); - m_heartbeatThread - = WorkManager.StartThread( - Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false); - + m_heartbeatThread = WorkManager.StartThread( + Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, + false, null, 20000, false); StartScripts(); } @@ -1943,7 +1957,7 @@ namespace OpenSim.Region.Framework.Scenes { if (!m_backingup) { - WorkManager.RunInThreadPool(o => Backup(false), null, string.Format("BackupWorker ({0}", Name), false); + WorkManager.RunInThreadPool(o => Backup(false), null, string.Format("BackupWorker ({0})", Name), false); } } diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 61a243dd20..68864cc683 100755 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -28,6 +28,7 @@ using System; using System.Threading; using System.Collections.Generic; +using System.Collections.Concurrent; using System.Reflection; using OpenMetaverse; using OpenMetaverse.Packets; @@ -68,8 +69,10 @@ namespace OpenSim.Region.Framework.Scenes #region Fields - protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim(); - protected Dictionary m_scenePresenceMap = new Dictionary(); + protected System.Threading.ReaderWriterLockSlim m_scenePresencesLock = new System.Threading.ReaderWriterLockSlim(); + + protected ConcurrentDictionary m_scenePresenceMap = new ConcurrentDictionary(); + protected ConcurrentDictionary m_scenePresenceLocalIDMap = new ConcurrentDictionary(); protected List m_scenePresenceArray = new List(); protected internal EntityManager Entities = new EntityManager(); @@ -147,10 +150,9 @@ namespace OpenSim.Region.Framework.Scenes m_scenePresencesLock.EnterWriteLock(); try { - Dictionary newmap = new Dictionary(); - List newlist = new List(); - m_scenePresenceMap = newmap; - m_scenePresenceArray = newlist; + m_scenePresenceMap = new ConcurrentDictionary(); + m_scenePresenceLocalIDMap = new ConcurrentDictionary(); + m_scenePresenceArray = new List(); } finally { @@ -165,22 +167,13 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroupsByLocalPartID.Clear(); Entities.Clear(); + m_scenePresencesLock.Dispose(); } #region Update Methods protected internal void UpdatePreparePhysics() { - // If we are using a threaded physics engine - // grab the latest scene from the engine before - // trying to process it. - - // PhysX does this (runs in the background). - - if (PhysicsScene.IsThreaded) - { - PhysicsScene.GetResults(); - } } /// @@ -197,6 +190,14 @@ namespace OpenSim.Region.Framework.Scenes }); } + protected internal void UpdateScenePresenceMovement() + { + ForEachScenePresence(delegate (ScenePresence presence) + { + presence.UpdateMovement(); + }); + } + /// /// Perform a physics frame update. /// @@ -204,23 +205,9 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal float UpdatePhysics(double elapsed) { - // Here is where the Scene calls the PhysicsScene. This is a one-way - // interaction; the PhysicsScene cannot access the calling Scene directly. - // But with joints, we want a PhysicsActor to be able to influence a - // non-physics SceneObjectPart. In particular, a PhysicsActor that is connected - // with a joint should be able to move the SceneObjectPart which is the visual - // representation of that joint (for editing and serialization purposes). - // However the PhysicsActor normally cannot directly influence anything outside - // of the PhysicsScene, and the non-physical SceneObjectPart which represents - // the joint in the Scene does not exist in the PhysicsScene. - // - // To solve this, we have an event in the PhysicsScene that is fired when a joint - // has changed position (because one of its associated PhysicsActors has changed - // position). - // - // Therefore, JointMoved and JointDeactivated events will be fired as a result of the following Simulate(). - - return PhysicsScene.Simulate((float)elapsed); + if (PhysicsScene != null) + return PhysicsScene.Simulate((float)elapsed); + return 0; } protected internal void ProcessPhysicsPreSimulation() @@ -229,14 +216,6 @@ namespace OpenSim.Region.Framework.Scenes PhysicsScene.ProcessPreSimulation(); } - protected internal void UpdateScenePresenceMovement() - { - ForEachScenePresence(delegate(ScenePresence presence) - { - presence.UpdateMovement(); - }); - } - public void GetCoarseLocations(out List coarseLocations, out List avatarUUIDs, uint maxLocations) { coarseLocations = new List(); @@ -640,7 +619,7 @@ namespace OpenSim.Region.Framework.Scenes lock (m_updateList) { updates = new List(m_updateList.Values); - m_updateList.Clear(); + m_updateList = new Dictionary(); } // Go through all updates @@ -720,26 +699,32 @@ namespace OpenSim.Region.Framework.Scenes { m_numChildAgents++; - Dictionary newmap = new Dictionary(m_scenePresenceMap); List newlist = new List(m_scenePresenceArray); - if (!newmap.ContainsKey(presence.UUID)) + if (!m_scenePresenceMap.ContainsKey(presence.UUID)) { - newmap.Add(presence.UUID, presence); + m_scenePresenceMap[presence.UUID] = presence; + m_scenePresenceLocalIDMap[presence.LocalId] = presence; newlist.Add(presence); } else { // Remember the old presence reference from the dictionary - ScenePresence oldref = newmap[presence.UUID]; + ScenePresence oldref = m_scenePresenceMap[presence.UUID]; + uint oldLocalID = oldref.LocalId; // Replace the presence reference in the dictionary with the new value - newmap[presence.UUID] = presence; - // Find the index in the list where the old ref was stored and update the reference + m_scenePresenceMap[presence.UUID] = presence; newlist[newlist.IndexOf(oldref)] = presence; + + if(presence.LocalId != oldLocalID) + { + m_scenePresenceLocalIDMap.TryRemove(oldLocalID, out oldref); + m_scenePresenceLocalIDMap[presence.LocalId] = presence; + } + // Find the index in the list where the old ref was stored and update the reference } // Swap out the dictionary and list with new references - m_scenePresenceMap = newmap; m_scenePresenceArray = newlist; } finally @@ -765,20 +750,15 @@ namespace OpenSim.Region.Framework.Scenes m_scenePresencesLock.EnterWriteLock(); try { - Dictionary newmap = new Dictionary(m_scenePresenceMap); - List newlist = new List(m_scenePresenceArray); - // Remove the presence reference from the dictionary - if (newmap.ContainsKey(agentID)) + ScenePresence oldref; + if(m_scenePresenceMap.TryRemove(agentID, out oldref)) { - ScenePresence oldref = newmap[agentID]; - newmap.Remove(agentID); - // Find the index in the list where the old ref was stored and remove the reference - newlist.RemoveAt(newlist.IndexOf(oldref)); - // Swap out the dictionary and list with new references - m_scenePresenceMap = newmap; - m_scenePresenceArray = newlist; + List newsps = new List(m_scenePresenceArray); + newsps.RemoveAt(newsps.IndexOf(oldref)); + m_scenePresenceArray = newsps; + m_scenePresenceLocalIDMap.TryRemove(oldref.LocalId, out oldref); } else { @@ -914,7 +894,16 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal List GetScenePresences() { - return m_scenePresenceArray; + + m_scenePresencesLock.EnterReadLock(); + try + { + return m_scenePresenceArray; + } + finally + { + m_scenePresencesLock.ExitReadLock(); + } } /// @@ -924,9 +913,8 @@ namespace OpenSim.Region.Framework.Scenes /// null if the presence was not found protected internal ScenePresence GetScenePresence(UUID agentID) { - Dictionary presences = m_scenePresenceMap; ScenePresence presence; - presences.TryGetValue(agentID, out presence); + m_scenePresenceMap.TryGetValue(agentID, out presence); return presence; } @@ -955,24 +943,28 @@ namespace OpenSim.Region.Framework.Scenes /// null if the presence was not found protected internal ScenePresence GetScenePresence(uint localID) { + ScenePresence sp = null; + if(m_scenePresenceLocalIDMap.TryGetValue(localID, out sp)) + return sp; +/* List presences = GetScenePresences(); foreach (ScenePresence presence in presences) if (presence.LocalId == localID) return presence; +*/ return null; } protected internal bool TryGetScenePresence(UUID agentID, out ScenePresence avatar) { - Dictionary presences = m_scenePresenceMap; - presences.TryGetValue(agentID, out avatar); - return (avatar != null); + return m_scenePresenceMap.TryGetValue(agentID, out avatar); } protected internal bool TryGetAvatarByName(string name, out ScenePresence avatar) { avatar = null; - foreach (ScenePresence presence in GetScenePresences()) + List presences = GetScenePresences(); + foreach (ScenePresence presence in presences) { if (String.Compare(name, presence.ControllingClient.Name, true) == 0) { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 423fbc70ed..a78ed8b779 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2584,14 +2584,33 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendFullUpdateToClient(IClientAPI remoteClient) { - RootPart.SendFullUpdate(remoteClient); + PrimUpdateFlags update = PrimUpdateFlags.FullUpdate; + + RootPart.SendFullUpdate(remoteClient, update); SceneObjectPart[] parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) { SceneObjectPart part = parts[i]; if (part != RootPart) - part.SendFullUpdate(remoteClient); + part.SendFullUpdate(remoteClient, update); + } + } + + public void SendFullAnimUpdateToClient(IClientAPI remoteClient) + { + PrimUpdateFlags update = PrimUpdateFlags.FullUpdate; + if (RootPart.Shape.MeshFlagEntry) + update = PrimUpdateFlags.FullUpdatewithAnim; + + RootPart.SendFullUpdate(remoteClient, update); + + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + { + SceneObjectPart part = parts[i]; + if (part != RootPart) + part.SendFullUpdate(remoteClient, update); } } @@ -3110,7 +3129,7 @@ namespace OpenSim.Region.Framework.Scenes ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar); if (sp != null) { - sp.SendAttachmentUpdate(this,UpdateRequired.FULL); + sp.SendAttachmentUpdate(this, PrimUpdateFlags.FullUpdate); return; } } @@ -3160,7 +3179,7 @@ namespace OpenSim.Region.Framework.Scenes ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar); if (sp != null) { - sp.SendAttachmentUpdate(this, UpdateRequired.TERSE); + sp.SendAttachmentUpdate(this, PrimUpdateFlags.TerseUpdate); return; } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 6c035f048e..c549f5c6a0 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -68,22 +68,6 @@ namespace OpenSim.Region.Framework.Scenes POSITION = 32768 } - // I don't really know where to put this except here. - // Can't access the OpenSim.Region.ScriptEngine.Common.LSL_BaseClass.Changed constants - [Flags] - public enum ExtraParamType - { - Something1 = 1, - Something2 = 2, - Something3 = 4, - Something4 = 8, - Flexible = 16, - Light = 32, - Sculpt = 48, - Something5 = 64, - Something6 = 128 - } - [Flags] public enum TextureAnimFlags : byte { @@ -109,13 +93,6 @@ namespace OpenSim.Region.Framework.Scenes SCULPT = 7 } - public enum UpdateRequired : byte - { - NONE = 0, - TERSE = 1, - FULL = 2 - } - #endregion Enumerations public class SceneObjectPart : ISceneEntity @@ -182,10 +159,13 @@ namespace OpenSim.Region.Framework.Scenes { get { - return - !(SitTargetPosition == Vector3.Zero - && (SitTargetOrientation == Quaternion.Identity // Valid Zero Rotation quaternion - || (SitTargetOrientation.W == 0f && SitTargetOrientation.X == 0f && SitTargetOrientation.Y == 0f && SitTargetOrientation.Z == 0f ))); // Invalid Quaternion + // assume SitTargetOrientation is normalized (as needed elsewhere) + if( SitTargetPosition != Vector3.Zero || + SitTargetOrientation.X != 0f || + SitTargetOrientation.Y != 0f || + SitTargetOrientation.Z != 0f) + return true; + return false; } } @@ -1212,7 +1192,18 @@ namespace OpenSim.Region.Framework.Scenes return a * b; } - public UpdateRequired UpdateFlag { get; set; } + public PrimUpdateFlags UpdateFlag { get; set; } + + public PrimUpdateFlags GetAndClearUpdateFlag() + { + lock(UpdateFlagLock) + { + PrimUpdateFlags ret = UpdateFlag; + UpdateFlag = PrimUpdateFlags.None; + return ret; + } + } + private object UpdateFlagLock = new object(); /// @@ -1503,11 +1494,16 @@ namespace OpenSim.Region.Framework.Scenes } set { + UUID old = m_collisionSound; + m_collisionSoundType = value; if (value == -1) m_collisionSound = invalidCollisionSoundUUID; else if (value == 0) m_collisionSound = UUID.Zero; + + if(m_collisionSound != old && ParentGroup != null) + ParentGroup.HasGroupChanged = true; } } @@ -1516,6 +1512,7 @@ namespace OpenSim.Region.Framework.Scenes get { return m_collisionSound; } set { + UUID olds = m_collisionSound; m_collisionSound = value; if (value == invalidCollisionSoundUUID) @@ -1525,13 +1522,24 @@ namespace OpenSim.Region.Framework.Scenes else m_collisionSoundType = 1; + if(m_collisionSound != olds && ParentGroup != null) + ParentGroup.HasGroupChanged = true; } } public float CollisionSoundVolume { get { return m_collisionSoundVolume; } - set { m_collisionSoundVolume = value; } + set + { + float oldvalue = m_collisionSoundVolume; + if(value >= 0) + m_collisionSoundVolume = value; + else + m_collisionSoundVolume = 0.0f; + if(m_collisionSoundVolume != oldvalue && ParentGroup != null) + ParentGroup.HasGroupChanged = true; + } } public float Buoyancy @@ -1884,7 +1892,7 @@ namespace OpenSim.Region.Framework.Scenes public void ClearUpdateSchedule() { lock(UpdateFlagLock) - UpdateFlag = UpdateRequired.NONE; + UpdateFlag = PrimUpdateFlags.None; } /// @@ -3276,40 +3284,27 @@ namespace OpenSim.Region.Framework.Scenes { // m_log.DebugFormat("[SCENE OBJECT PART]: Scheduling full update for {0} {1}", Name, LocalId); - if (ParentGroup == null) + if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.Scene == null) return; - if (ParentGroup.Scene == null) - return; - + if(ParentGroup.Scene.GetNumberOfClients() == 0) return; ParentGroup.QueueForUpdateCheck(); // just in case lock(UpdateFlagLock) - { - if(UpdateFlag != UpdateRequired.FULL) - { - UpdateFlag = UpdateRequired.FULL; + UpdateFlag |= PrimUpdateFlags.FullUpdate; - // m_log.DebugFormat( - // "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}", - // UUID, Name, TimeStampFull); - - } - } ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true); } /// /// Schedule a terse update for this prim. Terse updates only send position, - /// rotation, velocity and rotational velocity information. WRONG!!!! + /// rotation, velocity and rotational velocity information. /// public void ScheduleTerseUpdate() { - if (ParentGroup == null) - return; - if (ParentGroup.Scene == null) + if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.Scene == null) return; ParentGroup.HasGroupChanged = true; @@ -3317,28 +3312,47 @@ namespace OpenSim.Region.Framework.Scenes if(ParentGroup.Scene.GetNumberOfClients() == 0) return; - // This was pulled from SceneViewer. Attachments always receive full updates. - // This is needed because otherwise if only the root prim changes position, then - // it looks as if the entire object has moved (including the other prims). - if (ParentGroup.IsAttachment) + ParentGroup.QueueForUpdateCheck(); + + bool isfull = false; + lock (UpdateFlagLock) { - ScheduleFullUpdate(); - return; + if (ParentGroup.IsAttachment) + { + UpdateFlag |= PrimUpdateFlags.FullUpdate; + isfull = true; + } + else + UpdateFlag |= PrimUpdateFlags.TerseUpdate; } + ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, isfull); + } + + public void ScheduleUpdate(PrimUpdateFlags update) + { + if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.Scene == null) + return; + + ParentGroup.HasGroupChanged = true; + + if (ParentGroup.Scene.GetNumberOfClients() == 0) + return; ParentGroup.QueueForUpdateCheck(); - lock(UpdateFlagLock) - { - if (UpdateFlag == UpdateRequired.NONE) - { - UpdateFlag = UpdateRequired.TERSE; - // m_log.DebugFormat( - // "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1}", - // UUID, Name); + bool isfull = false; + lock (UpdateFlagLock) + { + if (ParentGroup.IsAttachment) + { + UpdateFlag |= update | PrimUpdateFlags.FullUpdate; + isfull = true; } + else + UpdateFlag |= update; } - ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false); + + ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, isfull); } public void ScriptSetPhysicsStatus(bool UsePhysics) @@ -3364,7 +3378,7 @@ namespace OpenSim.Region.Framework.Scenes ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar); if (sp != null) { - sp.SendAttachmentUpdate(this, UpdateRequired.FULL); + sp.SendAttachmentUpdate(this, PrimUpdateFlags.FullUpdate); } } else @@ -3373,6 +3387,29 @@ namespace OpenSim.Region.Framework.Scenes } } + protected internal void SendFullUpdate(IClientAPI remoteClient, PrimUpdateFlags update) + { + if (ParentGroup == null) + return; + + // m_log.DebugFormat( + // "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); + + + if (ParentGroup.IsAttachment) + { + ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar); + if (sp != null) + { + sp.SendAttachmentUpdate(this, update); + } + } + else + { + SendUpdateToClient(remoteClient, update); + } + } + /// /// Send a full update for this part to all clients. /// @@ -3419,7 +3456,7 @@ namespace OpenSim.Region.Framework.Scenes ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar); if (sp != null) { - sp.SendAttachmentUpdate(this, UpdateRequired.FULL); + sp.SendAttachmentUpdate(this, PrimUpdateFlags.FullUpdate); } } else @@ -3469,136 +3506,109 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendScheduledUpdates(double now) { - bool sendterse = false; - bool sendfull = false; - - lock(UpdateFlagLock) + PrimUpdateFlags current; + lock (UpdateFlagLock) { - switch (UpdateFlag) + current = UpdateFlag; + + if (current == PrimUpdateFlags.None) + return; + + if(current == PrimUpdateFlags.TerseUpdate) { - case UpdateRequired.NONE: - break; + Vector3 curvel = Velocity; + Vector3 curacc = Acceleration; + Vector3 angvel = AngularVelocity; - case UpdateRequired.TERSE: - sendterse = true; + while(true) // just to avoid ugly goto + { + double elapsed = now - m_lastUpdateSentTime; + if (elapsed > TIME_MS_TOLERANCE) + break; - Vector3 curvel = Velocity; - Vector3 curacc = Acceleration; - Vector3 angvel = AngularVelocity; - - while(true) // just to avoid ugly goto - { - double elapsed = now - m_lastUpdateSentTime; - if (elapsed > TIME_MS_TOLERANCE) - break; - - if( Math.Abs(curacc.X - m_lastAcceleration.X) > VELOCITY_TOLERANCE || + if( Math.Abs(curacc.X - m_lastAcceleration.X) > VELOCITY_TOLERANCE || Math.Abs(curacc.Y - m_lastAcceleration.Y) > VELOCITY_TOLERANCE || Math.Abs(curacc.Z - m_lastAcceleration.Z) > VELOCITY_TOLERANCE) - break; - - if( Math.Abs(curvel.X - m_lastVelocity.X) > VELOCITY_TOLERANCE || + break; + + if( Math.Abs(curvel.X - m_lastVelocity.X) > VELOCITY_TOLERANCE || Math.Abs(curvel.Y - m_lastVelocity.Y) > VELOCITY_TOLERANCE || Math.Abs(curvel.Z - m_lastVelocity.Z) > VELOCITY_TOLERANCE) - break; - - float vx = Math.Abs(curvel.X); - if(vx > 128.0) - break; - float vy = Math.Abs(curvel.Y); - if(vy > 128.0) - break; - float vz = Math.Abs(curvel.Z); - if(vz > 128.0) - break; + break; - if ( + float vx = Math.Abs(curvel.X); + if(vx > 128.0) + break; + float vy = Math.Abs(curvel.Y); + if(vy > 128.0) + break; + float vz = Math.Abs(curvel.Z); + if(vz > 128.0) + break; + + if( vx < VELOCITY_TOLERANCE && vy < VELOCITY_TOLERANCE && vz < VELOCITY_TOLERANCE ) - { - if(!AbsolutePosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE)) - break; - - if (vx < 1e-4 && + { + if(!AbsolutePosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE)) + break; + if(vx < 1e-4 && vy < 1e-4 && vz < 1e-4 && ( - Math.Abs(m_lastVelocity.X) > 1e-4 || - Math.Abs(m_lastVelocity.Y) > 1e-4 || - Math.Abs(m_lastVelocity.Z) > 1e-4 + Math.Abs(m_lastVelocity.X) > 1e-4 || + Math.Abs(m_lastVelocity.Y) > 1e-4 || + Math.Abs(m_lastVelocity.Z) > 1e-4 )) - break; - } + break; + } - if( Math.Abs(angvel.X - m_lastAngularVelocity.X) > ANGVELOCITY_TOLERANCE || + if( Math.Abs(angvel.X - m_lastAngularVelocity.X) > ANGVELOCITY_TOLERANCE || Math.Abs(angvel.Y - m_lastAngularVelocity.Y) > ANGVELOCITY_TOLERANCE || Math.Abs(angvel.Z - m_lastAngularVelocity.Z) > ANGVELOCITY_TOLERANCE) - break; + break; - // viewer interpolators have a limit of 64rad/s - float ax = Math.Abs(angvel.X); - if(ax > 64.0) - break; - float ay = Math.Abs(angvel.Y); - if(ay > 64.0) - break; - float az = Math.Abs(angvel.Z); - if(az > 64.0) - break; + // viewer interpolators have a limit of 64rad/s + float ax = Math.Abs(angvel.X); + if(ax > 64.0) + break; + float ay = Math.Abs(angvel.Y); + if(ay > 64.0) + break; + float az = Math.Abs(angvel.Z); + if(az > 64.0) + break; - if ( + if ( ax < ANGVELOCITY_TOLERANCE && ay < ANGVELOCITY_TOLERANCE && az < ANGVELOCITY_TOLERANCE && !RotationOffset.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) ) - break; - - sendterse = false; break; - } - - if(sendterse) - { - // Update the "last" values - m_lastPosition = AbsolutePosition; - m_lastRotation = RotationOffset; - m_lastVelocity = curvel; - m_lastAcceleration = curacc; - m_lastAngularVelocity = angvel; - m_lastUpdateSentTime = now; - ClearUpdateSchedule(); - } - break; - - case UpdateRequired.FULL: - m_lastPosition = AbsolutePosition; - m_lastRotation = RotationOffset; - m_lastVelocity = Velocity; - m_lastAcceleration = Acceleration; - m_lastAngularVelocity = AngularVelocity; - m_lastUpdateSentTime = now; - ClearUpdateSchedule(); - sendfull = true; - break; + return; + } } - } - if(sendterse) - { - ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) + + if((current & PrimUpdateFlags.TerseUpdate) != 0) { - SendTerseUpdateToClient(client); - }); + m_lastPosition = AbsolutePosition; + m_lastRotation = RotationOffset; + m_lastVelocity = Velocity; + m_lastAcceleration = Acceleration; + m_lastAngularVelocity = AngularVelocity; + m_lastUpdateSentTime = now; + } + + UpdateFlag = PrimUpdateFlags.None; } - else if(sendfull) + + ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) { - ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) - { - SendFullUpdate(avatar.ControllingClient); - }); - } + SendUpdateToClient(avatar.ControllingClient, current); + }); } /// @@ -3608,10 +3618,10 @@ namespace OpenSim.Region.Framework.Scenes { if (ParentGroup == null || ParentGroup.Scene == null) return; + lock(UpdateFlagLock) { - if(UpdateFlag != UpdateRequired.NONE) - return; + UpdateFlag &= ~PrimUpdateFlags.TerseUpdate; // Update the "last" values m_lastPosition = AbsolutePosition; @@ -3635,8 +3645,7 @@ namespace OpenSim.Region.Framework.Scenes lock(UpdateFlagLock) { - if(UpdateFlag != UpdateRequired.NONE) - return; + UpdateFlag &= ~PrimUpdateFlags.TerseUpdate; // Update the "last" values m_lastPosition = AbsolutePosition; @@ -3652,7 +3661,7 @@ namespace OpenSim.Region.Framework.Scenes ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar); if (sp != null) { - sp.SendAttachmentUpdate(this, UpdateRequired.TERSE); + sp.SendAttachmentUpdate(this, PrimUpdateFlags.TerseUpdate); } } else @@ -3682,12 +3691,6 @@ namespace OpenSim.Region.Framework.Scenes public void SetBuoyancy(float fvalue) { Buoyancy = fvalue; -/* - if (PhysActor != null) - { - PhysActor.Buoyancy = fvalue; - } - */ } public void SetDieAtEdge(bool p) @@ -4085,7 +4088,8 @@ namespace OpenSim.Region.Framework.Scenes GroupID = groupID; // if (client != null) // SendPropertiesToClient(client); - UpdateFlag = UpdateRequired.FULL; + lock(UpdateFlagLock) + UpdateFlag |= PrimUpdateFlags.FullUpdate; } /// @@ -4273,8 +4277,6 @@ namespace OpenSim.Region.Framework.Scenes Vector3 pos = GetWorldPosition(); Quaternion rot = GetWorldRotation(); - // Variables prefixed with AX are Axiom.Math copies of the LL variety. - Quaternion AXrot = rot; AXrot.Normalize(); @@ -4645,7 +4647,7 @@ namespace OpenSim.Region.Framework.Scenes { if (ParentGroup.RootPart.GetStatusSandbox()) { - if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10) + if (Vector3.DistanceSquared(ParentGroup.RootPart.StatusSandboxPos, newPos) > 100) { ParentGroup.RootPart.ScriptSetPhysicsStatus(false); newPos = OffsetPosition; @@ -5230,7 +5232,7 @@ namespace OpenSim.Region.Framework.Scenes // Materials capable viewers can send a ObjectImage packet // when nothing in TE has changed. MaterialID should be updated // by the RenderMaterials CAP handler, so updating it here may cause a - // race condtion. Therefore, if no non-materials TE fields have changed, + // race condtion. Therefore, if no non-materials TE fields have not changed, // we should ignore any changes and not update Shape.TextureEntry bool otherFieldsChanged = false; @@ -5279,7 +5281,7 @@ namespace OpenSim.Region.Framework.Scenes } if (changeFlags == 0) - return; + return; m_shape.TextureEntry = newTex.GetBytes(); TriggerScriptChangedEvent(changeFlags); ParentGroup.HasGroupChanged = true; @@ -5412,6 +5414,21 @@ namespace OpenSim.Region.Framework.Scenes #endregion Public Methods + public void SendUpdateToClient(IClientAPI remoteClient, PrimUpdateFlags PrimUpdateFlags) + { + if (ParentGroup.IsDeleted) + return; + + if (ParentGroup.IsAttachment && + (ParentGroup.RootPart != this || ParentGroup.AttachedAvatar != remoteClient.AgentId && ParentGroup.HasPrivateAttachmentPoint)) + return; + + remoteClient.SendEntityUpdate(this, PrimUpdateFlags); + + ParentGroup.Scene.StatsReporter.AddObjectUpdates(1); + } + + public void SendTerseUpdateToClient(IClientAPI remoteClient) { if (ParentGroup.IsDeleted) @@ -5424,10 +5441,7 @@ namespace OpenSim.Region.Framework.Scenes // Causes this thread to dig into the Client Thread Data. // Remember your locking here! - remoteClient.SendEntityUpdate( - this, - PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity - | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); + remoteClient.SendEntityUpdate(this, PrimUpdateFlags.TerseUpdate); ParentGroup.Scene.StatsReporter.AddObjectUpdates(1); } @@ -5691,5 +5705,75 @@ namespace OpenSim.Region.Framework.Scenes PhysActor.Building = true; UpdatePrimFlags(wasUsingPhysics,wasTemporary,wasPhantom,makeVolumeDetect,false); } + + private object animsLock = new object(); + public Dictionary Animations = null; + public Dictionary AnimationsNames = null; + + public bool AddAnimation(UUID animId, string animName) + { + if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit) + return false; + + lock (animsLock) + { + if (Animations == null) + Animations = new Dictionary(1); + if (AnimationsNames == null) + AnimationsNames = new Dictionary(1); + + if (Animations.ContainsKey(animId)) + return false; + + Animations[animId] = ParentGroup.Scene.NextObjectAnimationSequenceNumber; + AnimationsNames[animId] = animName; + ScheduleUpdate(PrimUpdateFlags.Animations); + } + return true; + } + + public bool RemoveAnimation(UUID animId) + { + if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit) + return false; + + lock (animsLock) + { + if (Animations == null) + return false; + + if (Animations.ContainsKey(animId)) + { + Animations.Remove(animId); + if(AnimationsNames!=null) + AnimationsNames.Remove(animId); + ScheduleUpdate(PrimUpdateFlags.Animations); + return true; + } + } + return false; + } + + public int GetAnimations(out UUID[] ids, out int[] seqs) + { + ids = null; + seqs = null; + + if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit) + return -1; + + lock (animsLock) + { + if (Animations == null) + return -1; + if(Animations.Count == 0) + return 0; + ids = new UUID[Animations.Count]; + Animations.Keys.CopyTo(ids, 0); + seqs = new int[Animations.Count]; + Animations.Values.CopyTo(seqs, 0); + return Animations.Count; + } + } } } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 3312ace2cc..a308abb0cf 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2173,7 +2173,7 @@ namespace OpenSim.Region.Framework.Scenes // if(root.LocalId != ParentPart.LocalId) // ControllingClient.SendEntityTerseUpdateImmediate(root); // ControllingClient.SendEntityTerseUpdateImmediate(ParentPart); - ParentPart.ParentGroup.SendFullUpdateToClient(ControllingClient); + ParentPart.ParentGroup.SendFullAnimUpdateToClient(ControllingClient); } // verify baked textures and cache @@ -4036,7 +4036,7 @@ namespace OpenSim.Region.Framework.Scenes foreach (EntityBase e in entities) { if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment) - ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); + ((SceneObjectGroup)e).SendFullAnimUpdateToClient(ControllingClient); } m_reprioritizationLastPosition = AbsolutePosition; @@ -4883,18 +4883,31 @@ namespace OpenSim.Region.Framework.Scenes Animator.ResetAnimations(); Overrides.CopyAOPairsFrom(cAgent.MovementAnimationOverRides); - + int nanim = ControllingClient.NextAnimationSequenceNumber; // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? if (cAgent.DefaultAnim != null) + { + if (cAgent.DefaultAnim.SequenceNum > nanim) + nanim = cAgent.DefaultAnim.SequenceNum; Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); + } if (cAgent.AnimState != null) + { + if (cAgent.AnimState.SequenceNum > nanim) + nanim = cAgent.AnimState.SequenceNum; Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); + } if (cAgent.Anims != null) - Animator.Animations.FromArray(cAgent.Anims); + { + int canim = Animator.Animations.FromArray(cAgent.Anims); + if(canim > nanim) + nanim = canim; + } + ControllingClient.NextAnimationSequenceNumber = ++nanim; + if (cAgent.MotionState != 0) Animator.currentControlState = (ScenePresenceAnimator.motionControlStates) cAgent.MotionState; - crossingFlags = cAgent.CrossingFlags; gotCrossUpdate = (crossingFlags != 0); if(gotCrossUpdate) @@ -5401,14 +5414,18 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart[] parts = sog.Parts; SceneObjectPart rootpart = sog.RootPart; - p.ControllingClient.SendEntityUpdate(rootpart, PrimUpdateFlags.FullUpdate); + PrimUpdateFlags update = PrimUpdateFlags.FullUpdate; + if (rootpart.Shape.MeshFlagEntry) + update = PrimUpdateFlags.FullUpdatewithAnim; + + p.ControllingClient.SendEntityUpdate(rootpart, update); for (int i = 0; i < parts.Length; i++) { SceneObjectPart part = parts[i]; if (part == rootpart) continue; - p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate); + p.ControllingClient.SendEntityUpdate(part, update); } } @@ -5422,51 +5439,30 @@ namespace OpenSim.Region.Framework.Scenes PrimUpdateFlags[] flags = new PrimUpdateFlags[origparts.Length]; SceneObjectPart rootpart = sog.RootPart; - UpdateRequired rootreq = sog.RootPart.UpdateFlag; + PrimUpdateFlags rootreq = sog.RootPart.GetAndClearUpdateFlag(); int j = 0; - bool allterse = true; + + PrimUpdateFlags cur; for (int i = 0; i < origparts.Length; i++) { if (origparts[i] != rootpart) { - switch (origparts[i].UpdateFlag) - { - case UpdateRequired.NONE: - break; - - case UpdateRequired.TERSE: - flags[j] = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity - | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; - parts[j] = origparts[i]; - j++; - break; - - case UpdateRequired.FULL: - flags[j] = PrimUpdateFlags.FullUpdate; - allterse = false; - parts[j] = origparts[i]; - j++; - break; - } + cur = origparts[i].GetAndClearUpdateFlag(); + if(cur == PrimUpdateFlags.None) + continue; + flags[j] = cur; + parts[j] = origparts[i]; + j++; } - origparts[i].UpdateFlag = 0; } - if (j == 0 && rootreq == UpdateRequired.NONE) + if (j == 0 && rootreq == PrimUpdateFlags.None) return; - PrimUpdateFlags rootflag = PrimUpdateFlags.FullUpdate; - - if (rootreq != UpdateRequired.FULL && allterse) - { - rootflag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity - | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; - } - int nparts = j; - ControllingClient.SendEntityUpdate(rootpart, rootflag); + ControllingClient.SendEntityUpdate(rootpart, rootreq); for (int i = 0; i < nparts; i++) { @@ -5485,7 +5481,7 @@ namespace OpenSim.Region.Framework.Scenes if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) continue; - p.ControllingClient.SendEntityUpdate(rootpart, rootflag); + p.ControllingClient.SendEntityUpdate(rootpart, rootreq); for (int i = 0; i < nparts; i++) { @@ -5494,41 +5490,22 @@ namespace OpenSim.Region.Framework.Scenes } } - public void SendAttachmentUpdate(SceneObjectGroup sog, UpdateRequired UpdateFlag) + public void SendAttachmentUpdate(SceneObjectGroup sog, PrimUpdateFlags update) { if (IsChildAgent || IsInTransit) return; - PrimUpdateFlags flag; - switch (UpdateFlag) - { - case UpdateRequired.TERSE: - flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity - | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; - break; - - case UpdateRequired.FULL: - flag = PrimUpdateFlags.FullUpdate; - break; - - default: - return; - } - SceneObjectPart[] parts = sog.Parts; SceneObjectPart rootpart = sog.RootPart; -// rootpart.UpdateFlag = 0; - - ControllingClient.SendEntityUpdate(rootpart, flag); + ControllingClient.SendEntityUpdate(rootpart, update); for (int i = 0; i < parts.Length; i++) { SceneObjectPart part = parts[i]; if (part == rootpart) continue; - ControllingClient.SendEntityUpdate(part, flag); -// part.UpdateFlag = 0; + ControllingClient.SendEntityUpdate(part, update); } if (sog.HasPrivateAttachmentPoint) @@ -5543,14 +5520,14 @@ namespace OpenSim.Region.Framework.Scenes if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) continue; - p.ControllingClient.SendEntityUpdate(rootpart, flag); + p.ControllingClient.SendEntityUpdate(rootpart, update); for (int i = 0; i < parts.Length; i++) { SceneObjectPart part = parts[i]; if (part == rootpart) continue; - p.ControllingClient.SendEntityUpdate(part, flag); + p.ControllingClient.SendEntityUpdate(part, update); } } } @@ -5560,24 +5537,7 @@ namespace OpenSim.Region.Framework.Scenes if (IsChildAgent || IsInTransit) return; - - PrimUpdateFlags flag; - switch (part.UpdateFlag) - { - case UpdateRequired.TERSE: - flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity - | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; - break; - - case UpdateRequired.FULL: - flag = PrimUpdateFlags.FullUpdate; - break; - - default: - return; - } - - part.UpdateFlag = 0; + PrimUpdateFlags flag = part.GetAndClearUpdateFlag(); ControllingClient.SendEntityUpdate(part, flag); @@ -5597,30 +5557,11 @@ namespace OpenSim.Region.Framework.Scenes } } - - public void SendAttachmentUpdate(SceneObjectPart part, UpdateRequired UpdateFlag) + public void SendAttachmentUpdate(SceneObjectPart part, PrimUpdateFlags flag) { if (IsChildAgent || IsInTransit) return; - PrimUpdateFlags flag; - switch (UpdateFlag) - { - case UpdateRequired.TERSE: - flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity - | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; - break; - - case UpdateRequired.FULL: - flag = PrimUpdateFlags.FullUpdate; - break; - - default: - return; - } - -// part.UpdateFlag = 0; - ControllingClient.SendEntityUpdate(part, flag); if (part.ParentGroup.HasPrivateAttachmentPoint) diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 469dd67437..cfb730c023 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -75,7 +75,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server m_client = client; m_scene = scene; - WorkManager.StartThread(InternalLoop, "IRCClientView", ThreadPriority.Normal, false, true); + WorkManager.StartThread(InternalLoop, "IRCClientView"); } private void SendServerCommand(string command) @@ -630,6 +630,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public int NextAnimationSequenceNumber { get { return 0; } + set { } } public string Name diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs index a1682d2ae6..a408a761b6 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs @@ -58,7 +58,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server m_listener.Start(50); - WorkManager.StartThread(ListenLoop, "IRCServer", ThreadPriority.Normal, false, true); + WorkManager.StartThread(ListenLoop, "IRCServer"); m_baseScene = baseScene; } diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs index ffbebe7d91..d20fe4fcc9 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs @@ -351,7 +351,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat m_log.InfoFormat("[IRC-Connector-{0}]: Connected to {1}:{2}", idn, m_server, m_port); - WorkManager.StartThread(ListenerRun, "IRCConnectionListenerThread", ThreadPriority.Normal, true, false); + WorkManager.StartThread(ListenerRun, "IRCConnectionListenerThread", false, false); // This is the message order recommended by RFC 2812 if (m_password != null) diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 02ac349b47..f975f74ce7 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -648,6 +648,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC public virtual int NextAnimationSequenceNumber { get { return 1; } + set { } } public virtual void SendWearables(AvatarWearable[] wearables, int serial) diff --git a/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsScene.cs b/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsScene.cs index 5ce1515cb4..0faca55387 100644 --- a/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsScene.cs +++ b/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsScene.cs @@ -229,16 +229,6 @@ namespace OpenSim.Region.PhysicsModule.BasicPhysics return fps; } - public override void GetResults() - { - } - - public override bool IsThreaded - { - get { return (false); // for now we won't be multithreaded - } - } - public override void SetTerrain(float[] heightMap) { _heightMap = heightMap; diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs b/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs index a53e2bc2a6..a076d9e746 100644 --- a/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs @@ -352,13 +352,9 @@ namespace OpenSim.Region.PhysicsModule.BulletS if (BSParam.UseSeparatePhysicsThread) { // The physics simulation should happen independently of the heartbeat loop - m_physicsThread - = WorkManager.StartThread( + m_physicsThread = WorkManager.StartThread( BulletSPluginPhysicsThread, - string.Format("{0} ({1})", BulletEngineName, RegionName), - ThreadPriority.Normal, - true, - true); + string.Format("{0} ({1})", BulletEngineName, RegionName)); } } @@ -942,8 +938,6 @@ namespace OpenSim.Region.PhysicsModule.BulletS #endregion // Simulation - public override void GetResults() { } - #region Terrain public override void SetTerrain(float[] heightMap) { @@ -1124,8 +1118,6 @@ namespace OpenSim.Region.PhysicsModule.BulletS return topColliders; } - public override bool IsThreaded { get { return false; } } - #region Extensions public override object Extension(string pFunct, params object[] pParams) { diff --git a/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs b/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs index e760fa258f..1b681051c7 100644 --- a/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs +++ b/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs @@ -3204,16 +3204,6 @@ namespace OpenSim.Region.PhysicsModule.ODE } } - public override void GetResults() - { - } - - public override bool IsThreaded - { - // for now we won't be multithreaded - get { return false; } - } - public override void SetTerrain(float[] heightMap) { if (m_worldOffset != Vector3.Zero && m_parentScene != null) diff --git a/OpenSim/Region/PhysicsModules/POS/POSScene.cs b/OpenSim/Region/PhysicsModules/POS/POSScene.cs index e62d8769c8..3e278f7144 100644 --- a/OpenSim/Region/PhysicsModules/POS/POSScene.cs +++ b/OpenSim/Region/PhysicsModules/POS/POSScene.cs @@ -297,16 +297,6 @@ namespace OpenSim.Region.PhysicsModule.POS return 1.0f; } - public override void GetResults() - { - } - - public override bool IsThreaded - { - // for now we won't be multithreaded - get { return (false); } - } - public override void SetTerrain(float[] heightMap) { _heightMap = heightMap; diff --git a/OpenSim/Region/PhysicsModules/SharedBase/NullPhysicsScene.cs b/OpenSim/Region/PhysicsModules/SharedBase/NullPhysicsScene.cs index 8079e79bbb..335e9bddbd 100644 --- a/OpenSim/Region/PhysicsModules/SharedBase/NullPhysicsScene.cs +++ b/OpenSim/Region/PhysicsModules/SharedBase/NullPhysicsScene.cs @@ -85,11 +85,6 @@ namespace OpenSim.Region.PhysicsModules.SharedBase return 0f; } - public override void GetResults() - { - m_log.Info("[PHYSICS]: NullPhysicsScene : GetResults()"); - } - public override void SetTerrain(float[] heightMap) { m_log.InfoFormat("[PHYSICS]: NullPhysicsScene : SetTerrain({0} items)", heightMap.Length); @@ -99,11 +94,6 @@ namespace OpenSim.Region.PhysicsModules.SharedBase { } - public override bool IsThreaded - { - get { return false; } - } - public override void Dispose() { } diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index dabfd3bf55..4ee2eb5679 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -331,7 +331,8 @@ namespace OpenSim.Services.GridService region = m_GridService.GetRegionByUUID(scopeID, regionID); if (region != null) { - m_log.DebugFormat("[HYPERGRID LINKER]: Region already exists in coordinates <{0},{1}>", Util.WorldToRegionLoc((uint)region.RegionLocX), Util.WorldToRegionLoc((uint)region.RegionLocY)); + m_log.DebugFormat("[HYPERGRID LINKER]: Region already exists in coordinates <{0},{1}>", + Util.WorldToRegionLoc((uint)region.RegionLocX), Util.WorldToRegionLoc((uint)region.RegionLocY)); regInfo = region; return true; } diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 91a71ec0ad..6e8cc9f226 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -441,6 +441,7 @@ namespace OpenSim.Tests.Common public virtual int NextAnimationSequenceNumber { get { return 1; } + set { } } public IScene Scene