try to make SOG crossings full async. Simplify some borders checking....

avinationmerge
UbitUmarov 2014-10-24 18:10:28 +01:00
parent fd79f75ba6
commit 4571e5bc3e
5 changed files with 434 additions and 275 deletions

View File

@ -3865,7 +3865,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
SceneObjectPart part = (SceneObjectPart)update.Entity; SceneObjectPart part = (SceneObjectPart)update.Entity;
if (part.ParentGroup.IsDeleted) if (part.ParentGroup.IsDeleted || part.ParentGroup.inTransit)
continue; continue;
if (part.ParentGroup.IsAttachment) if (part.ParentGroup.IsAttachment)

View File

@ -1385,13 +1385,61 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
#region Agent Crossings #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; reason = String.Empty;
return GetDestination(scene, agentID, pos, out xDest, out yDest, out version, out newpos, out r); version = String.Empty;
UUID agentID = agent.UUID;
ulong destinyHandle = destiny.RegionHandle;
ExpiringCache<ulong, DateTime> 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<ulong, DateTime>();
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; version = String.Empty;
reason = String.Empty; reason = String.Empty;
@ -1400,9 +1448,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// m_log.DebugFormat( // m_log.DebugFormat(
// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); // "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
uint neighbourx = scene.RegionInfo.RegionLocX; RegionInfo regInfo = scene.RegionInfo;
uint neighboury = scene.RegionInfo.RegionLocY;
uint neighbourx = regInfo.RegionLocX;
uint neighboury = regInfo.RegionLocY;
const float boundaryDistance = 0.7f; const float boundaryDistance = 0.7f;
/*
Vector3 northCross = new Vector3(0, boundaryDistance, 0); Vector3 northCross = new Vector3(0, boundaryDistance, 0);
Vector3 southCross = new Vector3(0, -1 * boundaryDistance, 0); Vector3 southCross = new Vector3(0, -1 * boundaryDistance, 0);
Vector3 eastCross = new Vector3(boundaryDistance, 0, 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.X = Util.Clamp(newpos.X, enterDistance, maxX);
newpos.Y = Util.Clamp(newpos.Y, enterDistance, maxY); newpos.Y = Util.Clamp(newpos.Y, enterDistance, maxY);
*/
float regionSizeX = regInfo.RegionSizeX;
float regionSizeY = regInfo.RegionSizeY;
xDest = neighbourx; if (pos.X < boundaryDistance)
yDest = neighboury; 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); 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); 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)) 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; 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 (neighbourRegion == null)
{ {
if (reason == String.Empty) if (reason != String.Empty)
agent.ControllingClient.SendAlertMessage("Cannot cross to region"); agent.ControllingClient.SendAlertMessage("Cannot cross to region");
else
agent.ControllingClient.SendAlertMessage("Cannot cross to region: " + reason);
return agent; return agent;
} }
@ -2346,6 +2429,62 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
#region Object Transfers #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;
}
/// <summary> /// <summary>
/// Move the given scene object into a new region depending on which region its absolute position has moved /// Move the given scene object into a new region depending on which region its absolute position has moved
/// into. /// into.
@ -2365,23 +2504,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (scene == null) if (scene == null)
return; 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 thisx = (int)scene.RegionInfo.RegionLocX;
int thisy = (int)scene.RegionInfo.RegionLocY; 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 /// 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 /// FIMXE: we still return true if the crossing object was not successfully deleted from the originating region
/// </returns> /// </returns>
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 <<<"); //m_log.Debug(" >>> CrossPrimGroupIntoNewRegion <<<");

View File

@ -93,9 +93,11 @@ namespace OpenSim.Region.Framework.Interfaces
void EnableChildAgent(ScenePresence agent, GridRegion region); 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); 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); ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version);

View File

