diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index f16a8e6e2f..a2e4417df1 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -429,6 +429,12 @@ namespace OpenSim.Region.Framework.Scenes return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0)); } + private struct avtocrossInfo + { + public ScenePresence av; + public uint ParentID; + } + /// /// The absolute position of this scene object in the scene /// @@ -456,13 +462,124 @@ namespace OpenSim.Region.Framework.Scenes || Scene.TestBorderCross(val, Cardinals.S)) && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) { + IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface(); + uint x = 0; + uint y = 0; + string version = String.Empty; + Vector3 newpos = Vector3.Zero; + OpenSim.Services.Interfaces.GridRegion destination = null; + if (m_rootPart.KeyframeMotion != null) m_rootPart.KeyframeMotion.StartCrossingCheck(); - m_scene.CrossPrimGroupIntoNewRegion(val, this, true); + bool canCross = true; + foreach (ScenePresence av in m_linkedAvatars) + { + // We need to cross these agents. First, let's find + // out if any of them can't cross for some reason. + // We have to deny the crossing entirely if any + // of them are banned. Alternatively, we could + // unsit banned agents.... + + + // We set the avatar position as being the object + // position to get the region to send to + if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null) + { + canCross = false; + break; + } + + m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName); + } + + if (canCross) + { + // We unparent the SP quietly so that it won't + // be made to stand up + + List avsToCross = new List(); + + foreach (ScenePresence av in m_linkedAvatars) + { + avtocrossInfo avinfo = new avtocrossInfo(); + SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID); + if (parentPart != null) + av.ParentUUID = parentPart.UUID; + + avinfo.av = av; + avinfo.ParentID = av.ParentID; + avsToCross.Add(avinfo); + + av.PrevSitOffset = av.OffsetPosition; + av.ParentID = 0; + } + + // m_linkedAvatars.Clear(); + m_scene.CrossPrimGroupIntoNewRegion(val, this, true); + + // Normalize + if (val.X >= Constants.RegionSize) + val.X -= Constants.RegionSize; + if (val.Y >= Constants.RegionSize) + val.Y -= Constants.RegionSize; + if (val.X < 0) + val.X += Constants.RegionSize; + if (val.Y < 0) + val.Y += Constants.RegionSize; + + // If it's deleted, crossing was successful + if (IsDeleted) + { + // foreach (ScenePresence av in m_linkedAvatars) + foreach (avtocrossInfo avinfo in avsToCross) + { + ScenePresence av = avinfo.av; + if (!av.IsInTransit) // just in case... + { + m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val); + + av.IsInTransit = true; + + CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync; + d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d); + } + else + m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar alreasy in transit {0} to {1}", av.Name, val); + } + avsToCross.Clear(); + return; + } + else // cross failed, put avas back ?? + { + foreach (avtocrossInfo avinfo in avsToCross) + { + ScenePresence av = avinfo.av; + av.ParentUUID = UUID.Zero; + av.ParentID = avinfo.ParentID; +// m_linkedAvatars.Add(av); + } + } + avsToCross.Clear(); + + } + else + { + if (m_rootPart.KeyframeMotion != null) + m_rootPart.KeyframeMotion.CrossingFailure(); + + if (RootPart.PhysActor != null) + { + RootPart.PhysActor.CrossingFailure(); + } + } + Vector3 oldp = AbsolutePosition; + val.X = Util.Clamp(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f); + val.Y = Util.Clamp(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f); + val.Z = Util.Clamp(oldp.Z, 0.5f, 4096.0f); } } - + if (RootPart.GetStatusSandbox()) { if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) @@ -496,6 +613,39 @@ namespace OpenSim.Region.Framework.Scenes } } + public override Vector3 Velocity + { + get { return RootPart.Velocity; } + set { RootPart.Velocity = value; } + } + + private void CrossAgentToNewRegionCompleted(IAsyncResult iar) + { + CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState; + ScenePresence agent = icon.EndInvoke(iar); + + //// If the cross was successful, this agent is a child agent + if (agent.IsChildAgent) + { + if (agent.ParentUUID != UUID.Zero) + { + agent.ParentPart = null; +// agent.ParentPosition = Vector3.Zero; +// agent.ParentUUID = UUID.Zero; + } + } + + agent.ParentUUID = UUID.Zero; +// agent.Reset(); +// else // Not successful +// agent.RestoreInCurrentScene(); + + // In any case + agent.IsInTransit = false; + + m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); + } + public override uint LocalId { get { return m_rootPart.LocalId; }