From f6f0d884bda8b5179d04a9cfe15efa3908552bcc Mon Sep 17 00:00:00 2001
From: UbitUmarov
Date: Wed, 15 Feb 2012 17:08:33 +0000
Subject:  try to make crossings work better. chode no longer prevents
 crossings i hope

---
 .../EntityTransfer/EntityTransferModule.cs         | 33 +++++++------
 .../Region/Framework/Scenes/SceneObjectGroup.cs    |  9 ++--
 OpenSim/Region/Framework/Scenes/SceneObjectPart.cs |  6 +--
 OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs      | 56 +++++++++++++++++++---
 4 files changed, 77 insertions(+), 27 deletions(-)

diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 9a6dfe1..557555d 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);
+                grp.RootPart.GroupPosition = pos; // only change this if we think there is anywhere to go
+                if (CrossPrimGroupIntoNewRegion(destination, grp, silent))
+                    return; // we did it
+            }
 
-                // 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);
+            // no one or failed lets go back and tell physics to go on
+            oldGroupPosition.X = Util.Clamp<float>(oldGroupPosition.X, 0.5f, (float)Constants.RegionSize - 0.5f);
+            oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
+            oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z, 0.5f, 4096.0f);
 
-                // 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<float>(oldGroupPosition.X,1.0f,(float)Constants.RegionSize-1);
-                oldGroupPosition.Y = Util.Clamp<float>(oldGroupPosition.Y,1.0f,(float)Constants.RegionSize-1);
-                oldGroupPosition.Z = Util.Clamp<float>(oldGroupPosition.Z,1.0f,4096.0f);
+            grp.AbsolutePosition = oldGroupPosition;
+            grp.Velocity = Vector3.Zero;
 
-                grp.AbsolutePosition = oldGroupPosition;
+            if (grp.RootPart.PhysActor != null)
+                grp.RootPart.PhysActor.CrossingFailure();
 
-                grp.ScheduleGroupForFullUpdate();
-            }
+            grp.ScheduleGroupForFullUpdate();
         }
 
 
+
         /// <summary>
         /// Move the given scene object into a new region
         /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index a4ca0fb..d964a6f 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<IEntityTransferModule>();
@@ -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 ac39b6b..f9e61be 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -2612,9 +2612,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 42e22ff..95a9741 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)
                 {
-- 
cgit v1.1