diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 9a6dfe124e..557555dbc3 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -1655,35 +1655,38 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } // Offset the positions for the new region across the border - Vector3 oldGroupPosition = grp.RootPart.GroupPosition; - grp.RootPart.GroupPosition = pos; + // NOT here // If we fail to cross the border, then reset the position of the scene object on that border. uint x = 0, y = 0; Utils.LongToUInts(newRegionHandle, out x, out y); GridRegion destination = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); - if (destination == null || !CrossPrimGroupIntoNewRegion(destination, grp, silent)) + Vector3 oldGroupPosition = grp.RootPart.GroupPosition; + + if (destination != null) { - m_log.InfoFormat("[ENTITY TRANSFER MODULE] cross region transfer failed for object {0}",grp.UUID); - - // Need to turn off the physics flags, otherwise the object will continue to attempt to - // move out of the region creating an infinite loop of failed attempts to cross - grp.UpdatePrimFlags(grp.RootPart.LocalId,false,grp.IsTemporary,grp.IsPhantom,false); - - // We are going to move the object back to the old position so long as the old position - // is in the region - oldGroupPosition.X = Util.Clamp(oldGroupPosition.X,1.0f,(float)Constants.RegionSize-1); - oldGroupPosition.Y = Util.Clamp(oldGroupPosition.Y,1.0f,(float)Constants.RegionSize-1); - oldGroupPosition.Z = Util.Clamp(oldGroupPosition.Z,1.0f,4096.0f); - - grp.AbsolutePosition = oldGroupPosition; - - grp.ScheduleGroupForFullUpdate(); + grp.RootPart.GroupPosition = pos; // only change this if we think there is anywhere to go + if (CrossPrimGroupIntoNewRegion(destination, grp, silent)) + return; // we did it } + + // no one or failed lets go back and tell physics to go on + oldGroupPosition.X = Util.Clamp(oldGroupPosition.X, 0.5f, (float)Constants.RegionSize - 0.5f); + oldGroupPosition.Y = Util.Clamp(oldGroupPosition.Y, 0.5f, (float)Constants.RegionSize - 0.5f); + oldGroupPosition.Z = Util.Clamp(oldGroupPosition.Z, 0.5f, 4096.0f); + + grp.AbsolutePosition = oldGroupPosition; + grp.Velocity = Vector3.Zero; + + if (grp.RootPart.PhysActor != null) + grp.RootPart.PhysActor.CrossingFailure(); + + grp.ScheduleGroupForFullUpdate(); } + /// /// Move the given scene object into a new region /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 644b78a4ec..77e67ba183 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -461,8 +461,11 @@ namespace OpenSim.Region.Framework.Scenes if (Scene != null) { - if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) - || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) + // if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) + // || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) + // && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) + if ((Scene.TestBorderCross(val, Cardinals.E) || Scene.TestBorderCross(val, Cardinals.W) + || Scene.TestBorderCross(val, Cardinals.N) || Scene.TestBorderCross(val, Cardinals.S)) && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) { IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface(); @@ -489,7 +492,7 @@ namespace OpenSim.Region.Framework.Scenes canCross = false; break; } - + m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName); } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 577c0d3f7b..19deddeee1 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2620,9 +2620,9 @@ namespace OpenSim.Region.Framework.Scenes Vector3 newpos = new Vector3(PhysActor.Position.GetBytes(), 0); if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) - | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) - | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E) - | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) + || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) + || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E) + || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) { ParentGroup.AbsolutePosition = newpos; return; diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 42e22ffb52..95a97415ab 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -732,13 +732,13 @@ namespace OpenSim.Region.Physics.OdePlugin public override void CrossingFailure() { - m_crossingfailures++; - if (m_crossingfailures > _parent_scene.geomCrossingFailuresBeforeOutofbounds) + int tmp = Interlocked.Increment(ref m_crossingfailures); + if (tmp > _parent_scene.geomCrossingFailuresBeforeOutofbounds) { base.RaiseOutOfBounds(_position); return; } - else if (m_crossingfailures == _parent_scene.geomCrossingFailuresBeforeOutofbounds) + else if (tmp == _parent_scene.geomCrossingFailuresBeforeOutofbounds) { m_log.Warn("[PHYSICS]: Too many crossing failures for: " + m_primName); } @@ -3042,10 +3042,9 @@ Console.WriteLine("ODEPrim JointCreateFixed !!!"); d.Vector3 torque = d.BodyGetTorque(Body); _torque = new Vector3(torque.X, torque.Y, torque.Z); - base.RequestPhysicsterseUpdate(); //Console.WriteLine("Move {0} at {1}", m_primName, l_position); - + /* // Check if outside region // In Scene.cs/CrossPrimGroupIntoNewRegion the object is checked for 0.1M from border! if (l_position.X > ((float)_parent_scene.WorldExtents.X - fence)) @@ -3112,7 +3111,52 @@ Console.WriteLine("ODEPrim JointCreateFixed !!!"); return; // Dont process any other motion? } // end various methods } // end outside region horizontally - + */ + if (_position.X < 0f || _position.X > _parent_scene.WorldExtents.X + || _position.Y < 0f || _position.Y > _parent_scene.WorldExtents.Y + ) + { + // we are outside current region + // clip position to a stop just outside region and stop it only internally + // do it only once using m_crossingfailures as control + _position.X = Util.Clip(l_position.X, -0.2f, _parent_scene.WorldExtents.X + .2f); + _position.Y = Util.Clip(l_position.Y, -0.2f, _parent_scene.WorldExtents.Y + .2f); + _position.Z = Util.Clip(l_position.Z, -100f, 50000f); + d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); + d.BodySetLinearVel(Body, 0, 0, 0); + + if (Interlocked.Exchange(ref m_crossingfailures, 0) == 0) + { // tell base code only once + Interlocked.Increment(ref m_crossingfailures); + base.RequestPhysicsterseUpdate(); + } + return; + } + + if (Interlocked.Exchange(ref m_crossingfailures, 0) > 1) + { + // main simulator had a crossing failure + // park it inside region + _position.X = Util.Clip(l_position.X, 0.5f, _parent_scene.WorldExtents.X - 0.5f); + _position.Y = Util.Clip(l_position.Y, 0.5f, _parent_scene.WorldExtents.Y - 0.5f); + _position.Z = Util.Clip(l_position.Z, -100f, 50000f); + d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); + + m_lastposition = _position; + + _velocity = Vector3.Zero; + m_lastVelocity = _velocity; + + + if (m_type != Vehicle.TYPE_NONE) + Halt(); + + d.BodySetLinearVel(Body, 0, 0, 0); + base.RequestPhysicsterseUpdate(); + return; + } + + base.RequestPhysicsterseUpdate(); if (l_position.Z < 0) {