diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 0c5224b8be..5a5e5d0413 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -602,16 +602,26 @@ namespace OpenSim.Framework { // we are on the new one if (m_flags.HasFlag(PrimUpdateFlags.CancelKill)) - m_flags = PrimUpdateFlags.FullUpdatewithAnim; + { + if (m_flags.HasFlag(PrimUpdateFlags.UpdateProbe)) + m_flags = PrimUpdateFlags.UpdateProbe; + else + m_flags = PrimUpdateFlags.FullUpdatewithAnim; + } } public virtual void Update(EntityUpdate oldupdate) { // we are on the new one PrimUpdateFlags updateFlags = oldupdate.Flags; + if (updateFlags.HasFlag(PrimUpdateFlags.UpdateProbe)) + updateFlags &= ~PrimUpdateFlags.UpdateProbe; if (m_flags.HasFlag(PrimUpdateFlags.CancelKill)) { - m_flags = PrimUpdateFlags.FullUpdatewithAnim; + if(m_flags.HasFlag(PrimUpdateFlags.UpdateProbe)) + m_flags = PrimUpdateFlags.UpdateProbe; + else + m_flags = PrimUpdateFlags.FullUpdatewithAnim; } else m_flags |= updateFlags; @@ -679,6 +689,7 @@ namespace OpenSim.Framework FullUpdatewithAnim = FullUpdate | Animations, + UpdateProbe = 0x10000000, // 1 << 28 SendInTransit = 0x20000000, // 1 << 29 CancelKill = 0x40000000, // 1 << 30 Kill = 0x80000000 // 1 << 31 @@ -805,7 +816,7 @@ namespace OpenSim.Framework event TeleportCancel OnTeleportCancel; event DeRezObject OnDeRezObject; event RezRestoreToWorld OnRezRestoreToWorld; - event Action OnRegionHandShakeReply; + event Action OnRegionHandShakeReply; event GenericCall1 OnRequestWearables; event Action OnCompleteMovementToRegion; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 662e5ade56..526783e66e 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -80,7 +80,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event DeRezObject OnDeRezObject; public event RezRestoreToWorld OnRezRestoreToWorld; public event ModifyTerrain OnModifyTerrain; - public event Action OnRegionHandShakeReply; + public event Action OnRegionHandShakeReply; public event GenericCall1 OnRequestWearables; public event SetAppearance OnSetAppearance; public event AvatarNowWearing OnAvatarNowWearing; @@ -392,6 +392,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected IAssetService m_assetService; + protected bool m_supportViewerCache = false; #endregion Class Members #region Properties @@ -552,6 +553,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP string name = string.Format("AsyncInUDP-{0}",m_agentId.ToString()); m_asyncPacketProcess = new JobEngine(name, name, 10000); IsActive = true; + + m_supportViewerCache = m_udpServer.SupportViewerObjectsCache; } #region Client Methods @@ -4777,6 +4780,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP 13 // ID (high frequency) }; + static private readonly byte[] ObjectUpdateCachedHeader = new byte[] { + Helpers.MSG_RELIABLE, + 0, 0, 0, 0, // sequence number + 0, // extra + 14 // ID (high frequency) + }; + private void ProcessEntityUpdates(int maxUpdatesBytes) { if (!IsActive) @@ -4786,8 +4796,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (mysp == null) return; + List objectUpdates = null; - //List compressedUpdates = null; + List objectUpdateProbes = null; + List compressedUpdates = null; List terseUpdates = null; List ObjectAnimationUpdates = null; @@ -4799,6 +4811,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP EntityUpdate update; + bool viewerCache = m_supportViewerCache && (m_viewerHandShakeFlags & 1) != 0 && mysp.IsChildAgent; // only on child agents bool doCulling = m_scene.ObjectsCullingByDistance; float cullingrange = 64.0f; Vector3 mypos = Vector3.Zero; @@ -4807,7 +4820,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP bool orderedDequeue = false; // temporary off HashSet GroupsNeedFullUpdate = new HashSet(); - + bool useCompressUpdate = false; if (doCulling) { @@ -4834,15 +4847,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags; + PrimUpdateFlags updateFlags = update.Flags; - if(updateFlags.HasFlag(PrimUpdateFlags.Kill)) + if (updateFlags.HasFlag(PrimUpdateFlags.Kill)) { m_killRecord.Add(update.Entity.LocalId); maxUpdatesBytes -= 30; continue; } + useCompressUpdate = false; + if (update.Entity is SceneObjectPart) { SceneObjectPart part = (SceneObjectPart)update.Entity; @@ -4928,10 +4943,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (dpos > maxview * maxview) continue; - GroupsNeedFullUpdate.Add(grp); - continue; + if (!viewerCache || !updateFlags.HasFlag(PrimUpdateFlags.UpdateProbe)) + { + GroupsNeedFullUpdate.Add(grp); + continue; + } } } + + if (updateFlags.HasFlag(PrimUpdateFlags.UpdateProbe)) + { + if (objectUpdateProbes == null) + { + objectUpdateProbes = new List(); + maxUpdatesBytes -= 18; + } + objectUpdateProbes.Add(update); + maxUpdatesBytes -= 12; + continue; + } + + if (m_SupportObjectAnimations && updateFlags.HasFlag(PrimUpdateFlags.Animations)) + { + if (part.Animations != null) + { + if (ObjectAnimationUpdates == null) + ObjectAnimationUpdates = new List(); + ObjectAnimationUpdates.Add(part); + maxUpdatesBytes -= 20 * part.Animations.Count + 24; + } + } + if(viewerCache) + useCompressUpdate = grp.IsViewerCachable; } else if (update.Entity is ScenePresence) { @@ -4951,27 +4994,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region UpdateFlags to packet type conversion - // bool canUseCompressed = true; - - if (update.Entity is SceneObjectPart) - { - if (m_SupportObjectAnimations && updateFlags.HasFlag(PrimUpdateFlags.Animations)) - { - SceneObjectPart sop = (SceneObjectPart)update.Entity; - if ( sop.Animations != null) - { - if(ObjectAnimationUpdates == null) - ObjectAnimationUpdates = new List(); - ObjectAnimationUpdates.Add(sop); - maxUpdatesBytes -= 20 * sop.Animations.Count + 24; - } - } - } - else - { - // canUseCompressed = false; - } - updateFlags &= PrimUpdateFlags.FullUpdate; // clear other control bits already handled if(updateFlags == PrimUpdateFlags.None) continue; @@ -5025,23 +5047,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { - SceneObjectPart part = (SceneObjectPart)update.Entity; - SceneObjectGroup grp = part.ParentGroup; - // minimal compress conditions, not enough ? - //if (grp.UsesPhysics || part.Velocity.LengthSquared() > 1e-8f || part.Acceleration.LengthSquared() > 1e-6f) - { - maxUpdatesBytes -= 150; // crude estimation - - if (objectUpdates == null) - { - objectUpdates = new List(); - maxUpdatesBytes -= 18; - } - objectUpdates.Add(update); - } - //compress still disabled - /* - else + if (useCompressUpdate) { maxUpdatesBytes -= 150; // crude estimation @@ -5052,7 +5058,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP } compressedUpdates.Add(update); } - */ + else + { + maxUpdatesBytes -= 150; // crude estimation + + if (objectUpdates == null) + { + objectUpdates = new List(); + maxUpdatesBytes -= 18; + } + objectUpdates.Add(update); + } } } @@ -5147,7 +5163,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); } } - /* + if(compressedUpdates != null) { List tau = new List(30); @@ -5168,8 +5184,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP int count = 0; foreach (EntityUpdate eu in compressedUpdates) { + SceneObjectPart sop = (SceneObjectPart)eu.Entity; + if (sop.ParentGroup == null || sop.ParentGroup.IsDeleted) + continue; lastpos = pos; - CreateCompressedUpdateBlock((SceneObjectPart)eu.Entity, mysp, data, ref pos); + CreateCompressedUpdateBlock(sop, mysp, data, ref pos); if (pos < LLUDPServer.MAXPAYLOAD) { tau.Add(eu); @@ -5207,7 +5226,68 @@ namespace OpenSim.Region.ClientStack.LindenUDP delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); } } - */ + + if (objectUpdateProbes != null) + { + UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); + byte[] data = buf.Data; + + Buffer.BlockCopy(ObjectUpdateCachedHeader, 0, data, 0, 7); + + Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, data, 7); // 15 + Utils.UInt16ToBytes(timeDilation, data, 15); // 17 + + int countposition = 17; // blocks count position + int pos = 18; + + int count = 0; + foreach (EntityUpdate eu in objectUpdateProbes) + { + SceneObjectPart sop = (SceneObjectPart)eu.Entity; + if (sop.ParentGroup == null || sop.ParentGroup.IsDeleted) + continue; + uint primflags = m_scene.Permissions.GenerateClientFlags(sop, mysp); + if (mysp.UUID != sop.OwnerID) + primflags &= ~(uint)PrimFlags.CreateSelected; + else + { + if (sop.CreateSelected) + primflags |= (uint)PrimFlags.CreateSelected; + else + primflags &= ~(uint)PrimFlags.CreateSelected; + } + + Utils.UIntToBytes(sop.LocalId, data, pos); pos += 4; + Utils.UIntToBytes((uint)sop.ParentGroup.PseudoCRC, data, pos); pos += 4; //WRONG + Utils.UIntToBytes(primflags, data, pos); pos += 4; + + if (pos < (LLUDPServer.MAXPAYLOAD - 12)) + ++count; + else + { + // we need more packets + UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); + Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, countposition); // start is the same + + buf.Data[countposition] = (byte)count; + buf.DataLength = pos; + m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, false); + + buf = newbuf; + data = buf.Data; + pos = 18; + count = 0; + } + } + + if (count > 0) + { + buf.Data[countposition] = (byte)count; + buf.DataLength = pos; + m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, null, false, false); + } + } + if (terseUpdates != null) { int blocks = terseUpdates.Count; @@ -5329,8 +5409,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP { lock (GroupsInView) GroupsInView.Add(grp); + PrimUpdateFlags flags = PrimUpdateFlags.CancelKill; + if(viewerCache && grp.IsViewerCachable) + flags |= PrimUpdateFlags.UpdateProbe; foreach (SceneObjectPart p in grp.Parts) - SendEntityUpdate(p, PrimUpdateFlags.CancelKill); + SendEntityUpdate(p, flags); } } @@ -5461,10 +5544,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP if(GroupsNeedFullUpdate.Count > 0) { - foreach(SceneObjectGroup grp in GroupsNeedFullUpdate) + bool viewerCache = m_supportViewerCache && (m_viewerHandShakeFlags & 1) != 0 && mysp.IsChildAgent; + foreach (SceneObjectGroup grp in GroupsNeedFullUpdate) { - foreach(SceneObjectPart p in grp.Parts) - SendEntityUpdate(p, PrimUpdateFlags.CancelKill); + PrimUpdateFlags flags = PrimUpdateFlags.CancelKill; + if (viewerCache && grp.IsViewerCachable) + flags |= PrimUpdateFlags.UpdateProbe; + foreach (SceneObjectPart p in grp.Parts) + SendEntityUpdate(p, flags); } } @@ -7173,7 +7260,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP dest[pos++] = state; ///**** temp hack - Utils.UIntToBytesSafepos((uint)rnd.Next(), dest, pos); pos += 4; //CRC needs fix or things will get crazy for now avoid caching + Utils.UIntToBytesSafepos((uint)part.ParentGroup.PseudoCRC, dest, pos); pos += 4; dest[pos++] = part.Material; dest[pos++] = part.ClickAction; part.Shape.Scale.ToBytes(dest, pos); pos += 12; @@ -8407,13 +8494,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } + public uint m_viewerHandShakeFlags = 0; + private bool HandlerRegionHandshakeReply(IClientAPI sender, Packet Pack) { - Action handlerRegionHandShakeReply = OnRegionHandShakeReply; - if (handlerRegionHandShakeReply != null) - { - handlerRegionHandShakeReply(this); - } + Action handlerRegionHandShakeReply = OnRegionHandShakeReply; + if (handlerRegionHandShakeReply == null) + return true; // silence the warning + + RegionHandshakeReplyPacket rsrpkt = (RegionHandshakeReplyPacket)Pack; + if(rsrpkt.AgentData.AgentID != m_agentId || rsrpkt.AgentData.SessionID != m_sessionId) + return false; + + // regionHandSHake is a protocol message, but it is also seems to be the only way to update terrain textures + // in last case this should be ignored. + OnRegionHandShakeReply = null; + if(m_supportViewerCache) + m_viewerHandShakeFlags = rsrpkt.RegionInfo.Flags; + else + m_viewerHandShakeFlags = 0; + + handlerRegionHandShakeReply(this, m_viewerHandShakeFlags); return true; } @@ -8657,19 +8758,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } - private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack) + private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack) { - m_log.DebugFormat("[LLClientView] HandleCompleteAgentMovement"); + //m_log.DebugFormat("[LLClientView] HandleCompleteAgentMovement"); Action handlerCompleteMovementToRegion = OnCompleteMovementToRegion; - if (handlerCompleteMovementToRegion != null) - { - handlerCompleteMovementToRegion(sender, true); - } - else - m_log.Debug("HandleCompleteAgentMovement NULL handler"); + if (handlerCompleteMovementToRegion == null) + return false; - handlerCompleteMovementToRegion = null; + CompleteAgentMovementPacket cmp = (CompleteAgentMovementPacket)Pack; + if(cmp.AgentData.AgentID != m_agentId || cmp.AgentData.SessionID != m_sessionId || cmp.AgentData.CircuitCode != m_circuitCode) + return false; + + handlerCompleteMovementToRegion(sender, true); return true; } @@ -9141,6 +9242,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP private bool HandleRequestMultipleObjects(IClientAPI sender, Packet Pack) { + ObjectRequest handlerObjectRequest = OnObjectRequest; + if (handlerObjectRequest == null) + return false; + RequestMultipleObjectsPacket incomingRequest = (RequestMultipleObjectsPacket)Pack; #region Packet Session and User Check @@ -9149,16 +9254,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; #endregion - ObjectRequest handlerObjectRequest = null; - for (int i = 0; i < incomingRequest.ObjectData.Length; i++) - { - handlerObjectRequest = OnObjectRequest; - if (handlerObjectRequest != null) - { handlerObjectRequest(incomingRequest.ObjectData[i].ID, this); - } - } return true; } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index a0b3d21e9f..6032681290 100755 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -369,6 +369,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public int IncomingOrphanedPacketCount { get; protected set; } + public bool SupportViewerObjectsCache = false; /// /// Run queue empty processing within a single persistent thread. /// @@ -433,6 +434,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_disableFacelights = config.GetBoolean("DisableFacelights", false); m_ackTimeout = 1000 * config.GetInt("AckTimeout", 60); m_pausedAckTimeout = 1000 * config.GetInt("PausedAckTimeout", 300); + SupportViewerObjectsCache = config.GetBoolean("SupportViewerObjectsCache", SupportViewerObjectsCache); } else { @@ -1724,14 +1726,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (client != null) { client.SendRegionHandshake(); - client.CheckViewerCaps(); - - // We only want to send initial data to new clients, not ones which are being converted from child to root. - bool tp = (aCircuit.teleportFlags > 0); - // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from - if (!tp) - client.SceneAgent.SendInitialDataToMe(); } } else diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index fd087213af..936f956c7a 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -574,7 +574,7 @@ namespace OpenSim.Region.CoreModules.World.Estate Scene.RegionInfo.RegionSettings.Save(); TriggerRegionInfoChange(); sendRegionHandshakeToAll(); - sendRegionInfoPacketToAll(); +// sendRegionInfoPacketToAll(); } private void handleCommitEstateTerrainTextureRequest(IClientAPI remoteClient) diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index 0c080d22df..299509100f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -153,10 +153,23 @@ namespace OpenSim.Region.Framework.Scenes /// public void RequestPrim(uint primLocalID, IClientAPI remoteClient) { - SceneObjectGroup sog = GetGroupByPrim(primLocalID); + SceneObjectPart part = GetSceneObjectPart(primLocalID); + if (part != null) + { + SceneObjectGroup sog = part.ParentGroup; + if(!sog.IsDeleted) + { + PrimUpdateFlags update = PrimUpdateFlags.FullUpdate; + if (sog.RootPart.Shape.MeshFlagEntry) + update = PrimUpdateFlags.FullUpdatewithAnim; + part.SendUpdate(remoteClient, update); + } + } - if (sog != null) - sog.SendFullAnimUpdateToClient(remoteClient); + //SceneObjectGroup sog = GetGroupByPrim(primLocalID); + + //if (sog != null) + //sog.SendFullAnimUpdateToClient(remoteClient); } /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 7668a87511..7d312e90f0 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -170,8 +170,6 @@ namespace OpenSim.Region.Framework.Scenes } private bool m_scripts_enabled; - public SynchronizeSceneHandler SynchronizeScene; - public bool ClampNegativeZ { get { return m_clampNegativeZ; } @@ -1006,11 +1004,9 @@ namespace OpenSim.Region.Framework.Scenes m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete",m_useTrashOnDelete); m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); - m_dontPersistBefore = - startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE); + m_dontPersistBefore = startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE); m_dontPersistBefore *= 10000000; - m_persistAfter = - startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE); + m_persistAfter = startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE); m_persistAfter *= 10000000; m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); @@ -1695,9 +1691,6 @@ namespace OpenSim.Region.Framework.Scenes { if (PhysicsEnabled) physicsFPS = m_sceneGraph.UpdatePhysics(FrameTime); - - if (SynchronizeScene != null) - SynchronizeScene(this); } tmpMS2 = Util.GetTimeStampMS(); @@ -1775,30 +1768,6 @@ namespace OpenSim.Region.Framework.Scenes // Region ready should always be set Ready = true; - - - IConfig restartConfig = m_config.Configs["RestartModule"]; - if (restartConfig != null) - { - string markerPath = restartConfig.GetString("MarkerPath", String.Empty); - - if (markerPath != String.Empty) - { - string path = Path.Combine(markerPath, RegionInfo.RegionID.ToString() + ".ready"); - try - { - string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString(); - FileStream fs = File.Create(path); - System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); - Byte[] buf = enc.GetBytes(pidstring); - fs.Write(buf, 0, buf.Length); - fs.Close(); - } - catch (Exception) - { - } - } - } } else { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 7d5bbbf0a0..0b3817996e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -119,6 +119,21 @@ namespace OpenSim.Region.Framework.Scenes // private PrimCountTaintedDelegate handlerPrimCountTainted = null; + public bool IsViewerCachable + { + get + { + // needs more exclusion ? + return(Backup && !IsTemporary && !inTransit && !IsSelected && !UsesPhysics && !IsAttachmentCheckFull() && + !RootPart.Shape.MeshFlagEntry && // animations are not sent correctly for now + RootPart.KeyframeMotion == null && + (DateTime.UtcNow.Ticks - timeLastChanged > 36000000000) && //36000000000 is one hour + RootPart.Velocity.LengthSquared() < 1e8f && // should not be needed + RootPart.Acceleration.LengthSquared() < 1e4f // should not be needed + ); + } + } + /// /// Signal whether the non-inventory attributes of any prims in the group have changed /// since the group's last persistent backup @@ -128,7 +143,8 @@ namespace OpenSim.Region.Framework.Scenes private long timeLastChanged = 0; private long m_maxPersistTime = 0; private long m_minPersistTime = 0; -// private Random m_rand; + + public int PseudoCRC; /// /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage @@ -145,40 +161,26 @@ namespace OpenSim.Region.Framework.Scenes { if (value) { - if (Backup) - { m_scene.SceneGraph.FireChangeBackup(this); - } + + PseudoCRC = (int)(DateTime.UtcNow.Ticks); ; timeLastChanged = DateTime.UtcNow.Ticks; if (!m_hasGroupChanged) - timeFirstChanged = DateTime.UtcNow.Ticks; + timeFirstChanged = timeLastChanged; if (m_rootPart != null && m_scene != null) { -/* - if (m_rand == null) - { - byte[] val = new byte[16]; - m_rootPart.UUID.ToBytes(val, 0); - m_rand = new Random(BitConverter.ToInt32(val, 0)); - } - */ if (m_scene.GetRootAgentCount() == 0) { //If the region is empty, this change has been made by an automated process //and thus we delay the persist time by a random amount between 1.5 and 2.5. -// float factor = 1.5f + (float)(m_rand.NextDouble()); float factor = 2.0f; - m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor); - m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor); + m_maxPersistTime = (long)(m_scene.m_persistAfter * factor); + m_minPersistTime = (long)(m_scene.m_dontPersistBefore * factor); } else { - //If the region is not empty, we want to obey the minimum and maximum persist times - //but add a random factor so we stagger the object persistance a little -// m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5 -// m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0 m_maxPersistTime = m_scene.m_persistAfter; m_minPersistTime = m_scene.m_dontPersistBefore; } @@ -1330,6 +1332,7 @@ namespace OpenSim.Region.Framework.Scenes public SceneObjectGroup() { m_lastCollisionSoundMS = Util.GetTimeStampMS() + 1000.0; + PseudoCRC = (int)(DateTime.UtcNow.Ticks); } /// @@ -2441,6 +2444,21 @@ namespace OpenSim.Region.Framework.Scenes } } + public void SendUpdateProbes(IClientAPI remoteClient) + { + PrimUpdateFlags update = PrimUpdateFlags.UpdateProbe; + + RootPart.SendUpdate(remoteClient, update); + + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + { + SceneObjectPart part = parts[i]; + if (part != RootPart) + part.SendUpdate(remoteClient, update); + } + } + #region Copying /// @@ -2516,6 +2534,7 @@ namespace OpenSim.Region.Framework.Scenes } dupe.InvalidatePartsLinkMaps(); + dupe.PseudoCRC = (int)(DateTime.UtcNow.Ticks); m_dupeInProgress = false; return dupe; } @@ -2769,6 +2788,7 @@ namespace OpenSim.Region.Framework.Scenes } } + PseudoCRC = (int)(DateTime.UtcNow.Ticks); rpart.ScheduleFullUpdate(); } @@ -2808,6 +2828,7 @@ namespace OpenSim.Region.Framework.Scenes part.ResetIDs(part.LinkNum); // Don't change link nums m_parts.Add(part.UUID, part); } + PseudoCRC = (int)(DateTime.UtcNow.Ticks); } } @@ -3117,7 +3138,6 @@ namespace OpenSim.Region.Framework.Scenes } } - // 'linkPart' == the root of the group being linked into this group SceneObjectPart linkPart = objectGroup.m_rootPart; @@ -3160,7 +3180,6 @@ namespace OpenSim.Region.Framework.Scenes axPos *= Quaternion.Conjugate(parentRot); linkPart.OffsetPosition = axPos; - // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset. // Now that we know this SOG has at least two SOPs in it, the new root // SOP becomes the first in the linkset. @@ -3193,8 +3212,7 @@ namespace OpenSim.Region.Framework.Scenes linkPart.CreateSelected = true; - // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now - linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive, true); + linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive || RootPart.VolumeDetectActive, true); // If the added SOP is physical, also tell the physics engine about the link relationship. if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 5c38bf3d6e..4f3f83a656 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1179,9 +1179,10 @@ namespace OpenSim.Region.Framework.Scenes set { + string old = m_mediaUrl; m_mediaUrl = value; - if (ParentGroup != null) + if (ParentGroup != null && old != m_mediaUrl) ParentGroup.HasGroupChanged = true; } } @@ -1385,13 +1386,6 @@ namespace OpenSim.Region.Framework.Scenes } } - [XmlIgnore] - public bool IsOccupied // KF If an av is sittingon this prim - { - get { return m_occupied; } - set { m_occupied = value; } - } - /// /// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero /// @@ -2472,12 +2466,6 @@ namespace OpenSim.Region.Framework.Scenes public uint GetEffectiveObjectFlags() { - // Commenting this section of code out since it doesn't actually do anything, as enums are handled by - // value rather than reference -// PrimFlags f = _flags; -// if (m_parentGroup == null || m_parentGroup.RootPart == this) -// f &= ~(PrimFlags.Touch | PrimFlags.Money); - uint eff = (uint)Flags | (uint)LocalFlags; if(m_inventory == null || m_inventory.Count == 0) eff |= (uint)PrimFlags.InventoryEmpty; diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index f010035c36..e635841c46 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1212,7 +1212,9 @@ namespace OpenSim.Region.Framework.Scenes ControllingClient.OnForceReleaseControls += HandleForceReleaseControls; ControllingClient.OnAutoPilotGo += MoveToTargetHandle; ControllingClient.OnUpdateThrottles += RaiseUpdateThrottles; -// ControllingClient.OnAgentFOV += HandleAgentFOV; + ControllingClient.OnRegionHandShakeReply += RegionHandShakeReply; + + // ControllingClient.OnAgentFOV += HandleAgentFOV; // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); @@ -1232,7 +1234,9 @@ namespace OpenSim.Region.Framework.Scenes ControllingClient.OnForceReleaseControls -= HandleForceReleaseControls; ControllingClient.OnAutoPilotGo -= MoveToTargetHandle; ControllingClient.OnUpdateThrottles -= RaiseUpdateThrottles; -// ControllingClient.OnAgentFOV += HandleAgentFOV; + ControllingClient.OnRegionHandShakeReply -= RegionHandShakeReply; + + // ControllingClient.OnAgentFOV += HandleAgentFOV; } private void SetDirectionVectors() @@ -2126,56 +2130,54 @@ namespace OpenSim.Region.Framework.Scenes return; } - + if(IsChildAgent) + { + return; // how? + } //m_log.DebugFormat("[CompleteMovement] MakeRootAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts)); - if(!haveGroupInformation && !IsChildAgent && !IsNPC) + if (!IsNPC) { - IGroupsModule gm = m_scene.RequestModuleInterface(); - if (gm != null) - Grouptitle = gm.GetGroupTitle(m_uuid); + if (!haveGroupInformation && !IsNPC) + { + IGroupsModule gm = m_scene.RequestModuleInterface(); + if (gm != null) + Grouptitle = gm.GetGroupTitle(m_uuid); - //m_log.DebugFormat("[CompleteMovement] Missing Grouptitle: {0}ms", Util.EnvironmentTickCountSubtract(ts)); + //m_log.DebugFormat("[CompleteMovement] Missing Grouptitle: {0}ms", Util.EnvironmentTickCountSubtract(ts)); - InventoryFolderBase cof = m_scene.InventoryService.GetFolderForType(client.AgentId, (FolderType)46); - if (cof == null) - COF = UUID.Zero; - else - COF = cof.ID; + InventoryFolderBase cof = m_scene.InventoryService.GetFolderForType(client.AgentId, (FolderType)46); + if (cof == null) + COF = UUID.Zero; + else + COF = cof.ID; - m_log.DebugFormat("[CompleteMovement]: Missing COF for {0} is {1}", client.AgentId, COF); + m_log.DebugFormat("[CompleteMovement]: Missing COF for {0} is {1}", client.AgentId, COF); + } + + if (!string.IsNullOrEmpty(m_callbackURI)) + { + // We cannot sleep here since this would hold up the inbound packet processing thread, as + // CompleteMovement() is executed synchronously. However, it might be better to delay the release + // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete + // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this + // region as the current region, meaning that a close sent before then will fail the teleport. + // System.Threading.Thread.Sleep(2000); + + m_log.DebugFormat( + "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", + client.Name, client.AgentId, m_callbackURI); + + UUID originID; + + lock (m_originRegionIDAccessLock) + originID = m_originRegionID; + + Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI); + m_callbackURI = null; + //m_log.DebugFormat("[CompleteMovement] ReleaseAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts)); + } } - - if (!string.IsNullOrEmpty(m_callbackURI)) - { - // We cannot sleep here since this would hold up the inbound packet processing thread, as - // CompleteMovement() is executed synchronously. However, it might be better to delay the release - // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete - // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this - // region as the current region, meaning that a close sent before then will fail the teleport. - // System.Threading.Thread.Sleep(2000); - - m_log.DebugFormat( - "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", - client.Name, client.AgentId, m_callbackURI); - - UUID originID; - - lock (m_originRegionIDAccessLock) - originID = m_originRegionID; - - Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI); - m_callbackURI = null; - //m_log.DebugFormat("[CompleteMovement] ReleaseAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts)); - } -// else -// { -// m_log.DebugFormat( -// "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}", -// client.Name, client.AgentId, m_scene.RegionInfo.RegionName); -// } - - // Tell the client that we're totally ready ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); //m_log.DebugFormat("[CompleteMovement] MoveAgentIntoRegion: {0}ms", Util.EnvironmentTickCountSubtract(ts)); @@ -2187,33 +2189,30 @@ namespace OpenSim.Region.Framework.Scenes int delayctnr = Util.EnvironmentTickCount(); - if (!IsChildAgent) + if( ParentPart != null && !IsNPC && (crossingFlags & 0x08) != 0) { - if( ParentPart != null && !IsNPC && (crossingFlags & 0x08) != 0) - { - ParentPart.ParentGroup.SendFullAnimUpdateToClient(ControllingClient); - } - - // verify baked textures and cache - bool cachedbaked = false; - - if (IsNPC) - cachedbaked = true; - else - { - if (m_scene.AvatarFactory != null && !isHGTP) - cachedbaked = m_scene.AvatarFactory.ValidateBakedTextureCache(this); - - // not sure we need this - if (!cachedbaked) - { - if (m_scene.AvatarFactory != null) - m_scene.AvatarFactory.QueueAppearanceSave(UUID); - } - } - //m_log.DebugFormat("[CompleteMovement] Baked check: {0}ms", Util.EnvironmentTickCountSubtract(ts)); + ParentPart.ParentGroup.SendFullAnimUpdateToClient(ControllingClient); } + // verify baked textures and cache + bool cachedbaked = false; + + if (IsNPC) + cachedbaked = true; + else + { + if (m_scene.AvatarFactory != null && !isHGTP) + cachedbaked = m_scene.AvatarFactory.ValidateBakedTextureCache(this); + + // not sure we need this + if (!cachedbaked) + { + if (m_scene.AvatarFactory != null) + m_scene.AvatarFactory.QueueAppearanceSave(UUID); + } + } + //m_log.DebugFormat("[CompleteMovement] Baked check: {0}ms", Util.EnvironmentTickCountSubtract(ts)); + if(m_teleportFlags > 0) { gotCrossUpdate = false; // sanity check @@ -2251,104 +2250,103 @@ namespace OpenSim.Region.Framework.Scenes landch.sendClientInitialLandInfo(client, !gotCrossUpdate); } - if (!IsChildAgent) + List allpresences = m_scene.GetScenePresences(); + + // send avatar object to all presences including us, so they cross it into region + // then hide if necessary + + SendInitialAvatarDataToAllAgents(allpresences); + + // send this look + SendAppearanceToAgent(this); + + // send this animations + + UUID[] animIDs = null; + int[] animseqs = null; + UUID[] animsobjs = null; + + if (Animator != null) + Animator.GetArrays(out animIDs, out animseqs, out animsobjs); + + bool haveAnims = (animIDs != null && animseqs != null && animsobjs != null); + + if (haveAnims) + SendAnimPackToAgent(this, animIDs, animseqs, animsobjs); + + // we should be able to receive updates, etc + // so release them + m_inTransit = false; + + // send look and animations to others + // if not cached we send greys + // uncomented if will wait till avatar does baking + //if (cachedbaked) { - List allpresences = m_scene.GetScenePresences(); - - // send avatar object to all presences including us, so they cross it into region - // then hide if necessary - - SendInitialAvatarDataToAllAgents(allpresences); - - // send this look - SendAppearanceToAgent(this); - - // send this animations - - UUID[] animIDs = null; - int[] animseqs = null; - UUID[] animsobjs = null; - - if (Animator != null) - Animator.GetArrays(out animIDs, out animseqs, out animsobjs); - - bool haveAnims = (animIDs != null && animseqs != null && animsobjs != null); - - if (haveAnims) - SendAnimPackToAgent(this, animIDs, animseqs, animsobjs); - - // we should be able to receive updates, etc - // so release them - m_inTransit = false; - - // send look and animations to others - // if not cached we send greys - // uncomented if will wait till avatar does baking - //if (cachedbaked) + foreach (ScenePresence p in allpresences) { + if (p == this) + continue; + + if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) + continue; + + SendAppearanceToAgentNF(p); + if (haveAnims) + SendAnimPackToAgentNF(p, animIDs, animseqs, animsobjs); + } + } // greys if + + //m_log.DebugFormat("[CompleteMovement] ValidateAndSendAppearanceAndAgentData: {0}ms", Util.EnvironmentTickCountSubtract(ts)); + + // attachments + if (IsNPC || IsRealLogin(m_teleportFlags)) + { + if (Scene.AttachmentsModule != null) + // Util.FireAndForget( + // o => + // { + + if (!IsNPC) + Scene.AttachmentsModule.RezAttachments(this); + else + Util.FireAndForget(x => + { + Scene.AttachmentsModule.RezAttachments(this); + }); + + // }); + } + else + { + if (m_attachments.Count > 0) + { +// m_log.DebugFormat( +// "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); + + foreach (SceneObjectGroup sog in m_attachments) + { + sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); + sog.ResumeScripts(); + } + foreach (ScenePresence p in allpresences) { if (p == this) + { + SendAttachmentsToAgentNF(this); continue; + } if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) continue; - SendAppearanceToAgentNF(p); - if (haveAnims) - SendAnimPackToAgentNF(p, animIDs, animseqs, animsobjs); - } - } // greys if - - //m_log.DebugFormat("[CompleteMovement] ValidateAndSendAppearanceAndAgentData: {0}ms", Util.EnvironmentTickCountSubtract(ts)); - - // attachments - if (IsNPC || IsRealLogin(m_teleportFlags)) - { - if (Scene.AttachmentsModule != null) - // Util.FireAndForget( - // o => - // { - - if (!IsNPC) - Scene.AttachmentsModule.RezAttachments(this); - else - Util.FireAndForget(x => - { - Scene.AttachmentsModule.RezAttachments(this); - }); - - // }); - } - else - { - if (m_attachments.Count > 0) - { -// m_log.DebugFormat( -// "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); - - foreach (SceneObjectGroup sog in m_attachments) - { - sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); - sog.ResumeScripts(); - } - - foreach (ScenePresence p in allpresences) - { - if (p == this) - { - SendAttachmentsToAgentNF(this); - continue; - } - - if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) - continue; - - SendAttachmentsToAgentNF(p); - } + SendAttachmentsToAgentNF(p); } } - + } + if(!IsNPC) + { //m_log.DebugFormat("[CompleteMovement] attachments: {0}ms", Util.EnvironmentTickCountSubtract(ts)); if (openChildAgents) { @@ -2366,34 +2364,33 @@ namespace OpenSim.Region.Framework.Scenes m_lastChildAgentUpdateGodLevel = GodController.ViwerUIGodLevel; m_childUpdatesBusy = false; // allow them - } - //m_log.DebugFormat("[CompleteMovement] openChildAgents: {0}ms", Util.EnvironmentTickCountSubtract(ts)); + //m_log.DebugFormat("[CompleteMovement] openChildAgents: {0}ms", Util.EnvironmentTickCountSubtract(ts)); - // send the rest of the world - if (m_teleportFlags > 0 && !IsNPC || m_currentParcelHide) - SendInitialDataToMe(); + // send the rest of the world + if (m_teleportFlags > 0 | m_currentParcelHide) + SendInitialDataToMe(); - // priority uses avatar position only -// m_reprioritizationLastPosition = AbsolutePosition; -// m_reprioritizationLastDrawDistance = DrawDistance; -// m_reprioritizationLastTime = Util.EnvironmentTickCount() + 15000; // delay it -// m_reprioritizationBusy = false; + // priority uses avatar position only + // m_reprioritizationLastPosition = AbsolutePosition; + // m_reprioritizationLastDrawDistance = DrawDistance; + // m_reprioritizationLastTime = Util.EnvironmentTickCount() + 15000; // delay it + // m_reprioritizationBusy = false; - //m_log.DebugFormat("[CompleteMovement] SendInitialDataToMe: {0}ms", Util.EnvironmentTickCountSubtract(ts)); + //m_log.DebugFormat("[CompleteMovement] SendInitialDataToMe: {0}ms", Util.EnvironmentTickCountSubtract(ts)); - if (!IsChildAgent && openChildAgents) - { - IFriendsModule friendsModule = m_scene.RequestModuleInterface(); - if (friendsModule != null) + if (openChildAgents) { - if(gotCrossUpdate) - friendsModule.IsNowRoot(this); - else - friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); + IFriendsModule friendsModule = m_scene.RequestModuleInterface(); + if (friendsModule != null) + { + if(gotCrossUpdate) + friendsModule.IsNowRoot(this); + else + friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); + } + //m_log.DebugFormat("[CompleteMovement] friendsModule: {0}ms", Util.EnvironmentTickCountSubtract(ts)); } - //m_log.DebugFormat("[CompleteMovement] friendsModule: {0}ms", Util.EnvironmentTickCountSubtract(ts)); - } } finally @@ -4024,10 +4021,100 @@ namespace OpenSim.Region.Framework.Scenes ControllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations); } + + public void RegionHandShakeReply (IClientAPI client, uint flags) + { + if(IsNPC) + return; + + bool selfappearance = (flags & 4) != 0; + bool cacheCulling = (flags & 1) != 0; + bool cacheEmpty; + if(cacheCulling) + cacheEmpty = (flags & 2) != 0; + else + cacheEmpty = true; + + if (m_teleportFlags > 0) // only doing for child for now + return; + + lock (m_completeMovementLock) + { + if (SentInitialData) + return; + SentInitialData = true; + } + + Util.FireAndForget(delegate + { + Scene.SendLayerData(ControllingClient); + + ILandChannel landch = m_scene.LandChannel; + if (landch != null) + landch.sendClientInitialLandInfo(ControllingClient, true); + + // recheck to reduce timing issues + ControllingClient.CheckViewerCaps(); + + SendOtherAgentsAvatarFullToMe(); + /* + if (m_scene.ObjectsCullingByDistance && cacheCulling) + { + m_reprioritizationBusy = true; + m_reprioritizationLastPosition = AbsolutePosition; + m_reprioritizationLastDrawDistance = DrawDistance; + + ControllingClient.ReprioritizeUpdates(); + m_reprioritizationLastTime = Util.EnvironmentTickCount(); + m_reprioritizationBusy = false; + return; + } + */ + + EntityBase[] entities = Scene.Entities.GetEntities(); + if(cacheEmpty) + { + foreach (EntityBase e in entities) + { + if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment) + ((SceneObjectGroup)e).SendFullAnimUpdateToClient(ControllingClient); + } + } + else + { + foreach (EntityBase e in entities) + { + if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment) + { + SceneObjectGroup grp = e as SceneObjectGroup; + if(grp.IsViewerCachable) + grp.SendUpdateProbes(ControllingClient); + else + grp.SendFullAnimUpdateToClient(ControllingClient); + } + } + } + + m_reprioritizationLastPosition = AbsolutePosition; + m_reprioritizationLastDrawDistance = DrawDistance; + m_reprioritizationLastTime = Util.EnvironmentTickCount() + 15000; // delay it + + m_reprioritizationBusy = false; + + }); + + } + public void SendInitialDataToMe() { // Send all scene object to the new client - SentInitialData = true; + lock (m_completeMovementLock) + { + if (SentInitialData) + return; + SentInitialData = true; + } + Util.FireAndForget(delegate { // we created a new ScenePresence (a new child agent) in a fresh region. @@ -4280,7 +4367,13 @@ namespace OpenSim.Region.Framework.Scenes if(IsDeleted || !ControllingClient.IsActive) return; - if(!SentInitialData) + bool needsendinitial = false; + lock(m_completeMovementLock) + { + needsendinitial = SentInitialData; + } + + if(!needsendinitial) { SendInitialDataToMe(); return; diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 59ce05a6a9..80baf82dbc 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -699,7 +699,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public event TeleportCancel OnTeleportCancel; public event DeRezObject OnDeRezObject; public event RezRestoreToWorld OnRezRestoreToWorld; - public event Action OnRegionHandShakeReply; + public event Action OnRegionHandShakeReply; public event GenericCall1 OnRequestWearables; public event Action OnCompleteMovementToRegion; public event UpdateAgent OnPreAgentUpdate; @@ -938,7 +938,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server if (OnRegionHandShakeReply != null) { - OnRegionHandShakeReply(this); + OnRegionHandShakeReply(this, 0); } if (OnCompleteMovementToRegion != null) diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 09f2a58873..a7ed7d14d5 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -319,7 +319,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC public event DeRezObject OnDeRezObject; public event RezRestoreToWorld OnRezRestoreToWorld; - public event Action OnRegionHandShakeReply; + public event Action OnRegionHandShakeReply; public event GenericCall1 OnRequestWearables; public event Action OnCompleteMovementToRegion; public event UpdateAgent OnPreAgentUpdate; @@ -928,7 +928,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC { if (OnRegionHandShakeReply != null) { - OnRegionHandShakeReply(this); + OnRegionHandShakeReply(this, 0); } } diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index bc6cb60ccd..4fe2684c9a 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -119,7 +119,7 @@ namespace OpenSim.Tests.Common public event DeRezObject OnDeRezObject; public event RezRestoreToWorld OnRezRestoreToWorld; - public event Action OnRegionHandShakeReply; + public event Action OnRegionHandShakeReply; public event GenericCall1 OnRequestWearables; public event Action OnCompleteMovementToRegion; public event UpdateAgent OnPreAgentUpdate; @@ -880,7 +880,7 @@ namespace OpenSim.Tests.Common { if (OnRegionHandShakeReply != null) { - OnRegionHandShakeReply(this); + OnRegionHandShakeReply(this, 0); } }