From 4571e5bc3e284c916d1ae4dd6429b80a8028b8e0 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 24 Oct 2014 18:10:28 +0100 Subject: [PATCH] try to make SOG crossings full async. Simplify some borders checking.... --- .../ClientStack/Linden/UDP/LLClientView.cs | 2 +- .../EntityTransfer/EntityTransferModule.cs | 184 +++++++-- .../Interfaces/IEntityTransferModule.cs | 6 +- .../Framework/Scenes/SceneObjectGroup.cs | 371 ++++++++++-------- .../Region/Framework/Scenes/ScenePresence.cs | 146 ++++--- 5 files changed, 434 insertions(+), 275 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 6385aedd0f..6f429905d1 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3865,7 +3865,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { SceneObjectPart part = (SceneObjectPart)update.Entity; - if (part.ParentGroup.IsDeleted) + if (part.ParentGroup.IsDeleted || part.ParentGroup.inTransit) continue; if (part.ParentGroup.IsAttachment) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index c89894635c..b855233d03 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -1385,13 +1385,61 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer #region Agent Crossings - public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos) + + public bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position, out string version, out string reason) { - string r = String.Empty; - return GetDestination(scene, agentID, pos, out xDest, out yDest, out version, out newpos, out r); + reason = String.Empty; + version = String.Empty; + + UUID agentID = agent.UUID; + ulong destinyHandle = destiny.RegionHandle; + + ExpiringCache r; + DateTime banUntil; + if (m_bannedRegions.TryGetValue(agentID, out r)) + { + if (r.TryGetValue(destinyHandle, out banUntil)) + { + if (DateTime.Now < banUntil) + { + reason = "Cannot connect to region"; + return false; + } + r.Remove(destinyHandle); + } + } + else + { + r = null; + } + + Scene ascene = agent.Scene; + + if (!ascene.SimulationService.QueryAccess(destiny, agentID, position, out version, out reason)) + { + if (r == null) + { + r = new ExpiringCache(); + r.Add(destinyHandle, DateTime.Now + TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30)); + + m_bannedRegions.Add(agentID, r, TimeSpan.FromSeconds(30)); + } + else + { + r.Add(destinyHandle, DateTime.Now + TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30)); + } + return false; + } + return true; } - public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos, out string reason) + public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos) + { + string r = String.Empty; + return GetDestination(scene, agentID, pos, out version, out newpos, out r); + } + + public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos, out string reason) { version = String.Empty; reason = String.Empty; @@ -1400,9 +1448,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // m_log.DebugFormat( // "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); - uint neighbourx = scene.RegionInfo.RegionLocX; - uint neighboury = scene.RegionInfo.RegionLocY; + RegionInfo regInfo = scene.RegionInfo; + + uint neighbourx = regInfo.RegionLocX; + uint neighboury = regInfo.RegionLocY; const float boundaryDistance = 0.7f; + +/* Vector3 northCross = new Vector3(0, boundaryDistance, 0); Vector3 southCross = new Vector3(0, -1 * boundaryDistance, 0); Vector3 eastCross = new Vector3(boundaryDistance, 0, 0); @@ -1463,11 +1515,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer newpos.X = Util.Clamp(newpos.X, enterDistance, maxX); newpos.Y = Util.Clamp(newpos.Y, enterDistance, maxY); +*/ + float regionSizeX = regInfo.RegionSizeX; + float regionSizeY = regInfo.RegionSizeY; - xDest = neighbourx; - yDest = neighboury; + if (pos.X < boundaryDistance) + neighbourx--; + else if (pos.X > regionSizeX - boundaryDistance) + neighbourx += (uint)(regionSizeX / Constants.RegionSize); - int x = (int)(neighbourx * Constants.RegionSize), y = (int)(neighboury * Constants.RegionSize); + if (pos.Y < boundaryDistance) + neighboury--; + else if (pos.Y > regionSizeY - boundaryDistance) + neighboury += (uint)(regionSizeY / Constants.RegionSize); + + int x = (int)(neighbourx * Constants.RegionSize); + int y = (int)(neighboury * Constants.RegionSize); ulong neighbourHandle = Utils.UIntsToLong((uint)x, (uint)y); @@ -1489,6 +1552,28 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); + if (neighbourRegion == null) + { + reason = ""; + return null; + } + + float newRegionSizeX = neighbourRegion.RegionSizeX; + float newRegionSizeY = neighbourRegion.RegionSizeY; + + if (pos.X < boundaryDistance) + newpos.X += newRegionSizeX; + else if (pos.X > regionSizeX - boundaryDistance) + newpos.X -= regionSizeX; + + if (pos.Y < boundaryDistance) + newpos.Y += newRegionSizeY; + else if (pos.Y > regionSizeY - boundaryDistance) + newpos.Y -= regionSizeY; + + const float enterDistance = 0.5f; + newpos.X = Util.Clamp(newpos.X, enterDistance, newRegionSizeX - enterDistance); + newpos.Y = Util.Clamp(newpos.Y, enterDistance, newRegionSizeY - enterDistance); if (!scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out reason)) { @@ -1543,13 +1628,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer Vector3 pos = agent.AbsolutePosition + agent.Velocity; - GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, pos, out x, out y, out version, out newpos, out reason); + GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, pos, out version, out newpos, out reason); if (neighbourRegion == null) { - if (reason == String.Empty) + if (reason != String.Empty) agent.ControllingClient.SendAlertMessage("Cannot cross to region"); - else - agent.ControllingClient.SendAlertMessage("Cannot cross to region: " + reason); return agent; } @@ -2346,6 +2429,62 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer #region Object Transfers + public GridRegion GetObjectDestination(SceneObjectGroup grp, Vector3 targetPosition,out Vector3 newpos) + { + newpos = targetPosition; + + Scene scene = grp.Scene; + if (scene == null) + return null; + + RegionInfo srcRegionInfo = scene.RegionInfo; + int neighbourx = (int)srcRegionInfo.RegionLocX; + int neighboury = (int)srcRegionInfo.RegionLocY; + float regionSizeX = srcRegionInfo.RegionSizeX; + float regionSizeY = srcRegionInfo.RegionSizeY; + + float edgeJitter = 0.2f; + + if (targetPosition.X < edgeJitter) + neighbourx--; + else if (targetPosition.X > regionSizeX - edgeJitter) + neighbourx += (int)(regionSizeX / Constants.RegionSize); + + if (targetPosition.Y < edgeJitter) + neighboury--; + else if (targetPosition.Y > regionSizeY - edgeJitter) + neighboury += (int)(regionSizeY / Constants.RegionSize); + + int x = neighbourx * (int)Constants.RegionSize; + int y = neighboury * (int)Constants.RegionSize; + + GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); + if (neighbourRegion == null) + { + return null; + } + + float newRegionSizeX = neighbourRegion.RegionSizeX; + float newRegionSizeY = neighbourRegion.RegionSizeY; + + if (targetPosition.X < edgeJitter) + newpos.X += newRegionSizeX; + else if (targetPosition.X > regionSizeX - edgeJitter) + newpos.X -= regionSizeX; + + if (targetPosition.Y < edgeJitter) + newpos.Y += newRegionSizeY; + else if (targetPosition.Y > regionSizeY - edgeJitter) + newpos.Y -= regionSizeY; + + const float enterDistance = 0.2f; + newpos.X = Util.Clamp(newpos.X, enterDistance, newRegionSizeX - enterDistance); + newpos.Y = Util.Clamp(newpos.Y, enterDistance, newRegionSizeY - enterDistance); + + return neighbourRegion; + } + + /// /// Move the given scene object into a new region depending on which region its absolute position has moved /// into. @@ -2365,23 +2504,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (scene == null) return; -// http://wiki.secondlife.com/wiki/STATUS_DIE_AT_EDGE -// DieAtEdge does NOT mean that objects can't cross regions. -// It just means they die when they go off world, unless -// RETURN_AT_EDGE is set. -// if (grp.RootPart.DIE_AT_EDGE) -// { -// // We remove the object here -// try -// { -// scene.DeleteSceneObject(grp, false); -// } -// catch (Exception) -// { -// m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border."); -// } -// return; -// } int thisx = (int)scene.RegionInfo.RegionLocX; int thisy = (int)scene.RegionInfo.RegionLocY; @@ -2594,7 +2716,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer /// true if the crossing itself was successful, false on failure /// FIMXE: we still return true if the crossing object was not successfully deleted from the originating region /// - protected bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent) + public bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent) { //m_log.Debug(" >>> CrossPrimGroupIntoNewRegion <<<"); diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs index 0c34c90277..84cdc15348 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs @@ -93,9 +93,11 @@ namespace OpenSim.Region.Framework.Interfaces void EnableChildAgent(ScenePresence agent, GridRegion region); - GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos); - + GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos); + GridRegion GetObjectDestination(SceneObjectGroup grp, Vector3 targetPosition, out Vector3 newpos); + bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position, out string version, out string reason); void Cross(SceneObjectGroup sog, Vector3 position, bool silent); + bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent); ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 0eed64ef20..a7e7294f26 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -516,6 +516,10 @@ namespace OpenSim.Region.Framework.Scenes public uint ParentID; } + + public bool inTransit = false; + public delegate SceneObjectGroup SOGCrossDelegate(SceneObjectGroup sog,Vector3 pos); + /// /// The absolute position of this scene object in the scene /// @@ -525,8 +529,8 @@ namespace OpenSim.Region.Framework.Scenes set { Vector3 val = value; - - if (Scene != null) + + if (Scene != null && !inTransit) { if ( // (Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) @@ -543,130 +547,10 @@ 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.DIE_AT_EDGE || m_rootPart.RETURN_AT_EDGE) - { - // this should delete the grp in this case - m_scene.CrossPrimGroupIntoNewRegion(val, this, true); - // actually assume this sog was removed from simulation - return; - } - - if (m_rootPart.KeyframeMotion != null) - m_rootPart.KeyframeMotion.StartCrossingCheck(); - - 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); - // dont crash land StarShips - // val.Z = Util.Clamp(oldp.Z, 0.5f, 4096.0f); + inTransit = true; + SOGCrossDelegate d = CrossAsync; + d.BeginInvoke(this, val, CrossAsyncCompleted, d); + return; } } @@ -714,46 +598,197 @@ namespace OpenSim.Region.Framework.Scenes part.TriggerScriptChangedEvent(Changed.POSITION); } } - -/* - This seems not needed and should not be needed: - sp absolute position depends on sit part absolute position fixed above. - sp ParentPosition is not used anywhere. - Since presence is sitting, viewer considers it 'linked' to root prim, so it will move/rotate it - Sending a extra packet with avatar position is not only bandwidth waste, but may cause jitter in viewers due to UPD nature. - - if (!m_dupeInProgress) - { - foreach (ScenePresence av in m_linkedAvatars) - { - SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID); - if (p != null && m_parts.TryGetValue(p.UUID, out p)) - { - Vector3 offset = p.GetWorldPosition() - av.ParentPosition; - av.AbsolutePosition += offset; -// av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition - av.SendAvatarDataToAllAgents(); - } - } - } -*/ - //if (m_rootPart.PhysActor != null) - //{ - //m_rootPart.PhysActor.Position = - //new PhysicsVector(m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y, - //m_rootPart.GroupPosition.Z); - //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); - //} - - if (Scene != null) - Scene.EventManager.TriggerParcelPrimCountTainted(); + + Scene.EventManager.TriggerParcelPrimCountTainted(); } } - public override Vector3 Velocity + public SceneObjectGroup CrossAsync(SceneObjectGroup sog, Vector3 val) { - get { return RootPart.Velocity; } - set { RootPart.Velocity = value; } + Scene sogScene = sog.m_scene; + IEntityTransferModule entityTransfer = sogScene.RequestModuleInterface(); + + Vector3 newpos = Vector3.Zero; + OpenSim.Services.Interfaces.GridRegion destination = null; + + if (sog.RootPart.DIE_AT_EDGE) + { + try + { + sogScene.DeleteSceneObject(sog, false); + } + catch (Exception) + { + m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border."); + } + return sog; + } + + if (sog.RootPart.RETURN_AT_EDGE) + { + // We remove the object here + try + { + List localIDs = new List(); + localIDs.Add(sog.RootPart.LocalId); + sogScene.AddReturn(sog.OwnerID, sog.Name, sog.AbsolutePosition, + "Returned at region cross"); + sogScene.DeRezObjects(null, localIDs, UUID.Zero, DeRezAction.Return, UUID.Zero); + } + catch (Exception) + { + m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border."); + } + return sog; + } + + if (sog.m_rootPart.KeyframeMotion != null) + sog.m_rootPart.KeyframeMotion.StartCrossingCheck(); + + if (entityTransfer == null) + return sog; + + destination = entityTransfer.GetObjectDestination(sog, val, out newpos); + if (destination == null) + return sog; + + if (sog.m_linkedAvatars.Count == 0) + { + entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true); + return sog; + } + + string reason = String.Empty; + string version = String.Empty; + + foreach (ScenePresence av in sog.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(!entityTransfer.checkAgentAccessToRegion(av, destination, newpos, out version, out reason)) + { + return sog; + } + m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName); + } + + // We unparent the SP quietly so that it won't + // be made to stand up + + List avsToCross = new List(); + + foreach (ScenePresence av in sog.m_linkedAvatars) + { + avtocrossInfo avinfo = new avtocrossInfo(); + SceneObjectPart parentPart = sogScene.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; + } + + if (entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true)) + { + 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); + entityTransfer.CrossAgentToNewRegionAsync(av, newpos, destination, av.Flying, version); + if(av.IsChildAgent) + { + if (av.ParentUUID != UUID.Zero) + { + av.ClearControls(); + av.ParentPart = null; + } + } + av.ParentUUID = UUID.Zero; + // In any case + av.IsInTransit = false; + + m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", av.Firstname, av.Lastname); + } + else + m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar already in transit {0} to {1}", av.Name, val); + } + avsToCross.Clear(); + return sog; + } + else // cross failed, put avas back ?? + { + foreach (avtocrossInfo avinfo in avsToCross) + { + ScenePresence av = avinfo.av; + av.ParentUUID = UUID.Zero; + av.ParentID = avinfo.ParentID; + } + } + avsToCross.Clear(); + + return sog; + } + + public void CrossAsyncCompleted(IAsyncResult iar) + { + SOGCrossDelegate icon = (SOGCrossDelegate)iar.AsyncState; + SceneObjectGroup sog = icon.EndInvoke(iar); + + if (sog.IsDeleted) + { + sog.inTransit = false; // just in case... + } + else + { + SceneObjectPart rootp = sog.m_rootPart; + Vector3 oldp = rootp.GroupPosition; + oldp.X = Util.Clamp(oldp.X, 0.5f, sog.m_scene.RegionInfo.RegionSizeX - 0.5f); + oldp.Y = Util.Clamp(oldp.Y, 0.5f, sog.m_scene.RegionInfo.RegionSizeY - 0.5f); + rootp.GroupPosition = oldp; + + SceneObjectPart[] parts = sog.m_parts.GetArray(); + + foreach (SceneObjectPart part in parts) + { + if (part != rootp) + part.GroupPosition = oldp; + } + + foreach (ScenePresence av in sog.m_linkedAvatars) + { + av.sitSOGmoved(); + } + + sog.Velocity = Vector3.Zero; + + if (sog.m_rootPart.KeyframeMotion != null) + sog.m_rootPart.KeyframeMotion.CrossingFailure(); + + if (sog.RootPart.PhysActor != null) + { + sog.RootPart.PhysActor.CrossingFailure(); + } + + sog.inTransit = false; + sog.ScheduleGroupForFullUpdate(); + } } private void CrossAgentToNewRegionCompleted(IAsyncResult iar) @@ -784,6 +819,12 @@ namespace OpenSim.Region.Framework.Scenes m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); } + public override Vector3 Velocity + { + get { return RootPart.Velocity; } + set { RootPart.Velocity = value; } + } + public override uint LocalId { get { return m_rootPart.LocalId; } @@ -2620,7 +2661,7 @@ namespace OpenSim.Region.Framework.Scenes // an object has been deleted from a scene before update was processed. // A more fundamental overhaul of the update mechanism is required to eliminate all // the race conditions. - if (IsDeleted) + if (IsDeleted || inTransit) return; // Even temporary objects take part in physics (e.g. temp-on-rez bullets) @@ -2736,7 +2777,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendGroupRootTerseUpdate() { - if (IsDeleted) + if (IsDeleted || inTransit) return; RootPart.SendTerseUpdateToAllClients(); @@ -2755,7 +2796,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendGroupTerseUpdate() { - if (IsDeleted) + if (IsDeleted || inTransit) return; if (IsAttachment) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 4cc4d94f40..56c3b5213c 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1123,6 +1123,11 @@ namespace OpenSim.Region.Framework.Scenes if (part == null) { m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); + ParentID = 0; + ParentPart = null; + PrevSitOffset = Vector3.Zero; + ClearControls(); + IsLoggingIn = false; } else { @@ -1216,13 +1221,6 @@ namespace OpenSim.Region.Framework.Scenes else AddToPhysicalScene(isFlying); - // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a - // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it - // since it requires a physics actor to be present. If it is left any later, then physics appears to reset - // the value to a negative position which does not trigger the border cross. - // This may not be the best location for this. - CheckForBorderCrossing(); - if (ForceFly) { Flying = true; @@ -1231,12 +1229,18 @@ namespace OpenSim.Region.Framework.Scenes { Flying = false; } - } - // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying - // avatar to return to the standing position in mid-air. On login it looks like this is being sent - // elsewhere anyway - // Animator.SendAnimPack(); + // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a + // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it + // since it requires a physics actor to be present. If it is left any later, then physics appears to reset + // the value to a negative position which does not trigger the border cross. + // This may not be the best location for this. + + + // its not +// CheckForBorderCrossing(); + } + m_log.DebugFormat("[MakeRootAgent] position and physical: {0}ms", Util.EnvironmentTickCountSubtract(ts)); m_scene.SwapRootAgentCount(false); @@ -2734,7 +2738,6 @@ namespace OpenSim.Region.Framework.Scenes ParentID = 0; ParentPart = null; - if (part.SitTargetAvatar == UUID) standRotation = standRotation * part.SitTargetOrientation; else @@ -2761,12 +2764,6 @@ namespace OpenSim.Region.Framework.Scenes Vector3 standPos = sitPartWorldPosition + adjustmentForSitPose; -// m_log.DebugFormat( -// "[SCENE PRESENCE]: Setting stand to pos {0}, (adjustmentForSitPosition {1}, adjustmentForSitPose {2}) rotation {3} for {4} in {5}", -// standPos, adjustmentForSitPosition, adjustmentForSitPose, standRotation, Name, Scene.Name); - - standPos.X = Util.Clamp(standPos.X, 0.5f, (float)Constants.RegionSize - 0.5f); - standPos.Y = Util.Clamp(standPos.Y, 0.5f, (float)Constants.RegionSize - 0.5f); m_pos = standPos; } @@ -3308,6 +3305,8 @@ namespace OpenSim.Region.Framework.Scenes if (IsChildAgent == false) { + CheckForBorderCrossing(); + if (IsInTransit) return; @@ -3329,8 +3328,6 @@ namespace OpenSim.Region.Framework.Scenes m_lastVelocity = Velocity; } - CheckForBorderCrossing(); - CheckForSignificantMovement(); // sends update to the modules. } } @@ -3847,7 +3844,7 @@ namespace OpenSim.Region.Framework.Scenes protected void CheckForBorderCrossing() { // Check that we we are not a child - if (IsChildAgent) + if (IsChildAgent || IsInTransit) return; // If we don't have a PhysActor, we can't cross anyway @@ -3857,25 +3854,22 @@ namespace OpenSim.Region.Framework.Scenes if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero) return; - if (IsInTransit) - return; - Vector3 pos2 = AbsolutePosition; Vector3 vel = Velocity; - int neighbor = 0; - int[] fix = new int[2]; float timeStep = 0.1f; - pos2.X = pos2.X + (vel.X * timeStep); - pos2.Y = pos2.Y + (vel.Y * timeStep); - pos2.Z = pos2.Z + (vel.Z * timeStep); - + pos2.X += vel.X * timeStep; + pos2.Y += vel.Y * timeStep; + pos2.Z += vel.Z * timeStep; // m_log.DebugFormat( // "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}", // pos2, Name, Scene.Name); - +/* // Checks if where it's headed exists a region + int neighbor = 0; + int[] fix = new int[2]; + bool needsTransit = false; if (m_scene.TestBorderCross(pos2, Cardinals.W)) { @@ -3925,59 +3919,55 @@ namespace OpenSim.Region.Framework.Scenes } // Makes sure avatar does not end up outside region + if (neighbor <= 0) { if (needsTransit) { - if (m_requestedSitTargetUUID == UUID.Zero) - { - bool isFlying = Flying; - RemoveFromPhysicalScene(); - - Vector3 pos = AbsolutePosition; - if (AbsolutePosition.X < 0) - pos.X += Velocity.X * 2; - else if (AbsolutePosition.X > Constants.RegionSize) - pos.X -= Velocity.X * 2; - if (AbsolutePosition.Y < 0) - pos.Y += Velocity.Y * 2; - else if (AbsolutePosition.Y > Constants.RegionSize) - pos.Y -= Velocity.Y * 2; - Velocity = Vector3.Zero; - AbsolutePosition = pos; - - // m_log.DebugFormat("[SCENE PRESENCE]: Prevented flyoff for {0} at {1}", Name, AbsolutePosition); - - AddToPhysicalScene(isFlying); - } + CrossToNewRegionFail(); } } else if (neighbor > 0) { if (!CrossToNewRegion()) { - if (m_requestedSitTargetUUID == UUID.Zero) - { - bool isFlying = Flying; - RemoveFromPhysicalScene(); - - Vector3 pos = AbsolutePosition; - if (AbsolutePosition.X < 0) - pos.X += Velocity.X * 2; - else if (AbsolutePosition.X > Constants.RegionSize) - pos.X -= Velocity.X * 2; - if (AbsolutePosition.Y < 0) - pos.Y += Velocity.Y * 2; - else if (AbsolutePosition.Y > Constants.RegionSize) - pos.Y -= Velocity.Y * 2; - Velocity = Vector3.Zero; - AbsolutePosition = pos; - - AddToPhysicalScene(isFlying); - } + CrossToNewRegionFail(); } } + */ + bool needsTransit = false; + if (pos2.X < 0) + needsTransit = true; + else if (pos2.X > m_scene.RegionInfo.RegionSizeX) + needsTransit = true; + else if (pos2.Y < 0) + needsTransit = true; + else if (pos2.Y > m_scene.RegionInfo.RegionSizeY) + needsTransit = true; + + if (needsTransit) + { + if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero) + { + // we don't have entity transfer module + Vector3 pos = AbsolutePosition; + float px = pos.X; + if (px < 0) + pos.X += Velocity.X * 2; + else if (px > m_scene.RegionInfo.RegionSizeX) + pos.X -= Velocity.X * 2; + + float py = pos.Y; + if (py < 0) + pos.Y += Velocity.Y * 2; + else if (py > m_scene.RegionInfo.RegionSizeY) + pos.Y -= Velocity.Y * 2; + + Velocity = Vector3.Zero; + AbsolutePosition = pos; + } + } } public void CrossToNewRegionFail() @@ -3988,14 +3978,18 @@ namespace OpenSim.Region.Framework.Scenes RemoveFromPhysicalScene(); Vector3 pos = AbsolutePosition; - if (AbsolutePosition.X < 0) + float px = pos.X; + if (px < 0) pos.X += Velocity.X * 2; - else if (AbsolutePosition.X > Constants.RegionSize) + else if (px > m_scene.RegionInfo.RegionSizeX) pos.X -= Velocity.X * 2; - if (AbsolutePosition.Y < 0) + + float py = pos.Y; + if (py < 0) pos.Y += Velocity.Y * 2; - else if (AbsolutePosition.Y > Constants.RegionSize) + else if (py > m_scene.RegionInfo.RegionSizeY) pos.Y -= Velocity.Y * 2; + Velocity = Vector3.Zero; AbsolutePosition = pos;