diff --git a/OpenSim/Framework/PriorityQueue.cs b/OpenSim/Framework/PriorityQueue.cs index d6c39a78b1..4f05f6540a 100644 --- a/OpenSim/Framework/PriorityQueue.cs +++ b/OpenSim/Framework/PriorityQueue.cs @@ -134,6 +134,21 @@ namespace OpenSim.Framework return true; } + + public void Remove(List ids) + { + LookupItem lookup; + + foreach (uint localid in ids) + { + if (m_lookupTable.TryGetValue(localid, out lookup)) + { + lookup.Heap.Remove(lookup.Handle); + m_lookupTable.Remove(localid); + } + } + } + /// /// Remove an item from one of the queues. Specifically, it removes the /// oldest item from the next queue in order to provide fair access to diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 06f13015e3..e19877c690 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1660,6 +1660,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP // foreach (uint id in localIDs) // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle); + // remove pending entities + lock (m_entityProps.SyncRoot) + m_entityProps.Remove(localIDs); + lock (m_entityUpdates.SyncRoot) + m_entityUpdates.Remove(localIDs); + KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); // TODO: don't create new blocks if recycling an old packet kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count]; @@ -1671,28 +1677,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP kill.Header.Reliable = true; kill.Header.Zerocoded = true; - if (localIDs.Count == 1 && m_scene.GetScenePresence(localIDs[0]) != null) - { - OutPacket(kill, ThrottleOutPacketType.Task); - } - else - { - // We MUST lock for both manipulating the kill record and sending the packet, in order to avoid a race - // condition where a kill can be processed before an out-of-date update for the same object. - // ProcessEntityUpdates() also takes the m_killRecord lock. -// lock (m_killRecord) -// { -// foreach (uint localID in localIDs) -// m_killRecord.Add(localID); - - // The throttle queue used here must match that being used for updates. Otherwise, there is a - // chance that a kill packet put on a separate queue will be sent to the client before an existing - // update packet on another queue. Receiving updates after kills results in unowned and undeletable - // scene objects in a viewer until that viewer is relogged in. - OutPacket(kill, ThrottleOutPacketType.Task); -// } - } - } + OutPacket(kill, ThrottleOutPacketType.Task); + } /// /// Send information about the items contained in a folder to the client. @@ -5328,13 +5314,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP Vector3 velocity = new Vector3(0, 0, 0); Vector3 acceleration = new Vector3(0, 0, 0); rotation.Normalize(); - Vector3 vrot = new Vector3(rotation.X, rotation.Y, rotation.Z); data.CollisionPlane.ToBytes(objectData, 0); offsetPosition.ToBytes(objectData, 16); velocity.ToBytes(objectData, 28); acceleration.ToBytes(objectData, 40); - vrot.ToBytes(objectData, 52); + rotation.ToBytes(objectData, 52); data.AngularVelocity.ToBytes(objectData, 64); ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); @@ -5394,8 +5379,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Quaternion rotation = data.RotationOffset; rotation.Normalize(); - Vector3 vrot = new Vector3(rotation.X, rotation.Y, rotation.Z); - vrot.ToBytes(objectData, 36); + rotation.ToBytes(objectData, 36); data.AngularVelocity.ToBytes(objectData, 48); ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index d5eca03f09..37aae0893a 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -981,10 +981,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // May need to logout or other cleanup // AgentHasMovedAway(sp, logout); - AgentHasMovedAway(sp, true); // until logout use is checked +// AgentHasMovedAway(sp, true); // until logout use is checked // Well, this is it. The agent is over there. - KillEntity(sp.Scene, sp.LocalId); +// KillEntity(sp.Scene, sp.LocalId); + + sp.HasMovedAway(); // Now let's make it officially a child agent sp.MakeChildAgent(); @@ -1139,6 +1141,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); + sp.HasMovedAway(); + // Need to signal neighbours whether child agents may need closing irrespective of whether this // one needed closing. We also need to close child agents as quickly as possible to avoid complicated // race conditions with rapid agent releporting (e.g. from A1 to a non-neighbour B, back @@ -1147,12 +1151,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // abandoned without proper close by viewer but then re-used by an incoming connection. sp.CloseChildAgents(newRegionX, newRegionY); - // May need to logout or other cleanup -// AgentHasMovedAway(sp, logout); - AgentHasMovedAway(sp, true); - +// AgentHasMovedAway(sp, true); // Well, this is it. The agent is over there. - KillEntity(sp.Scene, sp.LocalId); +// KillEntity(sp.Scene, sp.LocalId); // Now let's make it officially a child agent sp.MakeChildAgent(); diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 668087f6b3..fdadd32726 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -576,6 +576,16 @@ namespace OpenSim.Region.Framework.Scenes.Animation m_scenePresence.SendAnimPack(animations, seqs, objectIDs); } + public void GetArrays(out UUID[] animIDs, out int[] sequenceNums, out UUID[] objectIDs) + { + animIDs = null; + sequenceNums = null; + objectIDs = null; + + if(m_animations != null) + m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); + } + public void SendAnimPackToClient(IClientAPI client) { if (m_scenePresence.IsChildAgent) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 0266faf821..aa81000cef 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3000,13 +3000,18 @@ namespace OpenSim.Region.Framework.Scenes if (sp == null) { m_log.DebugFormat( - "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", - client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); + "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}, tpflags: {4}", + client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos, + ((TPFlags)aCircuit.teleportFlags).ToString()); m_clientManager.Add(client); SubscribeToClientEvents(client); sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); + + sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; + +/* done in completMovement InventoryFolderBase cof = InventoryService.GetFolderForType(client.AgentId, (AssetType)46); if (cof == null) sp.COF = UUID.Zero; @@ -3014,9 +3019,9 @@ namespace OpenSim.Region.Framework.Scenes sp.COF = cof.ID; m_log.DebugFormat("[SCENE]: COF for {0} is {1}", client.AgentId, sp.COF); + */ m_eventManager.TriggerOnNewPresence(sp); - sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; } else { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 28758a9e13..d3dd5d71dd 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2636,6 +2636,16 @@ namespace OpenSim.Region.Framework.Scenes m_rootPart.UpdateFlag = UpdateRequired.TERSE; } + if (IsAttachment) + { + ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar); + if (sp != null) + { + sp.SendAttachmentScheduleUpdate(this); + return; + } + } + SceneObjectPart[] parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) { @@ -2697,15 +2707,25 @@ namespace OpenSim.Region.Framework.Scenes return; // m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); - - RootPart.SendFullUpdateToAllClients(); + + if (IsAttachment) + { + ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar); + if (sp != null) + { + sp.SendAttachmentUpdate(this,UpdateRequired.FULL); + return; + } + } + + RootPart.SendFullUpdateToAllClientsInternal(); SceneObjectPart[] parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) { SceneObjectPart part = parts[i]; if (part != RootPart) - part.SendFullUpdateToAllClients(); + part.SendFullUpdateToAllClientsInternal(); } } @@ -2739,9 +2759,19 @@ namespace OpenSim.Region.Framework.Scenes if (IsDeleted) return; + if (IsAttachment) + { + ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar); + if (sp != null) + { + sp.SendAttachmentUpdate(this, UpdateRequired.TERSE); + return; + } + } + SceneObjectPart[] parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) - parts[i].SendTerseUpdateToAllClients(); + parts[i].SendTerseUpdateToAllClientsInternal(); } /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 98ea880355..6fbe732cda 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -862,7 +862,8 @@ namespace OpenSim.Region.Framework.Scenes { Vector3 offset = (m_offsetPosition - oldpos); av.AbsolutePosition += offset; - av.SendAvatarDataToAllAgents(); +// av.SendAvatarDataToAllAgents(); + av.SendTerseUpdateToAllClients(); } } } @@ -3236,7 +3237,19 @@ namespace OpenSim.Region.Framework.Scenes // 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, UpdateRequired.FULL); + } + } + +/* this does nothing +SendFullUpdateToClient(remoteClient, Position) ignores position parameter if (IsRoot) { if (ParentGroup.IsAttachment) @@ -3248,6 +3261,7 @@ namespace OpenSim.Region.Framework.Scenes SendFullUpdateToClient(remoteClient, AbsolutePosition); } } +*/ else { SendFullUpdateToClient(remoteClient); @@ -3257,7 +3271,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// Send a full update for this part to all clients. /// - public void SendFullUpdateToAllClients() + public void SendFullUpdateToAllClientsInternal() { if (ParentGroup == null) return; @@ -3276,6 +3290,36 @@ namespace OpenSim.Region.Framework.Scenes }); } + public void SendFullUpdateToAllClients() + { + if (ParentGroup == null) + return; + + // Update the "last" values + m_lastPosition = OffsetPosition; + m_lastRotation = RotationOffset; + m_lastVelocity = Velocity; + m_lastAcceleration = Acceleration; + m_lastAngularVelocity = AngularVelocity; + m_lastUpdateSentTime = Environment.TickCount; + + if (ParentGroup.IsAttachment) + { + ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar); + if (sp != null) + { + sp.SendAttachmentUpdate(this, UpdateRequired.FULL); + } + } + else + { + ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) + { + SendFullUpdate(avatar.ControllingClient); + }); + } + } + /// /// Sends a full update to the client /// @@ -3345,24 +3389,24 @@ namespace OpenSim.Region.Framework.Scenes !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || Environment.TickCount - m_lastUpdateSentTime > TIME_MS_TOLERANCE) { - SendTerseUpdateToAllClients(); - + SendTerseUpdateToAllClientsInternal(); } break; } case UpdateRequired.FULL: { ClearUpdateSchedule(); - SendFullUpdateToAllClients(); + SendFullUpdateToAllClientsInternal(); break; } } } + /// /// Send a terse update to all clients /// - public void SendTerseUpdateToAllClients() + public void SendTerseUpdateToAllClientsInternal() { if (ParentGroup == null || ParentGroup.Scene == null) return; @@ -3381,6 +3425,36 @@ namespace OpenSim.Region.Framework.Scenes }); } + public void SendTerseUpdateToAllClients() + { + if (ParentGroup == null || ParentGroup.Scene == null) + return; + + // Update the "last" values + m_lastPosition = OffsetPosition; + m_lastRotation = RotationOffset; + m_lastVelocity = Velocity; + m_lastAcceleration = Acceleration; + m_lastAngularVelocity = AngularVelocity; + m_lastUpdateSentTime = Environment.TickCount; + + if (ParentGroup.IsAttachment) + { + ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar); + if (sp != null) + { + sp.SendAttachmentUpdate(this, UpdateRequired.TERSE); + } + } + else + { + ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) + { + SendTerseUpdateToClient(client); + }); + } + } + public void SetAxisRotation(int axis, int rotate) { ParentGroup.SetAxisRotation(axis, rotate); diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 73283ed270..4fa95fddba 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1268,79 +1268,6 @@ namespace OpenSim.Region.Framework.Scenes m_scene.SwapRootAgentCount(false); - // The initial login scene presence is already root when it gets here - // and it has already rezzed the attachments and started their scripts. - // We do the following only for non-login agents, because their scripts - // haven't started yet. -/* moved down - if (PresenceType == PresenceType.Npc || (TeleportFlags & TeleportFlags.ViaLogin) != 0) - { - // Viewers which have a current outfit folder will actually rez their own attachments. However, - // viewers without (e.g. v1 viewers) will not, so we still need to make this call. - if (Scene.AttachmentsModule != null) - Util.FireAndForget( - o => - { -// if (PresenceType != PresenceType.Npc && Util.FireAndForgetMethod != FireAndForgetMethod.None) -// System.Threading.Thread.Sleep(7000); - - Scene.AttachmentsModule.RezAttachments(this); - }); - } - else - - { - // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT - // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently - // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are - // not transporting the required data. - // - // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT - // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently - // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are - // not transporting the required data. - // - // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of - // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here - // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status. - // - // FIXME: In theory, this deadlock should not arise since scripts should not be processing events until ResumeScripts(). - // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing - // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the - // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine. - // - // One cannot simply iterate over attachments in a fire and forget thread because this would no longer - // be locked, allowing race conditions if other code changes the attachments list. - - List attachments = GetAttachments(); - - if (attachments.Count > 0) - { - m_log.DebugFormat( - "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); - - // Resume scripts this possible should also be moved down after sending the avatar to viewer ? - foreach (SceneObjectGroup sog in attachments) - { -// sending attachments before the avatar ? -// moved to completemovement where it already was -// sog.ScheduleGroupForFullUpdate(); - sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); - sog.ResumeScripts(); - } - } - } -*/ -/* - SendAvatarDataToAllAgents(); - - // send the animations of the other presences to me - m_scene.ForEachRootScenePresence(delegate(ScenePresence presence) - { - if (presence != this) - presence.Animator.SendAnimPackToClient(ControllingClient); - }); -*/ // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will // stall on the border crossing since the existing child agent will still have the last movement @@ -1414,6 +1341,11 @@ namespace OpenSim.Region.Framework.Scenes RemoveFromPhysicalScene(); ParentID = 0; // Child agents can't be sitting +// we dont have land information for child + m_previusParcelHide = false; + m_previusParcelUUID = UUID.Zero; + m_currentParcelHide = false; + m_currentParcelUUID = UUID.Zero; // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into m_scene.EventManager.TriggerOnMakeChildAgent(this); @@ -1826,13 +1758,6 @@ namespace OpenSim.Region.Framework.Scenes // Tell the client that we're totally ready ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); - // Remember in HandleUseCircuitCode, we delayed this to here -// this prims etc, moved down -// if (m_teleportFlags > 0) -// SendInitialDataToMe(); - - // m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); - m_log.DebugFormat("[CompleteMovement] MoveAgentIntoRegion: {0}ms", Util.EnvironmentTickCountSubtract(ts)); if (!string.IsNullOrEmpty(m_callbackURI)) @@ -1878,19 +1803,82 @@ namespace OpenSim.Region.Framework.Scenes if (!IsChildAgent) { - ValidateAndSendAppearanceAndAgentData(); + // ValidateAndSendAppearanceAndAgentData(); + + // do it here in line + // so sequence is clear + + // verify baked textures and cache + + bool cachedbaked = false; + + if (m_scene.AvatarFactory != null) + cachedbaked = m_scene.AvatarFactory.ValidateBakedTextureCache(this); + + // not sure we need this + if (!cachedbaked) + { + if (m_scene.AvatarFactory != null) + m_scene.AvatarFactory.QueueAppearanceSave(UUID); + } + + 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.GodLevel < 200) + 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 || (TeleportFlags & TeleportFlags.ViaLogin) != 0) { if (Scene.AttachmentsModule != null) -// Util.FireAndForget( -// o => -// { + // Util.FireAndForget( + // o => + // { Scene.AttachmentsModule.RezAttachments(this); - // }); + // }); } else { @@ -1902,26 +1890,24 @@ namespace OpenSim.Region.Framework.Scenes // Resume scripts this possible should also be moved down after sending the avatar to viewer ? foreach (SceneObjectGroup sog in m_attachments) { - sog.SendFullUpdateToClient(ControllingClient); SendFullUpdateToClient(ControllingClient); + SendAttachmentFullUpdateToAgentNF(sog, this); if (!sog.HasPrivateAttachmentPoint) { // sog.ScheduleGroupForFullUpdate(); - m_scene.ForEachScenePresence(delegate(ScenePresence p) + foreach(ScenePresence p in allpresences) { if (p == this) - return; + continue; if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) - return; + continue; - p.ControllingClient.SendPartFullUpdate(sog.RootPart,LocalId + 1); - sog.SendFullUpdateToClient(p.ControllingClient); SendFullUpdateToClient(p.ControllingClient); // resend our data by updates path - }); + SendAttachmentFullUpdateToAgentNF(sog, p); + }; } - sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); sog.ResumeScripts(); } @@ -1947,25 +1933,14 @@ namespace OpenSim.Region.Framework.Scenes m_log.DebugFormat("[CompleteMovement] SendInitialDataToMe: {0}ms", Util.EnvironmentTickCountSubtract(ts)); - if (!IsChildAgent) + if (!IsChildAgent && openChildAgents) { -// moved from makeroot missing in sendInitialDataToMe -// its already there -/* - m_scene.ForEachRootScenePresence(delegate(ScenePresence presence) - { - if (presence != this) - presence.Animator.SendAnimPackToClient(ControllingClient); - }); -*/ - if (openChildAgents) - { IFriendsModule friendsModule = m_scene.RequestModuleInterface(); if (friendsModule != null) friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); m_log.DebugFormat("[CompleteMovement] friendsModule: {0}ms", Util.EnvironmentTickCountSubtract(ts)); - } + } } finally @@ -3543,14 +3518,12 @@ namespace OpenSim.Region.Framework.Scenes } SendOtherAgentsAvatarFullToMe(); - EntityBase[] entities = Scene.Entities.GetEntities(); foreach (EntityBase e in entities) { - if (e != null && e is SceneObjectGroup) + if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment) ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); } - }); } @@ -3558,6 +3531,8 @@ namespace OpenSim.Region.Framework.Scenes /// Do everything required once a client completes its movement into a region and becomes /// a root agent. /// + /// +/* only called from on place, do done inline there private void ValidateAndSendAppearanceAndAgentData() { //m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID); @@ -3579,11 +3554,13 @@ namespace OpenSim.Region.Framework.Scenes m_scene.AvatarFactory.QueueAppearanceSave(UUID); } + // send avatar object to all viewers so they cross it into region bool newhide = m_currentParcelHide; m_currentParcelHide = false; SendAvatarDataToAllAgents(); + // now hide if (newhide) { ParcelLoginCheck(m_currentParcelUUID); @@ -3592,14 +3569,14 @@ namespace OpenSim.Region.Framework.Scenes SendAppearanceToAgent(this); -// if (cachedappearance) -// { + m_inTransit = false; + SendAppearanceToAllOtherAgents(); -// } + if(Animator!= null) Animator.SendAnimPack(); } - +*/ /// /// Send avatar full data appearance and animations for all other root agents to this agent, this agent /// can be either a child or root @@ -3607,16 +3584,21 @@ namespace OpenSim.Region.Framework.Scenes public void SendOtherAgentsAvatarFullToMe() { int count = 0; - m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence) + m_scene.ForEachRootScenePresence(delegate(ScenePresence p) { // only send information about other root agents - if (scenePresence.UUID == UUID) + if (p.UUID == UUID) return; - scenePresence.SendAvatarDataToAgent(this); - scenePresence.SendAppearanceToAgent(this); - scenePresence.SendAnimPackToAgent(this); - // for now attachments are sent with all SOG + // get the avatar, then a kill if can't see it + p.SendInitialAvatarDataToAgent(this); + + if (p.ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && GodLevel < 200) + return; + + p.SendAppearanceToAgentNF(this); + p.SendAnimPackToAgentNF(this); + p.SendAttachmentsToAgentNF(this); count++; }); @@ -3636,7 +3618,6 @@ namespace OpenSim.Region.Framework.Scenes m_log.WarnFormat( "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}", Name, Scene.RegionInfo.RegionName); - return; } @@ -3652,6 +3633,36 @@ namespace OpenSim.Region.Framework.Scenes m_scene.StatsReporter.AddAgentUpdates(count); } + // sends avatar object to all clients so they cross it into region + // then sends kills to hide + public void SendInitialAvatarDataToAllAgents(List presences) + { + m_lastSize = Appearance.AvatarSize; + int count = 0; + + foreach (ScenePresence p in presences) + { + p.ControllingClient.SendAvatarDataImmediate(this); + if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) + // either just kill the object + // p.ControllingClient.SendKillObject(new List {LocalId}); + // or also attachments viewer may still know about + SendKillTo(p); + count++; + } + m_scene.StatsReporter.AddAgentUpdates(count); + } + + public void SendInitialAvatarDataToAgent(ScenePresence p) + { + p.ControllingClient.SendAvatarDataImmediate(this); + if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) + // either just kill the object + // p.ControllingClient.SendKillObject(new List {LocalId}); + // or also attachments viewer may still know about + SendKillTo(p); + } + /// /// Send avatar data to an agent. /// @@ -3666,9 +3677,9 @@ namespace OpenSim.Region.Framework.Scenes public void SendAvatarDataToAgentNF(ScenePresence avatar) { - avatar.ControllingClient.SendAvatarDataImmediate(this); + avatar.ControllingClient.SendAvatarDataImmediate(this); } - + /// /// Send this agent's appearance to all other root and child agents in the scene /// This agent must be root. @@ -3714,6 +3725,12 @@ namespace OpenSim.Region.Framework.Scenes UUID, Appearance.VisualParams, Appearance.Texture.GetBytes()); } + public void SendAppearanceToAgentNF(ScenePresence avatar) + { + avatar.ControllingClient.SendAppearance( + UUID, Appearance.VisualParams, Appearance.Texture.GetBytes()); + } + public void SendAnimPackToAgent(ScenePresence p) { if (IsChildAgent || Animator == null) @@ -3725,6 +3742,29 @@ namespace OpenSim.Region.Framework.Scenes Animator.SendAnimPackToClient(p.ControllingClient); } + public void SendAnimPackToAgent(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs) + { + if (IsChildAgent) + return; + + if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) + return; + + p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs); + } + + public void SendAnimPackToAgentNF(ScenePresence p) + { + if (IsChildAgent || Animator == null) + return; + Animator.SendAnimPackToClient(p.ControllingClient); + } + + public void SendAnimPackToAgentNF(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs) + { + p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs); + } + public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs) { if (IsChildAgent) @@ -4136,19 +4176,7 @@ namespace OpenSim.Region.Framework.Scenes cAgent.Far = DrawDistance; // Throttles - float multiplier = 1; - -/* this is also used to send to new main regions not children - - int childRegions = KnownRegionCount; - if (childRegions != 0) - multiplier = 1f / childRegions; - - // Minimum throttle for a child region is 1/4 of the root region throttle - if (multiplier <= 0.25f) - multiplier = 0.25f; -*/ - cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier); + cAgent.Throttles = ControllingClient.GetThrottlesPacked(1); cAgent.HeadRotation = m_headrotation; cAgent.BodyRotation = Rotation; @@ -4729,9 +4757,11 @@ namespace OpenSim.Region.Framework.Scenes { if (p != this && sog.HasPrivateAttachmentPoint) return; + if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) return; - sog.SendFullUpdateToClient(p.ControllingClient); + + SendAttachmentFullUpdateToAgentNF(sog, p); SendFullUpdateToClient(p.ControllingClient); // resend our data by updates path }); } @@ -4746,163 +4776,235 @@ namespace OpenSim.Region.Framework.Scenes { foreach (SceneObjectGroup sog in m_attachments) { - if (p == this || !sog.HasPrivateAttachmentPoint) - { - p.ControllingClient.SendPartFullUpdate(sog.RootPart, LocalId + 1); - sog.SendFullUpdateToClient(p.ControllingClient); - } + SendAttachmentFullUpdateToAgentNF(sog, p); } SendFullUpdateToClient(p.ControllingClient); // resend our data by updates path } } - // send attachments to a client without filters except for huds - // for now they are checked in several places down the line... - // kills all parts before sending - public void SendAttachmentsToAgentNFPK(ScenePresence p) + public void SendAttachmentFullUpdateToAgentNF(SceneObjectGroup sog, ScenePresence p) { - lock (m_attachments) + if (p != this && sog.HasPrivateAttachmentPoint) + return; + + SceneObjectPart[] parts = sog.Parts; + SceneObjectPart rootpart = sog.RootPart; + + p.ControllingClient.SendEntityUpdate(rootpart, PrimUpdateFlags.FullUpdate); + + for (int i = 0; i < parts.Length; i++) { - List pk = new List(); - foreach (SceneObjectGroup sog in m_attachments) - { - foreach (SceneObjectPart part in sog.Parts) - pk.Add(part.LocalId); - } - - p.ControllingClient.SendKillObject(pk); - - foreach (SceneObjectGroup sog in m_attachments) - { - if (p == this || !sog.HasPrivateAttachmentPoint) - sog.SendFullUpdateToClient(p.ControllingClient); - } - SendFullUpdateToClient(p.ControllingClient); // resend our data by updates path + SceneObjectPart part = parts[i]; + if (part == rootpart) + continue; + p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate); } } - public void SendAttachmentScheduleUpdate(SceneObjectGroup sog) { - if (IsChildAgent) + if (IsChildAgent || IsInTransit) return; - m_scene.ForEachScenePresence(delegate(ScenePresence p) + SceneObjectPart[] origparts = sog.Parts; + SceneObjectPart[] parts = new SceneObjectPart[origparts.Length]; + PrimUpdateFlags[] flags = new PrimUpdateFlags[origparts.Length]; + + SceneObjectPart rootpart = sog.RootPart; + UpdateRequired rootreq = sog.RootPart.UpdateFlag; + + int j = 0; + bool allterse = true; + + for (int i = 0; i < origparts.Length; i++) { - if (p != this && sog.HasPrivateAttachmentPoint) - return; - if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) - return; + switch (origparts[i].UpdateFlag) + { + case UpdateRequired.TERSE: + flags[j] = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity + | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; + parts[j] = origparts[i]; + j++; + break; - SceneObjectPart[] parts = sog.Parts; + case UpdateRequired.FULL: + flags[j] = PrimUpdateFlags.FullUpdate; + parts[j] = origparts[i]; + j++; + allterse = false; + break; + } + origparts[i].UpdateFlag = 0; + } - for (int i = 0; i < parts.Length; i++) + if (j == 0) + return; + + if (rootreq == UpdateRequired.NONE) + { + if (allterse) + rootreq = UpdateRequired.TERSE; + else + rootreq = UpdateRequired.FULL; + } + + PrimUpdateFlags rootflag = PrimUpdateFlags.FullUpdate; + if (rootreq == UpdateRequired.TERSE) + rootflag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity + | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; + + int nparts = j; + + bool priv = sog.HasPrivateAttachmentPoint; + + List allPresences = m_scene.GetScenePresences(); + foreach (ScenePresence p in allPresences) + { + if (p != this) + { + if (priv || + (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)) + continue; + } + + p.ControllingClient.SendEntityUpdate(rootpart, rootflag); + + for (int i = 0; i < nparts; i++) { SceneObjectPart part = parts[i]; - if (part.UpdateFlag == UpdateRequired.TERSE) - { - p.ControllingClient.SendEntityUpdate(part, - PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity - | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); - part.UpdateFlag = 0; - } - else if (part.UpdateFlag == UpdateRequired.FULL) - { - p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate); - part.UpdateFlag = 0; - } + if (part == rootpart) + continue; + p.ControllingClient.SendEntityUpdate(part, flags[i]); } - }); - } - - public void SendAttachmentScheduleUpdate(SceneObjectPart part) - { - if (IsChildAgent) - return; - - m_scene.ForEachScenePresence(delegate(ScenePresence p) - { - if (p != this && part.ParentGroup.HasPrivateAttachmentPoint) - return; - - if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) - return; - - if (part.UpdateFlag == UpdateRequired.TERSE) - { - p.ControllingClient.SendEntityUpdate(part, - PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity - | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); - part.UpdateFlag = 0; - } - else if (part.UpdateFlag == UpdateRequired.FULL) - { - p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate); - part.UpdateFlag = 0; - } - }); + } } public void SendAttachmentUpdate(SceneObjectGroup sog, UpdateRequired UpdateFlag) { - if (IsChildAgent) + if (IsChildAgent || IsInTransit) return; - m_scene.ForEachScenePresence(delegate(ScenePresence p) + PrimUpdateFlags flag; + switch (UpdateFlag) { - if (p != this && sog.HasPrivateAttachmentPoint) - return; + case UpdateRequired.TERSE: + flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity + | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; + break; - if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) - return; + case UpdateRequired.FULL: + flag = PrimUpdateFlags.FullUpdate; + break; - SceneObjectPart[] parts = sog.Parts; + default: + return; + } + + SceneObjectPart[] parts = sog.Parts; + SceneObjectPart rootpart = sog.RootPart; + + bool priv = sog.HasPrivateAttachmentPoint; + + List allPresences = m_scene.GetScenePresences(); + foreach (ScenePresence p in allPresences) + { + if (p != this) + { + if (priv || + (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)) + continue; + } + + p.ControllingClient.SendEntityUpdate(rootpart, flag); + rootpart.UpdateFlag = 0; for (int i = 0; i < parts.Length; i++) { SceneObjectPart part = parts[i]; - if (UpdateFlag == UpdateRequired.TERSE) - { - p.ControllingClient.SendEntityUpdate(part, - PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity - | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); - part.UpdateFlag = 0; - } - else if (UpdateFlag == UpdateRequired.FULL) - { - p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate); - part.UpdateFlag = 0; - } + if (part == rootpart) + continue; + p.ControllingClient.SendEntityUpdate(part, flag); + part.UpdateFlag = 0; } - }); + } + } + + public void SendAttachmentScheduleUpdate(SceneObjectPart part) + { + 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; + } + + bool priv = part.ParentGroup.HasPrivateAttachmentPoint; + + List allPresences = m_scene.GetScenePresences(); + foreach (ScenePresence p in allPresences) + { + if (p != this) + { + + if (priv || + (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)) + continue; + } + + p.ControllingClient.SendEntityUpdate(part, flag); + part.UpdateFlag = 0; + } } public void SendAttachmentUpdate(SceneObjectPart part, UpdateRequired UpdateFlag) { - if (IsChildAgent) + if (IsChildAgent || IsInTransit) return; - m_scene.ForEachScenePresence(delegate(ScenePresence p) + PrimUpdateFlags flag; + switch (UpdateFlag) { - if (p != this && part.ParentGroup.HasPrivateAttachmentPoint) - return; + case UpdateRequired.TERSE: + flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity + | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; + break; - if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200) - return; + case UpdateRequired.FULL: + flag = PrimUpdateFlags.FullUpdate; + break; - if (UpdateFlag == UpdateRequired.TERSE) + default: + return; + } + + bool priv = part.ParentGroup.HasPrivateAttachmentPoint; + + List allPresences = m_scene.GetScenePresences(); + foreach (ScenePresence p in allPresences) + { + if (p != this) { - p.ControllingClient.SendEntityUpdate(part, - PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity - | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); - part.UpdateFlag = 0; + if ( priv || + (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)) + continue; } - else if (UpdateFlag == UpdateRequired.FULL) - { - p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate); - part.UpdateFlag = 0; - } - }); + + p.ControllingClient.SendEntityUpdate(part, flag); + part.UpdateFlag = 0; + } } /// @@ -5650,153 +5752,23 @@ namespace OpenSim.Region.Framework.Scenes private void parcelGodCheck(UUID currentParcelID, bool isGod) { - List allpresences = null; - - - allpresences = m_scene.GetScenePresences(); - - if (isGod) - { - List viewsToSendme = new List(); - - foreach (ScenePresence p in allpresences) - { - if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) - continue; - - if (p.ParcelHideThisAvatar && p.currentParcelUUID != currentParcelID) - { - viewsToSendme.Add(p); // i see them - } - } - - if (viewsToSendme.Count > 0) - { - foreach (ScenePresence p in viewsToSendme) - { - if (p.IsChildAgent) - continue; - - p.SendAvatarDataToAgentNF(this); - p.SendAppearanceToAgent(this); - if (p.Animator != null) - p.Animator.SendAnimPackToClient(ControllingClient); - p.SendAttachmentsToAgentNF(this); - } - } - } - else - { - List killsToSendme = new List(); - - foreach (ScenePresence p in allpresences) - { - if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) - continue; - - if (p.ParcelHideThisAvatar && p.currentParcelUUID != currentParcelID) - { - killsToSendme.Add(p); - } - } - - if (killsToSendme.Count > 0) - { - foreach (ScenePresence p in killsToSendme) - { - m_log.Debug("[AVATAR]: killMe: " + Lastname + " " + p.Lastname); - try { ControllingClient.SendKillObject(new List { p.LocalId }); } - catch (NullReferenceException) { } - } - } - } - - } - - private void ParcelLoginCheck(UUID currentParcelID) - { - List killsToSendto = new List(); - List killsToSendme = new List(); - List viewsToSendto = new List(); - List viewsToSendme = new List(); - List allpresences = null; - - allpresences = m_scene.GetScenePresences(); + List allpresences = m_scene.GetScenePresences(); foreach (ScenePresence p in allpresences) { - if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) + if (p.IsDeleted || p.IsChildAgent || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) continue; - - if (currentParcelID != p.currentParcelUUID) - { - if (p.GodLevel < 200) - killsToSendto.Add(p); -// if (GodLevel < 200 && p.ParcelHideThisAvatar) -// killsToSendme.Add(p.LocalId); - } - else - { - viewsToSendto.Add(p); - viewsToSendme.Add(p); - } - } - allpresences.Clear(); - // send the things - // kill main avatar object - if (killsToSendto.Count > 0 && PresenceType != PresenceType.Npc) - { - foreach (ScenePresence p in killsToSendto) + if (p.ParcelHideThisAvatar && p.currentParcelUUID != currentParcelID) { - m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname); - try { p.ControllingClient.SendKillObject(new List { LocalId }); } - catch (NullReferenceException) { } + if (isGod) + p.SendViewTo(this); + else + p.SendKillTo(this); } } - - if (killsToSendme.Count > 0) - { - m_log.Debug("[AVATAR]: killMe: " + Lastname + " " + killsToSendme.Count.ToString()); - try - { - ControllingClient.SendKillObject(killsToSendme); - } - catch (NullReferenceException) { } - - } -/* - if (viewsToSendto.Count > 0 && PresenceType != PresenceType.Npc) - { - foreach (ScenePresence p in viewsToSendto) - { - m_log.Debug("[AVATAR]: viewTo: " + Lastname + " " + p.Lastname); - p.ControllingClient.SendAvatarDataImmediate(this); - SendAppearanceToAgent(p); - SendAttachmentsToClient(p.ControllingClient); - if (Animator != null) - Animator.SendAnimPackToClient(p.ControllingClient); - } - } - - if (viewsToSendme.Count > 0) - { - foreach (ScenePresence p in viewsToSendme) - { - m_log.Debug("[AVATAR]: viewMe: " + Lastname + "<-" + p.Lastname); - if (p.IsChildAgent) - continue; - ControllingClient.SendAvatarDataImmediate(p); - p.SendAppearanceToAgent(this); - p.SendAttachmentsToClient(ControllingClient); - if (p.Animator != null) - p.Animator.SendAnimPackToClient(ControllingClient); - } - } -*/ } - public void parcelRegionCross() { if (!ParcelHideThisAvatar || GodLevel >= 200) @@ -5805,42 +5777,28 @@ namespace OpenSim.Region.Framework.Scenes List allpresences = null; allpresences = m_scene.GetScenePresences(); - List killsToSendme = new List(); - foreach (ScenePresence p in allpresences) { - if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) + if (p.IsDeleted || p == this || p.IsChildAgent || p.ControllingClient == null || !p.ControllingClient.IsActive) continue; if (p.currentParcelUUID == m_currentParcelUUID) { - killsToSendme.Add(p.LocalId); + p.SendKillTo(this); } } - - if (killsToSendme.Count > 0) - { - try - { - ControllingClient.SendKillObject(killsToSendme); - } - catch (NullReferenceException) { } - } } private void ParcelCrossCheck(UUID currentParcelID,UUID previusParcelID, bool currentParcelHide, bool previusParcelHide, bool oldhide,bool check) { List killsToSendto = new List(); - List killsToSendme = new List(); + List killsToSendme = new List(); List viewsToSendto = new List(); List viewsToSendme = new List(); List allpresences = null; - if (IsInTransit) - return; - - if (IsChildAgent) + if (IsInTransit || IsChildAgent) return; if (check) @@ -5903,7 +5861,7 @@ namespace OpenSim.Region.Framework.Scenes if(p.GodLevel < 200) killsToSendto.Add(p); // they dont see me if(GodLevel < 200) - killsToSendme.Add(p.LocalId); // i dont see them + killsToSendme.Add(p); // i dont see them } // only those on new parcel need see if (currentParcelID == p.currentParcelUUID) @@ -5949,10 +5907,10 @@ namespace OpenSim.Region.Framework.Scenes { if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive) continue; - // only those old parcel need receive kills + // only those old parcel need kills if (previusParcelID == p.currentParcelUUID && GodLevel < 200) { - killsToSendme.Add(p.LocalId); // i dont see them + killsToSendme.Add(p); // i dont see them } else { @@ -5966,37 +5924,30 @@ namespace OpenSim.Region.Framework.Scenes } // send the things - // kill main avatar object - if (killsToSendto.Count > 0 && PresenceType != PresenceType.Npc) + + if (killsToSendto.Count > 0) { foreach (ScenePresence p in killsToSendto) { m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname); - try { p.ControllingClient.SendKillObject(new List { LocalId }); } - catch (NullReferenceException) { } + SendKillTo(p); } } if (killsToSendme.Count > 0) { - m_log.Debug("[AVATAR]: killtoMe: " + Lastname + " " + killsToSendme.Count.ToString()); - try + foreach (ScenePresence p in killsToSendme) { - ControllingClient.SendKillObject(killsToSendme); + m_log.Debug("[AVATAR]: killToMe: " + Lastname + " " + p.Lastname); + p.SendKillTo(this); } - catch (NullReferenceException) { } - } - if (viewsToSendto.Count > 0 && PresenceType != PresenceType.Npc) + if (viewsToSendto.Count > 0) { foreach (ScenePresence p in viewsToSendto) { - SendAvatarDataToAgentNF(p); - SendAppearanceToAgent(p); - if (Animator != null) - Animator.SendAnimPackToClient(p.ControllingClient); - SendAttachmentsToAgentNF(p); + SendViewTo(p); } } @@ -6007,14 +5958,55 @@ namespace OpenSim.Region.Framework.Scenes if (p.IsChildAgent) continue; // m_log.Debug("[AVATAR]: viewMe: " + Lastname + "<-" + p.Lastname); - - p.SendAvatarDataToAgentNF(this); - p.SendAppearanceToAgent(this); - if (p.Animator != null) - p.Animator.SendAnimPackToClient(ControllingClient); - p.SendAttachmentsToAgentNF(this); + p.SendViewTo(this); } } } + + public void HasMovedAway() + { + List allpresences = m_scene.GetScenePresences(); + foreach (ScenePresence p in allpresences) + { + if (p == this) + continue; + SendKillTo(p); + if (!p.IsChildAgent) + p.SendKillTo(this); + } + if (Scene.AttachmentsModule != null) + Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true); + } + +// kill with attachs root kills + public void SendKillTo(ScenePresence p) + { + List ids = new List(m_attachments.Count + 1); + foreach (SceneObjectGroup sog in m_attachments) + { + ids.Add(sog.RootPart.LocalId); + } + + ids.Add(LocalId); + p.ControllingClient.SendKillObject(ids); + } + +/* +// kill with hack + public void SendKillTo(ScenePresence p) + { + foreach (SceneObjectGroup sog in m_attachments) + p.ControllingClient.SendPartFullUpdate(sog.RootPart, LocalId + 1); + p.ControllingClient.SendKillObject(new List { LocalId }); + } +*/ + public void SendViewTo(ScenePresence p) + { + SendAvatarDataToAgentNF(p); + SendAppearanceToAgent(p); + if (Animator != null) + Animator.SendAnimPackToClient(p.ControllingClient); + SendAttachmentsToAgentNF(p); + } } }