@ -516,6 +516,10 @@ namespace OpenSim.Region.Framework.Scenes
public uint ParentID; public uint ParentID;
} }
public bool inTransit = false;
public delegate SceneObjectGroup SOGCrossDelegate(SceneObjectGroup sog,Vector3 pos);
/// <summary> /// <summary>
/// The absolute position of this scene object in the scene /// The absolute position of this scene object in the scene
/// </summary> /// </summary>
@ -525,8 +529,8 @@ namespace OpenSim.Region.Framework.Scenes
set set
{ {
Vector3 val = value; Vector3 val = value;
if (Scene != null) if (Scene != null && !inTransit)
{ {
if ( if (
// (Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) // (Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E)
@ -543,130 +547,10 @@ namespace OpenSim.Region.Framework.Scenes
|| Scene.TestBorderCross(val, Cardinals.S)) || Scene.TestBorderCross(val, Cardinals.S))
&& !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
{ {
IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); inTransit = true;
uint x = 0; SOGCrossDelegate d = CrossAsync;
uint y = 0; d.BeginInvoke(this, val, CrossAsyncCompleted, d);
string version = String.Empty; return;
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<avtocrossInfo> avsToCross = new List<avtocrossInfo>();
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<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f);
val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
// dont crash land StarShips
// val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f);
} }
} }
@ -714,46 +598,197 @@ namespace OpenSim.Region.Framework.Scenes
part.TriggerScriptChangedEvent(Changed.POSITION); part.TriggerScriptChangedEvent(Changed.POSITION);
} }
} }
/* Scene.EventManager.TriggerParcelPrimCountTainted();
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();
} }
} }
public override Vector3 Velocity public SceneObjectGroup CrossAsync(SceneObjectGroup sog, Vector3 val)
{ {
get { return RootPart.Velocity; } Scene sogScene = sog.m_scene;
set { RootPart.Velocity = value; } IEntityTransferModule entityTransfer = sogScene.RequestModuleInterface<IEntityTransferModule>();
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<uint> localIDs = new List<uint>();
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<avtocrossInfo> avsToCross = new List<avtocrossInfo>();
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<float>(oldp.X, 0.5f, sog.m_scene.RegionInfo.RegionSizeX - 0.5f);
oldp.Y = Util.Clamp<float>(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) 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); 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 public override uint LocalId
{ {
get { return m_rootPart.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. // 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 // A more fundamental overhaul of the update mechanism is required to eliminate all
// the race conditions. // the race conditions.
if (IsDeleted) if (IsDeleted || inTransit)
return; return;
// Even temporary objects take part in physics (e.g. temp-on-rez bullets) // Even temporary objects take part in physics (e.g. temp-on-rez bullets)
@ -2736,7 +2777,7 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
public void SendGroupRootTerseUpdate() public void SendGroupRootTerseUpdate()
{ {
if (IsDeleted) if (IsDeleted || inTransit)
return; return;
RootPart.SendTerseUpdateToAllClients(); RootPart.SendTerseUpdateToAllClients();
@ -2755,7 +2796,7 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
public void SendGroupTerseUpdate() public void SendGroupTerseUpdate()
{ {
if (IsDeleted) if (IsDeleted || inTransit)
return; return;
if (IsAttachment) if (IsAttachment)

View File

@ -1123,6 +1123,11 @@ namespace OpenSim.Region.Framework.Scenes
if (part == null) if (part == null)
{ {
m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); 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 else
{ {
@ -1216,13 +1221,6 @@ namespace OpenSim.Region.Framework.Scenes
else else
AddToPhysicalScene(isFlying); 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) if (ForceFly)
{ {
Flying = true; Flying = true;
@ -1231,12 +1229,18 @@ namespace OpenSim.Region.Framework.Scenes
{ {
Flying = false; 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_log.DebugFormat("[MakeRootAgent] position and physical: {0}ms", Util.EnvironmentTickCountSubtract(ts));
m_scene.SwapRootAgentCount(false); m_scene.SwapRootAgentCount(false);
@ -2734,7 +2738,6 @@ namespace OpenSim.Region.Framework.Scenes
ParentID = 0; ParentID = 0;
ParentPart = null; ParentPart = null;
if (part.SitTargetAvatar == UUID) if (part.SitTargetAvatar == UUID)
standRotation = standRotation * part.SitTargetOrientation; standRotation = standRotation * part.SitTargetOrientation;
else else
@ -2761,12 +2764,6 @@ namespace OpenSim.Region.Framework.Scenes
Vector3 standPos = sitPartWorldPosition + adjustmentForSitPose; 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<float>(standPos.X, 0.5f, (float)Constants.RegionSize - 0.5f);
standPos.Y = Util.Clamp<float>(standPos.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
m_pos = standPos; m_pos = standPos;
} }
@ -3308,6 +3305,8 @@ namespace OpenSim.Region.Framework.Scenes
if (IsChildAgent == false) if (IsChildAgent == false)
{ {
CheckForBorderCrossing();
if (IsInTransit) if (IsInTransit)
return; return;
@ -3329,8 +3328,6 @@ namespace OpenSim.Region.Framework.Scenes
m_lastVelocity = Velocity; m_lastVelocity = Velocity;
} }
CheckForBorderCrossing();
CheckForSignificantMovement(); // sends update to the modules. CheckForSignificantMovement(); // sends update to the modules.
} }
} }
@ -3847,7 +3844,7 @@ namespace OpenSim.Region.Framework.Scenes
protected void CheckForBorderCrossing() protected void CheckForBorderCrossing()
{ {
// Check that we we are not a child // Check that we we are not a child
if (IsChildAgent) if (IsChildAgent || IsInTransit)
return; return;
// If we don't have a PhysActor, we can't cross anyway // 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) if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero)
return; return;
if (IsInTransit)
return;
Vector3 pos2 = AbsolutePosition; Vector3 pos2 = AbsolutePosition;
Vector3 vel = Velocity; Vector3 vel = Velocity;
int neighbor = 0;
int[] fix = new int[2];
float timeStep = 0.1f; float timeStep = 0.1f;
pos2.X = pos2.X + (vel.X * timeStep); pos2.X += vel.X * timeStep;
pos2.Y = pos2.Y + (vel.Y * timeStep); pos2.Y += vel.Y * timeStep;
pos2.Z = pos2.Z + (vel.Z * timeStep); pos2.Z += vel.Z * timeStep;
// m_log.DebugFormat( // m_log.DebugFormat(
// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}", // "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
// pos2, Name, Scene.Name); // pos2, Name, Scene.Name);
/*
// Checks if where it's headed exists a region // Checks if where it's headed exists a region
int neighbor = 0;
int[] fix = new int[2];
bool needsTransit = false; bool needsTransit = false;
if (m_scene.TestBorderCross(pos2, Cardinals.W)) 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 // Makes sure avatar does not end up outside region
if (neighbor <= 0) if (neighbor <= 0)
{ {
if (needsTransit) if (needsTransit)
{ {
if (m_requestedSitTargetUUID == UUID.Zero) CrossToNewRegionFail();
{
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);
}
} }
} }
else if (neighbor > 0) else if (neighbor > 0)
{ {
if (!CrossToNewRegion()) if (!CrossToNewRegion())
{ {
if (m_requestedSitTargetUUID == UUID.Zero) CrossToNewRegionFail();
{
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);
}
} }
} }
*/
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() public void CrossToNewRegionFail()
@ -3988,14 +3978,18 @@ namespace OpenSim.Region.Framework.Scenes
RemoveFromPhysicalScene(); RemoveFromPhysicalScene();
Vector3 pos = AbsolutePosition; Vector3 pos = AbsolutePosition;
if (AbsolutePosition.X < 0) float px = pos.X;
if (px < 0)
pos.X += Velocity.X * 2; pos.X += Velocity.X * 2;
else if (AbsolutePosition.X > Constants.RegionSize) else if (px > m_scene.RegionInfo.RegionSizeX)
pos.X -= Velocity.X * 2; pos.X -= Velocity.X * 2;
if (AbsolutePosition.Y < 0)
float py = pos.Y;
if (py < 0)
pos.Y += Velocity.Y * 2; pos.Y += Velocity.Y * 2;
else if (AbsolutePosition.Y > Constants.RegionSize) else if (py > m_scene.RegionInfo.RegionSizeY)
pos.Y -= Velocity.Y * 2; pos.Y -= Velocity.Y * 2;
Velocity = Vector3.Zero; Velocity = Vector3.Zero;
AbsolutePosition = pos; AbsolutePosition = pos;